Last active
May 26, 2024 00:26
-
-
Save murilobsd/684c5dbf5bc413aa43912c9f9e2bda19 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "vorpal" | |
version = "0.1.0" | |
edition = "2021" | |
[dependencies] | |
walkdir = "2.3.2" | |
ignore = "0.4.18" | |
sha2 = "0.10.2" | |
fs_extra = "1.2.0" | |
anyhow = "1.0.68" | |
rayon = "1.5.3" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn main() -> anyhow::Result<()> { | |
let src_dir = "."; | |
let dst_base_dir = "/tmp/zumba"; | |
let name = "zumba"; | |
paastel::build(src_dir, dst_base_dir, name)?; | |
Ok(()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fs; | |
use std::path::{Path, PathBuf}; | |
use anyhow::{Context, Result}; | |
use ignore::WalkBuilder; | |
use rayon::prelude::*; | |
use sha2::{Digest, Sha256}; | |
pub fn build<P: AsRef<Path>>( | |
src_dir: P, | |
dst_base_dir: P, | |
name: &str, | |
) -> Result<()> { | |
// Liste os arquivos e gere o hash concatenado | |
let (files_to_copy, concatenated_hash) = | |
list_files_and_generate_hash(src_dir.as_ref())?; | |
// Verifique se o diretório de destino já existe | |
let dst_dir = dst_base_dir | |
.as_ref() | |
.join(format!("{name}-{concatenated_hash}")); | |
if dst_dir.exists() { | |
println!("O diretório de destino '{}' já existe!", dst_dir.display()); | |
return Ok(()); | |
} | |
// Crie o diretório de destino e copie os arquivos mantendo a hierarquia | |
std::fs::create_dir_all(&dst_dir) | |
.context("Falha ao criar diretório de destino")?; | |
copy_files_with_hierarchy(&files_to_copy, src_dir.as_ref(), &dst_dir)?; | |
println!("Arquivos copiados para o diretório '{}'", dst_dir.display()); | |
Ok(()) | |
} | |
fn list_files_and_generate_hash( | |
src_dir: &Path, | |
) -> Result<(Vec<PathBuf>, String)> { | |
let files_to_copy: Vec<PathBuf> = WalkBuilder::new(src_dir) | |
.build() | |
.filter_map(|entry| { | |
let entry = entry.ok()?; | |
if entry.file_type().is_some() | |
&& entry.file_type().unwrap().is_file() | |
{ | |
Some(entry.path().to_path_buf()) | |
} else { | |
None | |
} | |
}) | |
.collect(); | |
let mut file_hashes: Vec<String> = files_to_copy | |
.par_iter() | |
.map(hash_file) | |
.collect::<Result<Vec<String>>>()?; | |
// Ordena os hashes dos arquivos | |
file_hashes.sort(); | |
// Concatena os hashes em uma única string | |
let concatenated_hash = generate_hash_from_hashes(&file_hashes)?; | |
Ok((files_to_copy, concatenated_hash)) | |
} | |
fn copy_files_with_hierarchy( | |
files_to_copy: &[PathBuf], | |
src_dir: &Path, | |
dst_dir: &Path, | |
) -> Result<()> { | |
files_to_copy.par_iter().try_for_each(|file| { | |
let relative_path = file | |
.strip_prefix(src_dir) | |
.context("Falha ao obter caminho relativo")?; | |
let dst_file = dst_dir.join(relative_path); | |
if let Some(parent) = dst_file.parent() { | |
fs::create_dir_all(parent) | |
.context("Falha ao criar diretório pai no destino")?; | |
} | |
fs::copy(file, dst_file).context("Falha ao copiar arquivo")?; | |
Ok::<(), anyhow::Error>(()) | |
})?; | |
Ok(()) | |
} | |
fn hash_file<P: AsRef<Path>>(path: P) -> Result<String> { | |
let mut file = | |
fs::File::open(&path).context("Falha ao abrir arquivo para hash")?; | |
let mut hasher = Sha256::new(); | |
std::io::copy(&mut file, &mut hasher) | |
.context("Falha ao ler arquivo para hash")?; | |
let hash = hasher.finalize(); | |
Ok(format!("{:x}", hash)) | |
} | |
fn generate_hash_from_hashes(hashes: &[String]) -> Result<String> { | |
let mut hasher = Sha256::new(); | |
for hash in hashes { | |
hasher.update(hash.as_bytes()); | |
} | |
let final_hash = hasher.finalize(); | |
Ok(format!("{:x}", final_hash)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment