mirror of
https://github.com/Dummi26/rembackup.git
synced 2025-03-10 05:13:54 +01:00
Add some more cli options
This commit is contained in:
parent
7595d2482c
commit
c9c85ea6ad
@ -2,6 +2,8 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
|
use crate::update_index::Settings;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(author, version)]
|
#[command(author, version)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
@ -22,4 +24,7 @@ pub struct Args {
|
|||||||
/// don't ask for confirmation, just apply the changes.
|
/// don't ask for confirmation, just apply the changes.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub noconfirm: bool,
|
pub noconfirm: bool,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
pub settings: Settings,
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,34 @@ use std::{
|
|||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::repr_file::ReprFile;
|
use crate::{repr_file::ReprFile, update_index::Settings};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug)]
|
||||||
pub struct IndexFile {
|
pub struct IndexFile {
|
||||||
size: u64,
|
pub size: u64,
|
||||||
last_modified: Option<u64>,
|
pub last_modified: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexFile {
|
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 {
|
pub fn new_from_metadata(metadata: &Metadata) -> Self {
|
||||||
Self {
|
Self {
|
||||||
size: metadata.len(),
|
size: metadata.len(),
|
||||||
|
34
src/main.rs
34
src/main.rs
@ -26,7 +26,7 @@ fn main() {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|path| path.strip_prefix(source).unwrap_or(path))
|
.map(|path| path.strip_prefix(source).unwrap_or(path))
|
||||||
.collect();
|
.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,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Failed to generate index diff:\n {e}");
|
eprintln!("Failed to generate index diff:\n {e}");
|
||||||
@ -47,10 +47,34 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
eprintln!(" - - - - -");
|
eprintln!(" - - - - -");
|
||||||
eprintln!(" >> add directory");
|
eprintln!(
|
||||||
eprintln!(" + add/update file");
|
" >> add directory | {}x",
|
||||||
eprintln!(" - remove file");
|
changes
|
||||||
eprintln!(" [-] remove directory (and all contents!)");
|
.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
|
// apply changes after confirming
|
||||||
if !args.noconfirm {
|
if !args.noconfirm {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
|
@ -1,11 +1,33 @@
|
|||||||
use std::{collections::HashMap, fs, io, path::Path};
|
use std::{collections::HashMap, fs, io, path::Path};
|
||||||
|
|
||||||
|
use clap::Args;
|
||||||
|
|
||||||
use crate::{indexchanges::IndexChange, indexfile::IndexFile};
|
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>(
|
pub fn perform_index_diff<'a>(
|
||||||
source: &Path,
|
source: &Path,
|
||||||
index: &'a Path,
|
index: &'a Path,
|
||||||
mut ignore_paths: Vec<&'a Path>,
|
mut ignore_paths: Vec<&'a Path>,
|
||||||
|
settings: &Settings,
|
||||||
) -> io::Result<Vec<IndexChange>> {
|
) -> io::Result<Vec<IndexChange>> {
|
||||||
let mut changes = Vec::new();
|
let mut changes = Vec::new();
|
||||||
if let Ok(inner_index) = index.strip_prefix(source) {
|
if let Ok(inner_index) = index.strip_prefix(source) {
|
||||||
@ -18,6 +40,7 @@ pub fn perform_index_diff<'a>(
|
|||||||
index,
|
index,
|
||||||
&mut changes,
|
&mut changes,
|
||||||
&ignore_paths,
|
&ignore_paths,
|
||||||
|
settings,
|
||||||
)?;
|
)?;
|
||||||
Ok(changes)
|
Ok(changes)
|
||||||
}
|
}
|
||||||
@ -31,6 +54,7 @@ fn rec(
|
|||||||
// list of changes to be made
|
// list of changes to be made
|
||||||
changes: &mut Vec<IndexChange>,
|
changes: &mut Vec<IndexChange>,
|
||||||
ignore_paths: &Vec<&Path>,
|
ignore_paths: &Vec<&Path>,
|
||||||
|
settings: &Settings,
|
||||||
) -> Result<(), io::Error> {
|
) -> Result<(), io::Error> {
|
||||||
// used to find removals
|
// used to find removals
|
||||||
let index_rel_path = index_files.join(rel_path);
|
let index_rel_path = index_files.join(rel_path);
|
||||||
@ -63,7 +87,14 @@ fn rec(
|
|||||||
// is dir, but was file -> remove file
|
// is dir, but was file -> remove file
|
||||||
changes.push(IndexChange::RemoveFile(rel_path.clone()));
|
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 {
|
} else {
|
||||||
if let Some(true) = in_index_and_is_dir {
|
if let Some(true) = in_index_and_is_dir {
|
||||||
// is file, but was dir -> remove dir
|
// is file, but was dir -> remove dir
|
||||||
@ -72,7 +103,7 @@ fn rec(
|
|||||||
let newif = IndexFile::new_from_metadata(&metadata);
|
let newif = IndexFile::new_from_metadata(&metadata);
|
||||||
let oldif = IndexFile::from_path(&index_files.join(&rel_path));
|
let oldif = IndexFile::from_path(&index_files.join(&rel_path));
|
||||||
match oldif {
|
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)),
|
_ => changes.push(IndexChange::AddFile(rel_path, newif)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user