From c9c85ea6ad4ade7127359a578e16830dd1849c88 Mon Sep 17 00:00:00 2001 From: Mark <> Date: Sun, 17 Mar 2024 13:45:03 +0100 Subject: [PATCH] Add some more cli options --- src/args.rs | 5 +++++ src/indexfile.rs | 27 +++++++++++++++++++++++---- src/main.rs | 34 +++++++++++++++++++++++++++++----- src/update_index.rs | 35 +++++++++++++++++++++++++++++++++-- 4 files changed, 90 insertions(+), 11 deletions(-) diff --git a/src/args.rs b/src/args.rs index 8e9486e..7ced6a7 100755 --- a/src/args.rs +++ b/src/args.rs @@ -2,6 +2,8 @@ use std::path::PathBuf; use clap::Parser; +use crate::update_index::Settings; + #[derive(Parser)] #[command(author, version)] pub struct Args { @@ -22,4 +24,7 @@ pub struct Args { /// don't ask for confirmation, just apply the changes. #[arg(long)] pub noconfirm: bool, + + #[command(flatten)] + pub settings: Settings, } diff --git a/src/indexfile.rs b/src/indexfile.rs index 27fdafa..8d03dcc 100755 --- a/src/indexfile.rs +++ b/src/indexfile.rs @@ -6,15 +6,34 @@ use std::{ time::SystemTime, }; -use crate::repr_file::ReprFile; +use crate::{repr_file::ReprFile, update_index::Settings}; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug)] pub struct IndexFile { - size: u64, - last_modified: Option, + pub size: u64, + pub last_modified: Option, } impl IndexFile { + pub fn should_be_updated(&self, prev: &Self, settings: &Settings) -> bool { + self.size != prev.size + || ((!settings.ignore_timestamp) + && match (self.last_modified, prev.last_modified) { + (Some(new), Some(old)) => { + if new > old { + true + } else if new < old { + !settings.dont_replace_newer + } else { + // same timestamp + false + } + } + (Some(new), None) => !settings.dont_replace_if_timestamp_found, + (None, Some(old)) => settings.replace_if_timestamp_lost, + (None, None) => settings.replace_if_timestamp_unknown, + }) + } pub fn new_from_metadata(metadata: &Metadata) -> Self { Self { size: metadata.len(), diff --git a/src/main.rs b/src/main.rs index 59123f0..bd922ef 100755 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,7 @@ fn main() { .iter() .map(|path| path.strip_prefix(source).unwrap_or(path)) .collect(); - let changes = match perform_index_diff(source, index, ignore_subdirs) { + let changes = match perform_index_diff(source, index, ignore_subdirs, &args.settings) { Ok(c) => c, Err(e) => { eprintln!("Failed to generate index diff:\n {e}"); @@ -47,10 +47,34 @@ fn main() { } } eprintln!(" - - - - -"); - eprintln!(" >> add directory"); - eprintln!(" + add/update file"); - eprintln!(" - remove file"); - eprintln!(" [-] remove directory (and all contents!)"); + eprintln!( + " >> add directory | {}x", + changes + .iter() + .filter(|c| matches!(c, IndexChange::AddDir(..))) + .count() + ); + eprintln!( + " + add/update file | {}x", + changes + .iter() + .filter(|c| matches!(c, IndexChange::AddFile(..))) + .count() + ); + eprintln!( + " - remove file | {}x", + changes + .iter() + .filter(|c| matches!(c, IndexChange::RemoveFile(..))) + .count() + ); + eprintln!( + " [-] remove directory (and all contents!) | {}x", + changes + .iter() + .filter(|c| matches!(c, IndexChange::RemoveDir(..))) + .count() + ); // apply changes after confirming if !args.noconfirm { let mut line = String::new(); diff --git a/src/update_index.rs b/src/update_index.rs index e399aea..e2c30b4 100755 --- a/src/update_index.rs +++ b/src/update_index.rs @@ -1,11 +1,33 @@ use std::{collections::HashMap, fs, io, path::Path}; +use clap::Args; + use crate::{indexchanges::IndexChange, indexfile::IndexFile}; +#[derive(Clone, Default, Args)] +pub struct Settings { + /// don't update files just because their timestamp is different + #[arg(long)] + pub ignore_timestamp: bool, + /// keep *newer* files when the files in the source are *older* + #[arg(long)] + pub dont_replace_newer: bool, + /// replace files if their timestamp is unknown in both source and index + #[arg(long)] + pub replace_if_timestamp_unknown: bool, + /// replace files if their timestamp is unknown in source but known in index + #[arg(long)] + pub replace_if_timestamp_lost: bool, + /// don't replace files if their timestamp is known in source but unknown in index + #[arg(long)] + pub dont_replace_if_timestamp_found: bool, +} + pub fn perform_index_diff<'a>( source: &Path, index: &'a Path, mut ignore_paths: Vec<&'a Path>, + settings: &Settings, ) -> io::Result> { let mut changes = Vec::new(); if let Ok(inner_index) = index.strip_prefix(source) { @@ -18,6 +40,7 @@ pub fn perform_index_diff<'a>( index, &mut changes, &ignore_paths, + settings, )?; Ok(changes) } @@ -31,6 +54,7 @@ fn rec( // list of changes to be made changes: &mut Vec, ignore_paths: &Vec<&Path>, + settings: &Settings, ) -> Result<(), io::Error> { // used to find removals let index_rel_path = index_files.join(rel_path); @@ -63,7 +87,14 @@ fn rec( // is dir, but was file -> remove file changes.push(IndexChange::RemoveFile(rel_path.clone())); } - rec(source, &rel_path, index_files, changes, ignore_paths)?; + rec( + source, + &rel_path, + index_files, + changes, + ignore_paths, + settings, + )?; } else { if let Some(true) = in_index_and_is_dir { // is file, but was dir -> remove dir @@ -72,7 +103,7 @@ fn rec( let newif = IndexFile::new_from_metadata(&metadata); let oldif = IndexFile::from_path(&index_files.join(&rel_path)); match oldif { - Ok(Ok(oldif)) if oldif == newif => {} + Ok(Ok(oldif)) if !newif.should_be_updated(&oldif, settings) => {} _ => changes.push(IndexChange::AddFile(rel_path, newif)), } }