implement daemon mode argument option

This commit is contained in:
postscriptum 2025-07-03 12:53:59 +03:00
parent 77d0650aef
commit 1e3043d683
4 changed files with 58 additions and 21 deletions

View file

@ -35,7 +35,9 @@ 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 <ROTATE>
Keep running as the daemon, renew every `n` seconds
@ -62,6 +64,9 @@ snac2nex -s /path/to/snac/storage -t /path/to/nex -u user1 -u user2
-k, --keep
Keep Nex entry on Snac post was removed
-d, --daemon
Disables some debug output
-h, --help
Print help (see a summary with '-h')

View file

@ -48,4 +48,8 @@ pub struct Config {
/// Keep Nex entry on Snac post was removed
#[arg(short, long, default_value_t = false)]
pub keep: bool,
/// Disables some debug output
#[arg(short, long, default_value_t = false)]
pub daemon: bool,
}

View file

@ -13,30 +13,38 @@ fn main() -> Result<()> {
use config::Config;
let c = Config::parse();
println!("Sync `{}` for users {:?}...", &c.source, &c.user);
let n = Nex::init(
c.target,
c.format_filename,
c.format_updated,
c.format_content,
c.attachment,
!c.keep,
(!c.keep, !c.daemon),
&c.user,
)?;
let s = Snac::init(c.source, c.user)?;
println!("export begin...");
let mut r = sync(&s, &n)?;
let mut r = sync(&s, &n, !c.daemon)?;
match c.rotate {
Some(t) => loop {
println!(
"queue completed:\n\tcreated: {}\n\tupdated: {}\n\tdeleted:\n\t\tfiles: {}\n\t\tdirectories: {}\n\tignored: {}\n\ttotal: {}\nawait {t} seconds to rotate...",
r.created, r.updated, r.deleted.files, r.deleted.directories, r.ignored, r.total
);
if !c.daemon {
println!(
"queue completed:\n\tcreated: {}\n\tupdated: {}\n\tdeleted:\n\t\tfiles: {}\n\t\tdirectories: {}\n\tignored: {}\n\ttotal: {}\nawait {t} seconds to rotate...",
r.created,
r.updated,
r.deleted.files,
r.deleted.directories,
r.ignored,
r.total
);
}
std::thread::sleep(std::time::Duration::from_secs(t));
r = sync(&s, &n)?;
r = sync(&s, &n, !c.daemon)?;
},
None => println!(
"export completed:\n\tcreated: {}\n\tupdated: {}\n\tdeleted:\n\t\tfiles: {}\n\t\tdirectories: {}\n\tignored: {}\n\ttotal: {}",
"Sync operation completed:\n\tcreated: {}\n\tupdated: {}\n\tdeleted:\n\t\tfiles: {}\n\t\tdirectories: {}\n\tignored: {}\n\ttotal: {}",
r.created, r.updated, r.deleted.files, r.deleted.directories, r.ignored, r.total
),
}
@ -44,11 +52,13 @@ fn main() -> Result<()> {
Ok(())
}
fn sync(snac: &Snac, nex: &Nex) -> Result<Response> {
fn sync(snac: &Snac, nex: &Nex, is_debug: bool) -> Result<Response> {
use std::collections::HashSet;
let mut r = Response::default();
for user in &snac.users {
println!("\tsync profile for `{}`...", user.name);
if is_debug {
println!("\tsync profile for `{}`...", user.name);
}
let mut keep = if nex.is_cleanup() {
Some(HashSet::with_capacity(100)) // @TODO estimated
} else {
@ -62,7 +72,9 @@ fn sync(snac: &Snac, nex: &Nex) -> Result<Response> {
}
// skip non authorized content
if let Some(content) = post.source_content {
println!("\t\tsync post `{}`...", post.id);
if is_debug {
println!("\t\tsync post `{}`...", post.id);
}
let response = nex.sync(
&user.name,
content,
@ -99,15 +111,21 @@ fn sync(snac: &Snac, nex: &Nex) -> Result<Response> {
match response.change {
Change::Created => {
r.created += 1;
println!("\t\t\tcreate new post file.")
if is_debug {
println!("\t\t\tcreate new post file.")
}
}
Change::Ignored => {
r.ignored += 1;
println!("\t\t\tpost file is up to date.")
if is_debug {
println!("\t\t\tpost file is up to date.")
}
}
Change::Updated => {
r.updated += 1;
println!("\t\t\tpost file update with new content.")
if is_debug {
println!("\t\t\tpost file update with new content.")
}
}
}
if let Some(ref mut k) = keep

View file

@ -18,6 +18,7 @@ pub struct Nex {
attachment: Attachment,
filename: String,
is_cleanup: bool,
is_debug: bool,
pattern: String,
time_format: String,
users: HashMap<String, PathBuf>,
@ -30,7 +31,7 @@ impl Nex {
time_format: String,
pattern: String,
attachment_mode: Option<String>,
is_cleanup: bool,
(is_cleanup, is_debug): (bool, bool),
user_names: &Vec<String>,
) -> Result<Self> {
use std::path::MAIN_SEPARATOR;
@ -55,6 +56,7 @@ impl Nex {
attachment: Attachment::init(attachment_mode)?,
filename,
is_cleanup,
is_debug,
pattern,
time_format,
users,
@ -225,7 +227,9 @@ impl Nex {
}
pub fn clean(&self, name: &str, ignore: HashSet<PathBuf>) -> Result<Clean> {
println!("\t\tcleanup...");
if self.is_debug {
println!("\t\tcleanup...");
}
let mut r = Clean::default();
for entry in
walkdir::WalkDir::new(PathBuf::from(self.users.get(name).unwrap())).follow_links(false)
@ -233,7 +237,9 @@ impl Nex {
let e = entry?;
let p = e.path();
let s = p.to_string_lossy();
println!("\t\tcheck `{s}`...");
if self.is_debug {
println!("\t\tcheck `{s}`...");
}
if ignore.contains(p) {
continue;
}
@ -241,11 +247,15 @@ impl Nex {
if m.is_file() {
fs::remove_file(p)?;
r.files += 1;
println!("\t\t\tdelete file `{s}`");
if self.is_debug {
println!("\t\t\tdelete file `{s}`");
}
} else if m.is_dir() {
fs::remove_dir_all(p)?;
r.directories += 1;
println!("\t\t\tdelete directory `{s}`");
if self.is_debug {
println!("\t\t\tdelete directory `{s}`");
}
} else {
panic!()
}