aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock45
-rw-r--r--Cargo.toml2
-rw-r--r--src/main.rs48
3 files changed, 85 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 571f48d..0737d92 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -288,8 +288,10 @@ dependencies = [
"clap",
"image",
"indicatif",
+ "pathdiff",
"priority-queue",
"rayon",
+ "reflink-copy",
"serde",
"serde_json",
"sha2",
@@ -496,6 +498,12 @@ dependencies = [
]
[[package]]
+name = "ioctl-sys"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c"
+
+[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -659,6 +667,12 @@ dependencies = [
]
[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
name = "pin-project"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -766,6 +780,18 @@ dependencies = [
]
[[package]]
+name = "reflink-copy"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84b9fdc4b74744920661b70bc8daa091791c1f6940d7f9a90338754532237c29"
+dependencies = [
+ "cfg-if",
+ "ioctl-sys",
+ "libc",
+ "windows",
+]
+
+[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1036,6 +1062,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
+name = "windows"
+version = "0.51.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9"
+dependencies = [
+ "windows-core",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.51.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 7335a70..f066eae 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,3 +18,5 @@ serde = "1"
serde_json = "1"
sha2 = "0"
anyhow = "1"
+pathdiff = "0"
+reflink-copy = "0"
diff --git a/src/main.rs b/src/main.rs
index 1872e31..6337b14 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,10 +1,10 @@
-#![feature(iterator_try_collect)]
+#![feature(iterator_try_collect, absolute_path)]
use anyhow::Result;
use clap::Parser;
use priority_queue::PriorityQueue;
use sha2::{Sha512_256, Digest};
-use std::{cmp::Ordering, collections::HashMap, fs, io, io::Write, path::PathBuf};
+use std::{cmp::Ordering, collections::HashMap, fs, io, io::Write, path, path::PathBuf};
use embedders::*;
use pure_embedders::*;
@@ -28,11 +28,11 @@ struct Args {
embedder: Embedder,
/// Symlink the sorted images into this directory
- #[arg(short = 'o', long)]
+ #[arg(short = 's', long)]
symlink_dir: Option<PathBuf>,
- /// Copy the sorted images into this directory. TODO uses COW when available
- #[arg(short = 's', long)]
+ /// Copy the sorted images into this directory. Uses COW when available
+ #[arg(short = 'o', long)]
copy_dir: Option<PathBuf>,
/// Write sorted paths into stdout, one per line
@@ -186,8 +186,36 @@ fn process_embedder<E>(mut e: E, args: &Args, cfg: &Config) -> Result<Vec<PathBu
Ok(tsp_path.iter().map(|i| args.images[*i].clone()).collect())
}
-fn symlink_into(tsp: &[PathBuf], target: &PathBuf) -> Result<()> {todo!()}
-fn copy_into(tsp: &[PathBuf], target: &PathBuf) -> Result<()> {todo!()}
+fn symlink_into(tsp: &[PathBuf], target: &PathBuf) -> Result<()> {
+ fs::create_dir_all(target)?;
+
+ let pad_len = (tsp.len() as f64).log10().ceil() as usize;
+ for (i, p) in tsp.iter().enumerate() {
+ let ext: String = match p.extension() {
+ None => "".to_string(),
+ Some(e) => format!(".{}", e.to_str().unwrap()),
+ };
+ let tp = target.join(format!("{:0pl$}{ext}", i, pl = pad_len, ext = ext));
+ let rel_path = pathdiff::diff_paths(path::absolute(p)?,
+ path::absolute(target)?).unwrap();
+ std::os::unix::fs::symlink(rel_path, tp);
+ }
+ Ok(())
+}
+fn copy_into(tsp: &[PathBuf], target: &PathBuf) -> Result<()> {
+ fs::create_dir_all(target)?;
+
+ let pad_len = (tsp.len() as f64).log10().ceil() as usize;
+ for (i, p) in tsp.iter().enumerate() {
+ let ext: String = match p.extension() {
+ None => "".to_string(),
+ Some(e) => format!(".{}", e.to_str().unwrap()),
+ };
+ let tp = target.join(format!("{:0pl$}{ext}", i, pl = pad_len, ext = ext));
+ reflink_copy::reflink_or_copy(p, tp)?;
+ }
+ Ok(())
+}
fn main() -> Result<()> {
let cfg = get_config()?;
@@ -200,11 +228,11 @@ fn main() -> Result<()> {
Embedder::Content => process_embedder(ContentEmbedder::new(&cfg), &args, &cfg),
}?;
- args.symlink_dir.into_iter().try_for_each(|p| symlink_into(&tsp_path, &p))?;
- args.copy_dir .into_iter().try_for_each(|p| copy_into(&tsp_path, &p))?;
+ if let Some(p) = args.symlink_dir { symlink_into(&tsp_path, &p)? }
+ if let Some(p) = args.copy_dir { copy_into(&tsp_path, &p)? }
let path_delim = if args.stdout0 { Some(0) }
- else if args.stdout { Some(10) }
+ else if args.stdout { Some(b'\n') }
else { None };
path_delim.into_iter().try_for_each(|delim| {