dirhash_fast 0.1.1

A high-performance tool for hashing directory trees
Documentation
use std::path::Path;
use std::fs::File;
use std::io::{BufReader,Read};
use walkdir::WalkDir;
use rayon::prelude::*;

use crate::file::path::os_path::get_encoded_path;


fn hash_file(path: &Path) -> Option<String> {
    let file = File::open(path).ok()?;
    let mut reader = BufReader::new(file);

    let mut hasher = blake3::Hasher::new();
    
    let mut buffer = [0; 8192];
    
    while let Ok(bytes_read) = reader.read(&mut buffer) {
        if bytes_read == 0 { break; }
        hasher.update(&buffer[..bytes_read]);
    }
    
    Some(hasher.finalize().to_hex().to_string())
}

pub fn hash_directory(dir: &Path) -> String {
    let mut hasher = blake3::Hasher::new();
    
    let mut entries: Vec<_> = WalkDir::new(dir)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| e.file_type().is_file())
        .collect();

    entries.sort_by(|a, b| a.path().cmp(b.path()));

    let hashes: Vec<_> = entries
        .into_par_iter()
        .filter_map(|entry| hash_file(entry.path()).map(|h| (get_encoded_path(entry.path()), h)))
        .collect();
    
    for (path, hash) in hashes {
        hasher.update(&path);
        hasher.update(hash.as_bytes());
    }
    
    hasher.finalize().to_hex().to_string()
}


#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::File;
    use std::io::Write;
    use tempfile::tempdir;
    
    #[test]
    fn test_hash_directory() {
        let dir = tempdir().expect("Failed to create temp directory");
        let file_path = dir.path().join("testfile.txt");
        
        let mut file = File::create(&file_path).expect("Failed to create temp file");
        writeln!(file, "Hello, world!").expect("Failed to write to temp file");
        
        let hash1 = hash_directory(dir.path());
        assert!(!hash1.is_empty(), "Hash should not be empty");
        
        let hash2 = hash_directory(dir.path());
        assert_eq!(hash1, hash2, "Hashes should be deterministic");
    }
}