1use std::fs::OpenOptions;
2use std::os::unix::fs::PermissionsExt;
3use std::path::Path;
4use std::path::PathBuf;
5
6use serde::Deserialize;
7use serde::Serialize;
8
9use crate::pgpass::PgpassEntry;
10
11pub fn save_new_nvim_dbee_conns_file(updated_pg_pass_entry: &PgpassEntry, conns_path: &Path) -> rootcause::Result<()> {
17 let conns = get_updated_conns(updated_pg_pass_entry, conns_path)?;
18
19 let mut tmp_path = PathBuf::from(conns_path);
20 tmp_path.set_file_name("conns.json.tmp");
21 std::fs::write(&tmp_path, serde_json::to_string(&conns)?)?;
22 std::fs::rename(&tmp_path, conns_path)?;
23
24 let file = OpenOptions::new().read(true).open(conns_path)?;
25 let mut permissions = file.metadata()?.permissions();
26 permissions.set_mode(0o600);
27 file.set_permissions(permissions)?;
28
29 Ok(())
30}
31
32fn get_updated_conns(updated_pg_pass_entry: &PgpassEntry, conns_path: &Path) -> rootcause::Result<Vec<NvimDbeeConn>> {
38 let updated_conn = NvimDbeeConn::from(updated_pg_pass_entry);
39
40 if !conns_path.try_exists()? {
42 return Ok(vec![updated_conn]);
43 }
44
45 let conns_file_content = std::fs::read_to_string(conns_path)?;
46 if conns_file_content.is_empty() {
48 return Ok(vec![updated_conn]);
49 }
50
51 let mut conns: Vec<NvimDbeeConn> = serde_json::from_str(&conns_file_content)?;
53 let mut seen = false;
54 for conn in &mut conns {
55 if conn.name == updated_conn.name {
56 conn.url = updated_pg_pass_entry.connection_params.db_url();
57 seen = true;
58 }
59 }
60 if !seen {
61 conns.push(updated_conn);
62 }
63 Ok(conns)
64}
65
66#[derive(Clone, Debug, Deserialize, Serialize)]
67struct NvimDbeeConn {
68 id: String,
69 name: String,
70 r#type: String,
71 url: String,
72}
73
74impl From<&PgpassEntry> for NvimDbeeConn {
75 fn from(value: &PgpassEntry) -> Self {
76 Self {
77 id: value.metadata.alias.clone(),
78 name: value.metadata.alias.clone(),
79 url: value.connection_params.db_url(),
80 r#type: "postgres".to_string(),
81 }
82 }
83}