From d8dac50cb64b5bfc462199545b2fcaa238e68b87 Mon Sep 17 00:00:00 2001 From: postscriptum Date: Thu, 3 Jul 2025 12:30:51 +0300 Subject: [PATCH] implement argument option to Keep Nex entry on Snac post was removed (disables cleanup action) --- README.md | 7 +++--- src/config.rs | 4 ++++ src/main.rs | 23 ++++++++++++++----- src/nex.rs | 54 +++++++++++++++++++++++++++++++++------------ src/nex/response.rs | 2 +- 5 files changed, 66 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b778ea7..a3e34a9 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,7 @@ snac2nex -s /path/to/snac/storage -t /path/to/nex -u user1 -u user2 Supported values: - * `c` (`copy`) - copy files - * `h` (`hard`) - create hard links - * `s` (`soft`) - create soft links (macos, linux, windows only) + * `c` (`copy`) - copy files * `h` (`hard`) - create hard links * `s` (`soft`) - create soft links (macos, linux, windows only) -r, --rotate Keep running as the daemon, renew every `n` seconds @@ -61,6 +59,9 @@ snac2nex -s /path/to/snac/storage -t /path/to/nex -u user1 -u user2 [default: "%Y/%m/%d %H:%M:%S"] + -k, --keep + Keep Nex entry on Snac post was removed + -h, --help Print help (see a summary with '-h') diff --git a/src/config.rs b/src/config.rs index 99918af..38d98b3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -44,4 +44,8 @@ pub struct Config { /// * escaped with `%%` #[arg(long, default_value_t = String::from("%Y/%m/%d %H:%M:%S"))] pub format_updated: String, + + /// Keep Nex entry on Snac post was removed + #[arg(short, long, default_value_t = false)] + pub keep: bool, } diff --git a/src/main.rs b/src/main.rs index 4f59eba..cec6cf1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,7 @@ fn main() -> Result<()> { c.format_updated, c.format_content, c.attachment, + !c.keep, &c.user, )?; let s = Snac::init(c.source, c.user)?; @@ -48,7 +49,11 @@ fn sync(snac: &Snac, nex: &Nex) -> Result { let mut r = Response::default(); for user in &snac.users { println!("\tsync profile for `{}`...", user.name); - let mut keep = HashSet::with_capacity(100); // @TODO estimated + let mut keep = if nex.is_cleanup() { + Some(HashSet::with_capacity(100)) // @TODO estimated + } else { + None + }; for post in user.public()? { r.total += 1; // make sure post entry has expected content type @@ -106,15 +111,21 @@ fn sync(snac: &Snac, nex: &Nex) -> Result { println!("\t\t\tpost file `{f}` update with new content.") } } - for i in response.keep { - keep.insert(i); + if let Some(ref mut k) = keep + && let Some(r) = response.keep + { + for i in r { + k.insert(i); + } } } } // cleanup removed post entries - let d = nex.clean(&user.name, keep)?; - r.deleted.directories += d.directories; - r.deleted.files += d.files; + if let Some(k) = keep { + let d = nex.clean(&user.name, k)?; + r.deleted.directories += d.directories; + r.deleted.files += d.files; + } } Ok(r) } diff --git a/src/nex.rs b/src/nex.rs index 5a3c3e0..d36020e 100644 --- a/src/nex.rs +++ b/src/nex.rs @@ -17,6 +17,7 @@ use std::{ pub struct Nex { attachment: Attachment, filename: String, + is_cleanup: bool, pattern: String, time_format: String, users: HashMap, @@ -29,6 +30,7 @@ impl Nex { time_format: String, pattern: String, attachment_mode: Option, + is_cleanup: bool, user_names: &Vec, ) -> Result { use std::path::MAIN_SEPARATOR; @@ -52,16 +54,15 @@ impl Nex { Ok(Self { attachment: Attachment::init(attachment_mode)?, filename, + is_cleanup, pattern, time_format, users, }) } - // @TODO: This function requires the following improvements: - // * validate attachments before updating - // * apply the post time to the files - /// Update destination with given data (typically received from Snac) + // Sync the Snac post with the Nex entry + // * @TODO apply the post time to the files pub fn sync( &self, name: &str, @@ -72,21 +73,33 @@ impl Nex { (published, updated): (DateTime, Option>), ) -> Result { // collect existing entries to ignore on cleanup - let mut i = Vec::with_capacity(10); // includes est. attachments len + let mut index = if self.is_cleanup { + Some(Vec::with_capacity(10)) // includes est. attachments len + } else { + None + }; // prepare destination let root = PathBuf::from(self.users.get(name).unwrap()); let mut p = PathBuf::from(&root); - i.push(root); + if let Some(ref mut i) = index { + i.push(root); + } p.push(published.format("%Y").to_string()); - i.push(p.clone()); + if let Some(ref mut i) = index { + i.push(p.clone()); + } p.push(published.format("%m").to_string()); - i.push(p.clone()); + if let Some(ref mut i) = index { + i.push(p.clone()); + } p.push(published.format("%d").to_string()); - i.push(p.clone()); + if let Some(ref mut i) = index { + i.push(p.clone()); + } fs::create_dir_all(&p)?; @@ -114,10 +127,12 @@ impl Nex { fs::create_dir_all(&d)?; fs::write(&s, updated.unwrap_or(published).to_string())? } else { - i.extend([d, f, p, s]); // move all paths processed to cleanup ignore + if let Some(ref mut i) = index { + i.extend([d, f, p, s]); + } return Ok(Sync { change: Change::Ignored, - keep: i, + keep: index, }); } @@ -157,7 +172,9 @@ impl Nex { if !to.exists() { self.attachment.sync(&from, &to).unwrap() } - i.push(to); + if let Some(ref mut i) = index { + i.push(to); + } format!("{}/{f}", d.file_name().unwrap().to_string_lossy()) } } @@ -197,9 +214,14 @@ impl Nex { fs::write(&f, c)?; // move all paths processed to cleanup ignore - i.extend([d, f, p, s]); + if let Some(ref mut i) = index { + i.extend([d, f, p, s]); + } - Ok(Sync { change, keep: i }) + Ok(Sync { + change, + keep: index, + }) } pub fn clean(&self, name: &str, ignore: HashSet) -> Result { @@ -233,4 +255,8 @@ impl Nex { pub fn is_attachments_disabled(&self) -> bool { matches!(self.attachment, Attachment::Disabled) } + + pub fn is_cleanup(&self) -> bool { + self.is_cleanup + } } diff --git a/src/nex/response.rs b/src/nex/response.rs index b364438..9a015c8 100644 --- a/src/nex/response.rs +++ b/src/nex/response.rs @@ -2,7 +2,7 @@ pub mod change; pub struct Sync { pub change: change::Change, - pub keep: Vec, + pub keep: Option>, } #[derive(Default)]