From 68af427ca0c292d12fd0e9b2fac7b9ed4b02a14e Mon Sep 17 00:00:00 2001 From: thewh1teagle <61390950+thewh1teagle@users.noreply.github.com> Date: Sun, 15 Dec 2024 20:28:07 +0200 Subject: [PATCH] feat: add reflink --- BUILDLING.md | 9 +++++- Cargo.lock | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + README.md | 28 ++++++++++++++++-- src/cli.rs | 5 ++++ src/files.rs | 8 +++++- src/paths.rs | 3 ++ 7 files changed, 128 insertions(+), 6 deletions(-) diff --git a/BUILDLING.md b/BUILDLING.md index f35ca6e..4e6fe1f 100644 --- a/BUILDLING.md +++ b/BUILDLING.md @@ -5,4 +5,11 @@ ```console git tag v0.1.0 git push --tags -``` \ No newline at end of file +``` + +## Test with dummay file + +```console +dd if=/dev/zero of=dummy bs=1G count=5 +mc dummy copied_dummy --verify +``` diff --git a/Cargo.lock b/Cargo.lock index 6922c7c..4683ce1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1148,7 +1148,7 @@ dependencies = [ "core-foundation", "derive_builder", "thiserror", - "windows", + "windows 0.52.0", "zbus", ] @@ -1239,6 +1239,7 @@ dependencies = [ "keepawake", "num_cpus", "rand", + "reflink-copy", "sha256", "tempfile", "tracing", @@ -1602,6 +1603,17 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "reflink-copy" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17400ed684c3a0615932f00c271ae3eea13e47056a1455821995122348ab6438" +dependencies = [ + "cfg-if", + "rustix 0.38.42", + "windows 0.58.0", +] + [[package]] name = "regex" version = "1.11.1" @@ -2333,7 +2345,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", "windows-targets 0.52.6", ] @@ -2346,6 +2368,60 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 39ff407..2b5ffbd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ humansize = "2.1.3" indicatif = "0.17.9" keepawake = "0.5.1" num_cpus = "1.16.0" +reflink-copy = "0.1.20" sha256 = "1.5.0" tracing = "0.1.41" tracing-indicatif = "0.3.8" diff --git a/README.md b/README.md index 49db48d..e742bfe 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,31 @@ See installation options in [Mc Website](https://thewh1teagle.github.io/mc/) or ## Usage +See `--help` + +
+ +Details + ```console -dd if=/dev/zero of=dummy bs=2G count=10 -mc dummy copied_dummy --verify +Copies files or directories with options for recursion and overwriting. + +Usage: mc [OPTIONS] ... + +Arguments: + ... Source file or directory to copy + Destination file or directory + +Options: + -f, --force Overwrite destination if it exists + --hard-link Hard link file + --symlink Symbol link file + --reflink Ref link file Similar to hardlink except modify one doesn't affect the other + --verify Verify hash of folder / file once copied + --no-progress Disable progress bar + --no-keep-awake Disable keep system awake while copy + --keep-display-awake Keep display awake while copy + -h, --help Print help ``` + +
diff --git a/src/cli.rs b/src/cli.rs index 2e4b4c9..4fbb838 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -24,6 +24,11 @@ pub struct Args { #[arg(long)] pub symlink: bool, + /// Ref link file + /// Similar to hardlink except modify one doesn't affect the other + #[arg(long)] + pub reflink: bool, + /// Verify hash of folder / file once copied #[arg(long)] pub verify: bool, diff --git a/src/files.rs b/src/files.rs index a93910e..6ea21d6 100644 --- a/src/files.rs +++ b/src/files.rs @@ -28,6 +28,7 @@ pub fn perform_copy_operation( !args.no_progress, args.symlink, args.hard_link, + args.reflink, source_path, destination_path, pb, @@ -93,6 +94,7 @@ pub fn copy_file>( progress: bool, symlink: bool, hard_link: bool, + reflink: bool, source_path: P, destination_path: P, pb: &Option, @@ -122,7 +124,9 @@ pub fn copy_file>( } else { let mut file_options = fs_extra::file::CopyOptions::new(); file_options.overwrite = force; - if progress { + if reflink { + reflink_copy::reflink_or_copy(source_path, destination_path)?; + } else if progress { fs_extra::file::copy_with_progress( source_path, destination_path, @@ -170,6 +174,7 @@ mod tests { no_keep_awake: true, source: vec![source_file.to_str().unwrap().to_string()], verify: false, + reflink: false, }; // Perform the copy operation @@ -209,6 +214,7 @@ mod tests { no_keep_awake: true, source: vec![source_dir.to_str().unwrap().to_string()], verify: false, + reflink: false, }; // Perform the copy operation diff --git a/src/paths.rs b/src/paths.rs index d91da5e..24be99c 100644 --- a/src/paths.rs +++ b/src/paths.rs @@ -63,6 +63,7 @@ mod tests { hard_link: false, keep_display_awake: false, no_keep_awake: true, + reflink: false, }; let result = ensure_valid_paths(&args); @@ -82,6 +83,7 @@ mod tests { hard_link: false, keep_display_awake: false, no_keep_awake: true, + reflink: false, }; let result = ensure_valid_paths(&args); @@ -118,6 +120,7 @@ mod tests { hard_link: false, keep_display_awake: false, no_keep_awake: true, + reflink: false, }; // Ensure that the destination directory doesn't exist before the test