diff --git a/.cargo/config.toml b/.cargo/config.toml index 02c2c84..223c2e5 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -10,9 +10,13 @@ lto = "thin" [profile.tiny] inherits = "release" opt-level = "z" +lto = true codegen-units = 1 [profile.fast] inherits = "release" lto = true codegen-units = 1 + +[build] +rustflags = ["-Ctarget-cpu=native"] \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 93456c7..d4e396a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### !!!⚠️!!! BREAKING CHANGE + +- Now, there is no difference between single file and diretories storage, all saves as `.qs` files. + ### Changed - Change to the CLI to support multiple files or directories at once -- !!!⚠️!!! BREAKING CHANGE: the default extension changed from `.cs*` to `.qs*` ## [1.0.0] - 2022-02-28 diff --git a/Cargo.lock b/Cargo.lock index 407467d..a0584b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,9 +64,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bincode" @@ -85,9 +85,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ "generic-array", ] @@ -115,9 +115,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.7.3" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" [[package]] name = "byteorder" @@ -163,29 +163,30 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "cpufeatures" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] [[package]] name = "crypto-common" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ "generic-array", + "typenum", ] [[package]] @@ -199,9 +200,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" dependencies = [ "byteorder", "digest 0.9.0", @@ -212,9 +213,9 @@ dependencies = [ [[package]] name = "deflate" -version = "0.9.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f95bf05dffba6e6cce8dfbb30def788154949ccd9aed761b472119c21e01c70" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" dependencies = [ "adler32", ] @@ -230,80 +231,15 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ "block-buffer", "crypto-common", - "generic-array", "subtle", ] -[[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -dependencies = [ - "encoding-index-japanese", - "encoding-index-korean", - "encoding-index-simpchinese", - "encoding-index-singlebyte", - "encoding-index-tradchinese", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" - [[package]] name = "generic-array" version = "0.14.5" @@ -355,20 +291,20 @@ dependencies = [ [[package]] name = "hkdf" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158bc31e00a68e380286904cc598715f861f2b0ccf7aa6fe20c6d0c49ca5d0f6" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" dependencies = [ "hmac", ] [[package]] name = "hmac" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddca131f3e7f2ce2df364b57949a9d47915cfbd35e46cfee355ccebbf794d6a2" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.1", + "digest 0.10.3", ] [[package]] @@ -394,18 +330,17 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.116" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", - "autocfg", ] [[package]] @@ -420,7 +355,7 @@ dependencies = [ "brotli", "byteorder", "ctr", - "digest 0.10.1", + "digest 0.10.3", "generic-array", "ghash", "hkdf", @@ -435,9 +370,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -445,9 +380,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg", "num-integer", @@ -467,9 +402,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] @@ -482,14 +417,13 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "png" -version = "0.17.2" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c845088517daa61e8a57eee40309347cea13f273694d1385c553e7a57127763b" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" dependencies = [ "bitflags", "crc32fast", "deflate", - "encoding", "miniz_oxide", ] @@ -537,9 +471,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" dependencies = [ "unicode-xid", ] @@ -548,7 +482,6 @@ dependencies = [ name = "quick-storer" version = "1.1.0" dependencies = [ - "brotli", "image", "lazy_static", "mla", @@ -558,9 +491,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] @@ -608,18 +541,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -628,13 +561,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.1", + "digest 0.10.3", ] [[package]] @@ -675,9 +608,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ "proc-macro2", "quote", @@ -707,9 +640,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] @@ -722,9 +655,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -734,9 +667,9 @@ checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "universal-hash" @@ -819,9 +752,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index fe47915..cdce839 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ categories = ["command-line-utilities", "compression", "data-structures", "encod # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -brotli = "3.3.4" lazy_static = "1.4.0" mla = "1.2.0" structopt = "0.3.26" @@ -22,3 +21,5 @@ image = { version = "0.24.2", features = ["ico", "png"], default-features = fals [target."cfg(windows)".build-dependencies] winres = "0.1.12" + +[features] diff --git a/build.rs b/build.rs index 2a0b073..8b10897 100644 --- a/build.rs +++ b/build.rs @@ -10,10 +10,8 @@ fn main() -> Result<(), Box> { BufWriter::new(File::create(format!("{}/config.rs", env::var("OUT_DIR")?))?); write!( config_file, - "pub const FILE_EXTENSION: &str = \"{}\";\n\ -pub const DIR_EXTENSION: &str = \"{}\";", - String::from("qsfile"), - String::from("qsdir") + r#"pub const EXTENSION: &str = "{}";"#, + String::from("qs") )?; #[cfg(windows)] windows_part()?; diff --git a/src/main.rs b/src/main.rs index 4b14a4b..6ae221f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,13 +2,12 @@ //! Defines the way our files are stored -use brotli::enc::BrotliEncoderParams; use lazy_static::lazy_static; use mla::{config::ArchiveWriterConfig, ArchiveReader, ArchiveWriter, Layers}; use std::{ ffi::OsString, fs::{File, OpenOptions}, - io::{self, BufReader, BufWriter, Write}, + io::{self, BufReader, BufWriter, ErrorKind, Write}, path::{Path, PathBuf}, }; use structopt::StructOpt; @@ -36,12 +35,14 @@ mod config { } fn main() -> Result<(), Box> { - for input in CLI_OPTIONS.input.iter() { + let mut to_load = vec![]; + let mut to_store = vec![]; + for input in &CLI_OPTIONS.input { if CLI_OPTIONS.verbose { println!("{}", input.display()); } if input.is_dir() { - store_dir(input)?; + to_store.push(input); } else if !input.is_file() { return Err(io::Error::new( io::ErrorKind::InvalidInput, @@ -51,107 +52,75 @@ fn main() -> Result<(), Box> { } else { match input.extension() { Some(ext) => { - if ext == OsString::from(config::FILE_EXTENSION).as_os_str() { - load_file(input)?; - } else if ext == OsString::from(config::DIR_EXTENSION).as_os_str() { - load_dir(input)?; + if ext == OsString::from(config::EXTENSION).as_os_str() { + to_load.push(input); } else { - store_file(input)?; + to_store.push(input); } } - None => store_file(input)?, + None => to_store.push(input), }; } } - Ok(()) -} + load(to_load)?; + store(to_store)?; -fn load_file(input: impl AsRef) -> Result<(), Box> { - let mut input_file = BufReader::new(File::open(input.as_ref())?); - let output = input.as_ref().with_extension(""); - if CLI_OPTIONS.verbose { - println!("{}", output.display()); - } - let mut output_file = BufWriter::new( - OpenOptions::new() - .create_new(!CLI_OPTIONS.force) - .create(true) - .truncate(true) - .write(true) - .open(&output)?, - ); - brotli::BrotliDecompress(&mut input_file, &mut output_file)?; - output_file.flush()?; Ok(()) } -fn store_file(input: impl AsRef) -> Result<(), Box> { - let mut input_file = BufReader::new(File::open(input.as_ref())?); - let output = PathBuf::from({ - let mut output = input.as_ref().as_os_str().to_owned(); - output.push(format!(".{}", config::FILE_EXTENSION)); - output - }); - if CLI_OPTIONS.verbose { - println!("{}", output.display()); - } - let mut output_file = BufWriter::new( - OpenOptions::new() - .create_new(!CLI_OPTIONS.force) - .create(true) - .truncate(true) - .write(true) - .open(&output)?, - ); - brotli::BrotliCompress( - &mut input_file, - &mut output_file, - &BrotliEncoderParams::default(), - )?; - output_file.flush()?; - Ok(()) -} +fn load(input_vec: Vec>) -> Result<(), Box> { + for input in input_vec { + let input_file = BufReader::new(File::open(input.as_ref())?); + let mut archive_reader = ArchiveReader::new(input_file)?; + let iter = archive_reader.list_files()?.cloned().collect::>(); + let nb_of_files = iter.len(); + for (i, file_string) in iter.into_iter().enumerate() { + let file_path = { + let mut bd = input.as_ref().to_path_buf(); + bd.pop(); + let mut path = bd.as_os_str().to_owned(); + path.push(&file_string); + PathBuf::from(path) + }; + println!( + "File stored at {} extracted to {} (file {} of {})", + &file_string, + file_path.display(), + i + 1, + nb_of_files + ); + let openoptions = { + let mut o = OpenOptions::new(); + o.create_new(!CLI_OPTIONS.force) + .create(true) + .truncate(true) + .write(true); + o + }; -fn load_dir(input: impl AsRef) -> Result<(), Box> { - let input_file = BufReader::new(File::open(input.as_ref())?); - let mut archive_reader = ArchiveReader::new(input_file)?; - let iter = archive_reader.list_files()?.cloned().collect::>(); - let nb_of_files = iter.len(); - for (i, file_string) in iter.into_iter().enumerate() { - let file_path = { - let mut bd = input.as_ref().to_path_buf(); - bd.pop(); - let mut path = bd.as_os_str().to_owned(); - path.push(&file_string); - PathBuf::from(path) - }; - println!( - "File stored at {} extracted to {} (file {} of {})", - &file_string, - file_path.display(), - i + 1, - nb_of_files - ); - std::fs::create_dir_all(file_path.parent().unwrap())?; - let mut output_file = BufWriter::new( - OpenOptions::new() - .create_new(!CLI_OPTIONS.force) - .create(true) - .truncate(true) - .write(true) - .open(&file_path)?, - ); - let mut file = archive_reader.get_file(file_string.clone())?.unwrap().data; - io::copy(&mut file, &mut output_file)?; + let mut output_file = BufWriter::new(match openoptions.open(&file_path) { + Ok(v) => v, + Err(e) => { + if e.kind() == ErrorKind::NotFound { + std::fs::create_dir_all(file_path.parent().unwrap())?; + openoptions.open(&file_path)? + } else { + return Err(e.into()); + } + } + }); + let mut file = archive_reader.get_file(file_string.clone())?.unwrap().data; + io::copy(&mut file, &mut output_file)?; + } } Ok(()) } -fn store_dir(input: impl AsRef) -> Result<(), Box> { +fn store(input_vec: Vec>) -> Result<(), Box> { let output = PathBuf::from({ - let mut output = input.as_ref().as_os_str().to_owned(); - output.push(format!(".{}", config::DIR_EXTENSION)); + let mut output = input_vec[0].as_ref().as_os_str().to_owned(); + output.push(format!(".{}", config::EXTENSION)); output }); println!("{}", output.display()); @@ -170,50 +139,54 @@ fn store_dir(input: impl AsRef) -> Result<(), Box> awc }; let mut archive_writer = ArchiveWriter::from_config(output_file, archive_writer_config)?; - traverse_and_store_dir(input, &PathBuf::from(""), &mut archive_writer)?; + for input in input_vec { + traverse_dir_and_store(input, &PathBuf::from(""), &mut archive_writer)?; + } + archive_writer.finalize()?; archive_writer.flush()?; Ok(()) } -fn traverse_and_store_dir( - current_dir: impl AsRef, +fn store_file( + path: impl AsRef, root: impl AsRef, archive_writer: &mut ArchiveWriter, ) -> Result<(), Box> { - let iter: Vec<_> = (current_dir.as_ref().read_dir()?) - .flatten() - .enumerate() - .collect(); - let len = iter.len(); - for (i, file) in iter { + let input_file_handler = BufReader::new(File::open(&path)?); + let file_path = { + let mut p = root.as_ref().as_os_str().to_owned(); + p.push("/"); + p.push(path.as_ref().file_name().unwrap()); + p + }; + archive_writer.add_file( + &file_path.to_string_lossy(), + path.as_ref().metadata()?.len(), + input_file_handler, + )?; + Ok(()) +} + +fn traverse_dir_and_store( + path: impl AsRef, + root: impl AsRef, + archive_writer: &mut ArchiveWriter, +) -> Result<(), Box> { + let iter = match path.as_ref().read_dir() { + Ok(i) => i.flatten().collect::>(), + Err(_) => { + return store_file(path, root, archive_writer); + } + }; + for file in iter { if file.path().is_dir() { let mut new_root = root.as_ref().as_os_str().to_owned(); new_root.push("/"); - new_root.push(current_dir.as_ref().file_name().unwrap()); - traverse_and_store_dir(&file.path(), &PathBuf::from(new_root), archive_writer)?; + new_root.push(path.as_ref().file_name().unwrap()); + traverse_dir_and_store(&file.path(), &PathBuf::from(new_root), archive_writer)?; } else if file.path().is_file() { - let input_file_handler = BufReader::new(File::open(file.path())?); - let file_path = { - let mut p = root.as_ref().as_os_str().to_owned(); - p.push("/"); - p.push(current_dir.as_ref().file_name().unwrap()); - p.push("/"); - p.push(file.path().file_name().unwrap()); - p - }; - println!( - "Found file to store at {}, storing it at path {} (file {} of {} in this directory)", - file.path().display(), - file_path.to_string_lossy(), - i+1, - len - ); - archive_writer.add_file( - &file_path.to_string_lossy(), - file.metadata()?.len(), - input_file_handler, - )?; + store_file(file.path(), &root, archive_writer)?; }; } Ok(())