From 4d390b131e40773e03b4c73ec527563259e6610b Mon Sep 17 00:00:00 2001 From: grimhilt Date: Thu, 1 Jun 2023 20:41:54 +0200 Subject: [PATCH] status test for differences works --- .gitignore | 1 + Cargo.lock | 100 ++++++++++++++++++++++++++++- Cargo.toml | 3 +- src/commands.rs | 1 + src/commands/init.rs | 10 +++ src/commands/status.rs | 141 +++++++++++++++++++++++++++++++++++++++++ src/main.rs | 3 + 7 files changed, 256 insertions(+), 3 deletions(-) create mode 100644 src/commands/status.rs diff --git a/.gitignore b/.gitignore index fbcc087..635f34d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ target todo .nextsync .nextsyncignore +test diff --git a/Cargo.lock b/Cargo.lock index c726443..b668afc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,6 +170,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "futures-channel" version = "0.3.28" @@ -218,6 +224,12 @@ dependencies = [ "slab", ] +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + [[package]] name = "h2" version = "0.3.19" @@ -462,7 +474,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eebffdb73fe72e917997fad08bdbf31ac50b0fa91cec93e69a0662e4264d454c" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -485,12 +497,13 @@ dependencies = [ ] [[package]] -name = "next-sync" +name = "nextsync" version = "0.1.0" dependencies = [ "clap", "dotenv", "reqwest", + "rust-crypto", "tokio", ] @@ -619,6 +632,53 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -675,6 +735,25 @@ dependencies = [ "winreg", ] +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +dependencies = [ + "gcc", + "libc", + "rand 0.3.23", + "rustc-serialize", + "time", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + [[package]] name = "rustix" version = "0.37.19" @@ -835,6 +914,17 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1011,6 +1101,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 852bd95..939ffd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "next-sync" +name = "nextsync" version = "0.1.0" edition = "2021" @@ -10,3 +10,4 @@ reqwest = { version = "0.11", features = ["blocking", "json", "multipart"] } tokio = { version = "1", features = ["full"] } dotenv ="0.15.0" clap = "2.33" +rust-crypto = "0.2.36" diff --git a/src/commands.rs b/src/commands.rs index 43763f1..3ed8b62 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1 +1,2 @@ pub mod init; +pub mod status; diff --git a/src/commands/init.rs b/src/commands/init.rs index 57478d6..8c2cb96 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -4,12 +4,21 @@ use std::env; pub fn init() { let builder = DirBuilder::new(); let mut path = env::current_dir().unwrap(); + + // .nextsync folder path.push(".nextsync"); match builder.create(path.clone()) { Ok(()) => println!("Directory successfuly created"), Err(_) => println!("Error: cannot create directory"), } + path.push("HEAD"); + match File::create(path.clone()) { + Ok(_) => println!("File successfuly created"), + Err(_) => println!("Error: cannot create .nextsyncignore"), + } + + path.pop(); path.pop(); path.push(".nextsyncignore"); @@ -17,4 +26,5 @@ pub fn init() { Ok(_) => println!("File successfuly created"), Err(_) => println!("Error: cannot create .nextsyncignore"), } + } diff --git a/src/commands/status.rs b/src/commands/status.rs new file mode 100644 index 0000000..b0ff8bc --- /dev/null +++ b/src/commands/status.rs @@ -0,0 +1,141 @@ +use std::env; +use std::path::Path; +use std::fs::File; +use std::io::{self, BufRead}; +use std::path::PathBuf; +use crypto::digest::Digest; +use crypto::sha1::Sha1; +use std::collections::HashSet; + + +pub fn status() { + let mut a = vec![]; + + { + let b = 2; + a.push(b.clone()); + } + + println!("Vector a: {:?}", a); + let mut new_files: Vec = Vec::new(); + let mut hashes = HashSet::new(); + let mut objects: Vec<&str> = vec![]; + + let path = env::current_dir().unwrap(); + let mut next_sync_path = path.clone(); + next_sync_path.push(".nextsync"); + + + if let Ok(lines) = read_head(next_sync_path.clone()) { + for line in lines { + if let Ok(ip) = line { + hashes.insert(String::from(ip).as_str()); + } + } + } + + if let Ok(entries) = read_folder(path.clone()) { + for entry in entries { + if !is_nextsync_config(entry.clone()) { + let object_path = entry.strip_prefix(path.clone()).unwrap(); + objects.push(object_path.to_str().unwrap().clone()); + } + } + } + + find_missing_elements(&mut hashes, &mut objects); + dbg!(hashes); + dbg!(objects); +} + +fn find_missing_elements(hashes: &mut HashSet<&str>, objects: &mut Vec<&str>) { + let mut hasher = Sha1::new(); + let mut to_remove: Vec = vec![]; + let mut i = 0; + + for object in &mut *objects { + // hash the object + hasher.input_str(object); + let hash = hasher.result_str(); + hasher.reset(); + + // find it on the list of hashes + if hashes.contains(hash.as_str()) { + hashes.remove(hash.as_str()); + to_remove.push(i); + } + i += 1; + } + + // remove all objects existing in the list of hashes + i = 0; + for index in to_remove { + objects.remove(index-i); + i += 1; + } +} + +fn is_nextsync_config(path: PathBuf) -> bool { + path.ends_with(".nextsync") || path.ends_with(".nextsyncignore") +} + +fn read_head(mut path: PathBuf) -> io::Result>> { + path.push("HEAD"); + read_lines(path) +} + +use std::fs; + +fn read_folder(path: PathBuf) -> io::Result> { + let mut entries = fs::read_dir(path)? + .map(|res| res.map(|e| e.path())) + .collect::, io::Error>>()?; + + entries.sort(); + Ok(entries) +} + +// The output is wrapped in a Result to allow matching on errors +// Returns an Iterator to the Reader of the lines of the file. +fn read_lines

(filename: P) -> io::Result>> +where P: AsRef, { + let file = File::open(filename)?; + Ok(io::BufReader::new(file).lines()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_find_missing_elements() { + let mut hasher = Sha1::new(); + hasher.input_str("file1"); + let hash1 = hasher.result_str(); + hasher.reset(); + let mut hasher = Sha1::new(); + hasher.input_str("file2"); + let hash2 = hasher.result_str(); + hasher.reset(); + let mut hasher = Sha1::new(); + hasher.input_str("file4"); + let hash4 = hasher.result_str(); + hasher.reset(); + + let mut hashes = HashSet::new(); + hashes.insert(hash1.as_str()); + hashes.insert(hash2.as_str()); + hashes.insert(hash4.as_str()); + + let mut objects: Vec<&str> = vec![]; + objects.push("file1"); + objects.push("file2"); + objects.push("file3"); + find_missing_elements(&mut hashes, &mut objects); + dbg!(hashes.clone()); + dbg!(objects.clone()); + assert_eq!(hashes.contains(hash4.as_str()), true); + assert_eq!(hashes.len(), 1); + assert_eq!(objects, vec!["file3"]); + } +} diff --git a/src/main.rs b/src/main.rs index c533a02..bd1bda9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,10 +14,13 @@ fn main() { .author("grimhilt") .about("") .subcommand(SubCommand::with_name("init")) + .subcommand(SubCommand::with_name("status")) .get_matches(); if let Some(_) = matches.subcommand_matches("init") { commands::init::init(); + } else if let Some(_) = matches.subcommand_matches("status") { + commands::status::status(); } //tokio::runtime::Runtime::new().unwrap().block_on(async {