use diff::Result; use hex; use log::{debug, trace}; use sha3::{Digest, Sha3_256}; use std::fs; use std::io::{self, Error}; use std::path::Path; pub(crate) fn filesum_filtered( path: &Path, oldfile: &mut String, diff_string: &mut String, re: Option<®ex::Regex>, ) -> io::Result<(bool, String)> { // Open file for hashing match re { Some(v) => debug!("try to open file {:?} for hashing using filter regex {}", path, v), None => debug!("try to open file {:?} for hashing", path), } let mut hasher = Sha3_256::new(); let mut filedata = String::with_capacity(2048); let mut changed = false; // we read only smal files, so its fast to read the whole file to memory, so we can also du a diff if let Ok(file_contents) = fs::read_to_string(path) { if let Some(re) = re { debug!("Filter lines with regex {:?}", re); for line in file_contents.lines() { if re.is_match(line) { trace!("line {} skipped by filter regex", line); continue; } // Update the hasher with the bytes filedata.push_str(line); } } else { // we do not have a filter regex, so we could simply paste the file to the hasher debug!("Hash file without filter regex"); filedata = file_contents; } hasher.update(format!("{}\n", filedata).as_bytes()); if !oldfile.is_empty() && *oldfile != filedata { diff_string.clear(); for diff in diff::lines(oldfile, &filedata) { match diff { Result::Left(l) => { trace!("Diff - {}", l); // Removed line diff_string.push_str(&format!("-{}\n", l)); } Result::Both(l, _) => { trace!("Diff {}", l); // Unchanged line } Result::Right(r) => { trace!("Diff + {}", r); // Added line diff_string.push_str(&format!("+{}\n", r)); } } } debug!("Diff for {:?} is now {}", path, diff_string); changed = true; *oldfile = filedata; } else if oldfile.is_empty() { *oldfile = filedata; } // Finalize the hash and convert it to a hexadecimal string let hash = hex::encode(hasher.finalize()); return Ok((changed, hash)); } Err(Error::other(format!("Unable to read file {:?}", path))) }