This commit is contained in:
2025-10-17 11:34:59 +03:00
parent 9d9beefe7f
commit 561400ae3c
6 changed files with 24 additions and 24 deletions

70
src/zspatch.rs Normal file
View File

@@ -0,0 +1,70 @@
mod utils;
use clap::Parser;
use std::fs::read;
use std::io::Write;
use std::path::Path;
use std::{fs, io};
use utils::Zsdiff;
async fn create_tmp_dir(dir_name: String) -> Result<String, io::Error> {
let name = format!("{}.tmp", dir_name);
fs::remove_dir_all(name.clone()).ok();
fs::DirBuilder::new().create(name.clone())?;
Ok(name)
}
async fn extract_files(zsdiff: &Zsdiff, filename: &String) -> Result<String, io::Error> {
let tmp_dir_name = create_tmp_dir(filename.to_string()).await?;
let path = Path::new(&tmp_dir_name);
fs::remove_dir_all(path).ok();
for (f, c) in zsdiff.content.iter() {
let filepath = path.join(f);
fs::create_dir_all(filepath.parent().unwrap())?;
fs::File::create(&filepath)?.write_all(c)?;
}
Ok(tmp_dir_name)
}
async fn zpatch(filename: String, dest_dir: String) -> Result<(), io::Error> {
let filename = &format!("{}.zdiff", filename);
let parts = utils::decompress_parts(read(filename)?).await?;
let diff = Zsdiff::from_vec(parts).await?;
let tmp_dir_name = extract_files(&diff, filename).await?;
for name in diff.content.keys().collect::<Vec<&String>>() {
let from_path = Path::new(&tmp_dir_name).join(name);
let to_path = Path::new(&dest_dir).join(name);
fs::create_dir_all(to_path.parent().unwrap())?;
fs::copy(from_path, to_path)?;
}
for file in diff.metadata.remove_files {
let path = Path::new(&dest_dir).join(file);
fs::remove_file(path).ok();
}
for (k, hash) in diff.metadata.hashes {
let path = Path::new(&dest_dir).join(k);
let content = read(path)?;
let fs_hash = utils::get_hash(&content).await;
if !fs_hash.eq(&hash) {
Err(io::Error::new(io::ErrorKind::Other, "Hash mismatch"))?
}
}
Ok(())
}
#[derive(Parser, Debug)]
struct Args {
#[arg(short, long)]
filename: String,
#[arg(short, long)]
dest_dir: String,
}
#[tokio::main]
async fn main() -> io::Result<()> {
let args = Args::parse();
zpatch(args.filename, args.dest_dir).await?;
Ok(())
}