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]
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