v0.2
This commit is contained in:
8
Makefile
8
Makefile
@@ -1,5 +1,9 @@
|
|||||||
build:
|
all: build-linux build-win
|
||||||
|
|
||||||
|
build-linux:
|
||||||
cargo build --release --target x86_64-unknown-linux-gnu --package zsdiff_all --bin zspatch
|
cargo build --release --target x86_64-unknown-linux-gnu --package zsdiff_all --bin zspatch
|
||||||
cargo build --release --target x86_64-unknown-linux-gnu --package zsdiff_all --bin zsdiff
|
cargo build --release --target x86_64-unknown-linux-gnu --package zsdiff_all --bin zsdiff
|
||||||
|
|
||||||
|
build-win:
|
||||||
cargo build --release --target x86_64-pc-windows-gnu --package zsdiff_all --bin zspatch
|
cargo build --release --target x86_64-pc-windows-gnu --package zsdiff_all --bin zspatch
|
||||||
cargo build --release --target x86_64-pc-windows-gnu --package zsdiff_all --bin zsdiff
|
cargo build --release --target x86_64-pc-windows-gnu --package zsdiff_all --bin zsdiff
|
||||||
@@ -55,6 +55,7 @@ pub struct Metadata {
|
|||||||
pub(crate) diff_files: Vec<String>,
|
pub(crate) diff_files: Vec<String>,
|
||||||
pub hashes: HashMap<String, String>,
|
pub hashes: HashMap<String, String>,
|
||||||
pub remove_files: Vec<String>,
|
pub remove_files: Vec<String>,
|
||||||
|
pub remove_folders: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_hash(data: Vec<u8>) -> String {
|
pub async fn get_hash(data: Vec<u8>) -> String {
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ use std::{fs, io, time};
|
|||||||
use utils::{Metadata, Zsdiff, get_hash};
|
use utils::{Metadata, Zsdiff, get_hash};
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct FileInfo {
|
struct FileInfo {
|
||||||
path: String,
|
path: String,
|
||||||
relative_path: String, // Without dir prefix
|
relative_path: String, // Without dir prefix
|
||||||
hash: String,
|
hash: String,
|
||||||
|
is_dir: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn walk_dir(dir: String) -> HashMap<String, FileInfo> {
|
async fn walk_dir(dir: String) -> HashMap<String, FileInfo> {
|
||||||
@@ -18,33 +20,66 @@ async fn walk_dir(dir: String) -> HashMap<String, FileInfo> {
|
|||||||
for e in WalkDir::new(&dir) {
|
for e in WalkDir::new(&dir) {
|
||||||
let e = e.unwrap();
|
let e = e.unwrap();
|
||||||
let path = e.path();
|
let path = e.path();
|
||||||
if path.is_dir() {
|
println!(
|
||||||
|
"Path: {}, {}",
|
||||||
|
path.display(),
|
||||||
|
path.display().to_string().eq(&dir)
|
||||||
|
);
|
||||||
|
if path.display().to_string().eq(&dir) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let content = fs::read(path).unwrap();
|
if path.is_dir() {
|
||||||
let hash = get_hash(content).await;
|
let path_str = path.display().to_string();
|
||||||
let path_str = path.display().to_string();
|
let hash = get_hash(path_str.clone().into_bytes()).await;
|
||||||
let file_info = FileInfo {
|
let file_info = FileInfo {
|
||||||
relative_path: path_str[dir.len() + 1..].to_string(),
|
relative_path: path_str[dir.len() + 1..].to_string(),
|
||||||
path: path_str,
|
path: path_str,
|
||||||
hash: hash.clone(),
|
hash: hash.clone(),
|
||||||
};
|
is_dir: true,
|
||||||
hash_list.entry(hash).or_insert(file_info);
|
};
|
||||||
|
hash_list.entry(hash).or_insert(file_info);
|
||||||
|
} else {
|
||||||
|
let content = fs::read(path).unwrap();
|
||||||
|
let hash = get_hash(content).await;
|
||||||
|
let path_str = path.display().to_string();
|
||||||
|
let file_info = FileInfo {
|
||||||
|
relative_path: path_str[dir.len() + 1..].to_string(),
|
||||||
|
path: path_str,
|
||||||
|
hash: hash.clone(),
|
||||||
|
is_dir: false,
|
||||||
|
};
|
||||||
|
hash_list.entry(hash).or_insert(file_info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
println!("{:?}", hash_list);
|
||||||
hash_list
|
hash_list
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn compare_hashes(old: HashMap<String, FileInfo>, new: HashMap<String, FileInfo>) -> Zsdiff {
|
async fn compare_hashes(old: HashMap<String, FileInfo>, new: HashMap<String, FileInfo>) -> Zsdiff {
|
||||||
let mut diff_files: HashMap<String, Vec<u8>> = HashMap::new();
|
let mut diff_files: HashMap<String, Vec<u8>> = HashMap::new();
|
||||||
let mut remove_files: Vec<String> = vec![];
|
let mut remove_files: Vec<String> = vec![];
|
||||||
|
let mut remove_folders: Vec<String> = vec![];
|
||||||
let mut hashes: HashMap<String, String> = HashMap::new();
|
let mut hashes: HashMap<String, String> = HashMap::new();
|
||||||
for (_, info) in &old {
|
for (_, info) in &old {
|
||||||
remove_files.push(info.relative_path.clone());
|
if info.is_dir {
|
||||||
|
remove_folders.push(info.relative_path.clone());
|
||||||
|
} else {
|
||||||
|
remove_files.push(info.relative_path.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (new_hash, new_fileinfo) in &new {
|
for (new_hash, new_fileinfo) in &new {
|
||||||
let old_fileinfo = old.get(new_hash);
|
let old_fileinfo = old.get(new_hash);
|
||||||
remove_files.retain(|filename| !filename.eq(&new_fileinfo.relative_path));
|
if new_fileinfo.is_dir {
|
||||||
|
remove_folders.retain(|filename| !filename.eq(&new_fileinfo.relative_path));
|
||||||
|
} else {
|
||||||
|
remove_files.retain(|filename| !filename.eq(&new_fileinfo.relative_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if new_fileinfo.is_dir {
|
||||||
|
println!("{}", new_fileinfo.is_dir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if old_fileinfo.is_none() {
|
if old_fileinfo.is_none() {
|
||||||
let path = new_fileinfo.relative_path.clone();
|
let path = new_fileinfo.relative_path.clone();
|
||||||
@@ -62,6 +97,7 @@ async fn compare_hashes(old: HashMap<String, FileInfo>, new: HashMap<String, Fil
|
|||||||
diff_files: diff_files.keys().cloned().collect(),
|
diff_files: diff_files.keys().cloned().collect(),
|
||||||
hashes,
|
hashes,
|
||||||
remove_files,
|
remove_files,
|
||||||
|
remove_folders,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +131,7 @@ pub async fn zsdiff(
|
|||||||
"Compress ratio: {:.2?}%",
|
"Compress ratio: {:.2?}%",
|
||||||
size_after as f64 / size_before as f64 * 100.0
|
size_after as f64 / size_before as f64 * 100.0
|
||||||
);
|
);
|
||||||
print!("Time elapsed: {:.2?}s", elapsed);
|
print!("Time elapsed: {:.2?}", elapsed);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,13 @@ async fn create_tmp_dir(dir_name: String) -> Result<String, io::Error> {
|
|||||||
Ok(name)
|
Ok(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn extract_files(zsdiff: &Zsdiff, filename: &String) -> Result<String, io::Error> {
|
async fn load_file(filename: String) -> Result<Zsdiff, io::Error> {
|
||||||
|
let filename = &format!("{}.zdiff", filename);
|
||||||
|
let parts = utils::decompress_parts(read(filename)?).await?;
|
||||||
|
Ok(Zsdiff::from_vec(parts).await?)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn extract_files(zsdiff: &Zsdiff, filename: String) -> Result<String, io::Error> {
|
||||||
let tmp_dir_name = create_tmp_dir(filename.to_string()).await?;
|
let tmp_dir_name = create_tmp_dir(filename.to_string()).await?;
|
||||||
let path = Path::new(&tmp_dir_name);
|
let path = Path::new(&tmp_dir_name);
|
||||||
fs::remove_dir_all(path).ok();
|
fs::remove_dir_all(path).ok();
|
||||||
@@ -38,9 +44,7 @@ async fn check_hash(filename: String) -> Result<(), io::Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn zspatch(filename: String, dest_dir: String) -> Result<(), io::Error> {
|
async fn zspatch(filename: String, dest_dir: String) -> Result<(), io::Error> {
|
||||||
let filename = &format!("{}.zdiff", filename);
|
let diff = load_file(filename.clone()).await?;
|
||||||
let parts = utils::decompress_parts(read(filename)?).await?;
|
|
||||||
let diff = Zsdiff::from_vec(parts).await?;
|
|
||||||
let tmp_dir_name = extract_files(&diff, filename).await?;
|
let tmp_dir_name = extract_files(&diff, filename).await?;
|
||||||
let now = time::Instant::now();
|
let now = time::Instant::now();
|
||||||
for name in diff.content.keys().collect::<Vec<&String>>() {
|
for name in diff.content.keys().collect::<Vec<&String>>() {
|
||||||
@@ -55,6 +59,11 @@ async fn zspatch(filename: String, dest_dir: String) -> Result<(), io::Error> {
|
|||||||
fs::remove_file(path).ok();
|
fs::remove_file(path).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for folder in diff.metadata.remove_folders {
|
||||||
|
let path = Path::new(&dest_dir).join(folder);
|
||||||
|
fs::remove_dir_all(path).ok();
|
||||||
|
}
|
||||||
|
|
||||||
for (k, hash) in diff.metadata.hashes {
|
for (k, hash) in diff.metadata.hashes {
|
||||||
let path = Path::new(&dest_dir).join(k);
|
let path = Path::new(&dest_dir).join(k);
|
||||||
let content = read(path)?;
|
let content = read(path)?;
|
||||||
@@ -76,6 +85,8 @@ struct Args {
|
|||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
dest_dir: String,
|
dest_dir: String,
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
|
metadata: bool,
|
||||||
|
#[arg(short, long)]
|
||||||
hash_check: bool,
|
hash_check: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,5 +96,10 @@ async fn main() -> io::Result<()> {
|
|||||||
if args.hash_check {
|
if args.hash_check {
|
||||||
check_hash(args.filename.clone()).await?;
|
check_hash(args.filename.clone()).await?;
|
||||||
}
|
}
|
||||||
|
if args.metadata {
|
||||||
|
let diff = load_file(args.filename).await?;
|
||||||
|
println!("{}", serde_json::to_string(&diff.metadata)?);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
zspatch(args.filename, args.dest_dir).await
|
zspatch(args.filename, args.dest_dir).await
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user