From fc4d0c2b3b306a35d33d185cc6c78eec5f8ad6b1 Mon Sep 17 00:00:00 2001 From: postscriptum Date: Sat, 5 Jul 2025 23:26:14 +0300 Subject: [PATCH] init `filesystem-dir-permissions` option --- README.md | 3 +++ src/config.rs | 6 ++++++ src/nex.rs | 45 ++++++++++++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index fb99c77..242d61c 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,9 @@ snac2nex -s /path/to/snac/storage -t /path/to/nex -u user1 -u user2 --filesystem-sync-time Sync file meta with Snac entry time (e.g. time modified) + --filesystem-dir-permissions + Set new directory permissions (macos, linux only) + --filesystem-file-permissions Set new file permissions (macos, linux only) diff --git a/src/config.rs b/src/config.rs index 78b7efb..8904634 100644 --- a/src/config.rs +++ b/src/config.rs @@ -52,6 +52,10 @@ pub struct Config { #[arg(long, default_value_t = false)] pub filesystem_sync_time: bool, + /// Set new directory permissions (macos, linux only) + #[arg(long, value_parser = permissions)] + pub filesystem_dir_permissions: Option, + /// Set new file permissions (macos, linux only) #[arg(long, value_parser = permissions)] pub filesystem_file_permissions: Option, @@ -78,7 +82,9 @@ fn test() { "cmd", "--source=p", "--target=p", + "--filesystem-dir-permissions=0755", "--filesystem-file-permissions=0644", ]); + assert!(a.filesystem_dir_permissions.is_some_and(|p| p == 0o755)); assert!(a.filesystem_file_permissions.is_some_and(|p| p == 0o644)) } diff --git a/src/nex.rs b/src/nex.rs index 0b92fd5..202f918 100644 --- a/src/nex.rs +++ b/src/nex.rs @@ -18,6 +18,7 @@ use template::Template; pub struct Nex { attachment: Attachment, + dir_permissions: Option, file_permissions: Option, filename: String, is_cleanup: bool, @@ -42,12 +43,18 @@ impl Nex { if !target.is_dir() { bail!("Target location is not directory!") } + // init permissions + let dir_permissions = permissions(config.filesystem_dir_permissions, 0o755); + let file_permissions = permissions(config.filesystem_file_permissions, 0o644); // init locations for each user let mut users = HashMap::with_capacity(config.user.len()); for u in &config.user { let mut p = PathBuf::from(&target); p.push(u); fs::create_dir_all(&p)?; + if let Some(ref permissions) = dir_permissions { + fs::set_permissions(&p, permissions.clone())? + } users.insert(u.clone(), p); } // init document template formatter @@ -55,19 +62,8 @@ impl Nex { Ok(Self { attachment: Attachment::init(config.attachment.as_ref())?, - file_permissions: { - #[cfg(any(target_os = "linux", target_os = "macos"))] - { - use std::{fs::Permissions, os::unix::fs::PermissionsExt}; - Some(Permissions::from_mode( - config.filesystem_file_permissions.unwrap_or(0o644), - )) - } - #[cfg(not(any(target_os = "linux", target_os = "macos",)))] - { - None // @TODO - } - }, + dir_permissions, + file_permissions, filename: config.format_filename.clone(), is_cleanup: !config.keep, is_debug: !config.daemon, @@ -117,6 +113,9 @@ impl Nex { } fs::create_dir_all(&p)?; + if let Some(ref permissions) = self.dir_permissions { + fs::set_permissions(&p, permissions.clone())? + } // init shared post ID once let id = published @@ -133,6 +132,9 @@ impl Nex { let mut d = PathBuf::from(&p); d.push(format!(".{id}")); fs::create_dir_all(&d)?; + if let Some(ref permissions) = self.dir_permissions { + fs::set_permissions(&p, permissions.clone())? + } // create system meta file to track post time updated // if this meta file exists and has timestamp changed, also cleanup attachment files to update @@ -143,6 +145,9 @@ impl Nex { if !fs::read_to_string(&s).is_ok_and(|this| this == state) { fs::remove_dir_all(&d)?; fs::create_dir_all(&d)?; + if let Some(ref permissions) = self.dir_permissions { + fs::set_permissions(&p, permissions.clone())? + } self.persist(&s, ×tamp, state.as_bytes())?; } else { if let Some(ref mut i) = index { @@ -299,3 +304,17 @@ impl Nex { Ok(status) } } + +fn permissions(config: Option, default: u32) -> Option { + { + #[cfg(any(target_os = "linux", target_os = "macos"))] + { + use std::{fs::Permissions, os::unix::fs::PermissionsExt}; + Some(Permissions::from_mode(config.unwrap_or(default))) + } + #[cfg(not(any(target_os = "linux", target_os = "macos",)))] + { + None // @TODO + } + } +}