kitab

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | LICENSE

commit a10b02ce31440618574a3ca4b9049ad3b03d9476
parent c9357fc4f409a65f6f029104ac4001d53e11942d
Author: lash <dev@holbrook.no>
Date:   Sun, 25 Sep 2022 20:25:38 +0000

Prepare enable define multiple digest types for apply

Diffstat:
MCargo.toml | 5+++++
Msrc/digest.rs | 35+++++++++++++++++++++++++++++++++++
Msrc/main.rs | 40++++++++++++++++++++++------------------
Msrc/meta.rs | 58+++++++++++++++++++++++++++++++++-------------------------
4 files changed, 95 insertions(+), 43 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -51,7 +51,12 @@ version = "0.7.1" version = "0.2.3" optional = true +[dependencies.md5] +version = "0.7.0" +optional = true + [features] #rdf = ["rio_turtle", "rio_api"] #dump_bibtex = ["biblatex"] magic = ["tree_magic"] +digest_md5 = ["md5"] diff --git a/src/digest.rs b/src/digest.rs @@ -1,4 +1,5 @@ use std::marker::Copy; +use std::fmt; use crate::error::ParseError; @@ -10,6 +11,12 @@ use sha2::{ use log::error; +pub enum DigestType { + Sha512, + #[cfg(feature="digest_md5")] + MD5, +} + /// Encapsulations of supported digests for digest data. pub enum RecordDigest { Sha512(Vec<u8>), @@ -61,8 +68,36 @@ impl RecordDigest { }, } } + + /// Returns the digest value of the media as a hex-encoded string. + /// + /// TODO: implememt in fmt for digest instead + pub fn urn(&self) -> String { + match self { + RecordDigest::Empty => { + return String::new(); + }, + RecordDigest::Sha512(v) => { + return String::from("sha512:") + hex::encode(&v).as_str(); + }, + RecordDigest::Sha256(v) => { + return String::from("sha256:") + hex::encode(&v).as_str(); + }, + RecordDigest::MD5(v) => { + return String::from("md5:") + hex::encode(&v).as_str(); + }, + RecordDigest::SwarmHash(v) => { + return hex::encode(&v); + }, + } + } } +impl fmt::Debug for RecordDigest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.urn()) + } +} /// Create a [RecordDigest::Sha512](RecordDigest::Sha512) instance from the raw digest data. /// diff --git a/src/main.rs b/src/main.rs @@ -38,10 +38,11 @@ use kitab::biblatex::{ }; use kitab::meta::{ MetaData, - digest_from_path, + digests_from_path, }; use kitab::digest::from_urn; use kitab::digest::RecordDigest; +use kitab::digest::DigestType; fn args_setup() -> ArgMatches<'static> { @@ -235,27 +236,30 @@ fn exec_import_biblatex(f: &Path, index_path: &Path, digests: &Vec<RecordDigest> true } -fn exec_apply(p: &Path, index_path: &Path) -> bool { +fn exec_apply(p: &Path, index_path: &Path, mut extra_digest_types: Vec<DigestType>) -> bool { + let mut digest_types: Vec<DigestType> = vec!(DigestType::Sha512); + digest_types.append(&mut extra_digest_types); for entry in WalkDir::new(&p) .into_iter() .filter_map(Result::ok) .filter(|e| !e.file_type().is_dir()) { let ep = entry.path(); - let z = digest_from_path(ep); - let z_hex = hex::encode(z); - - let fp = index_path.join(&z_hex); - match fp.canonicalize() { - Ok(v) => { - let f = File::open(&v).unwrap(); - let m = rdf_read(f); - info!("apply {:?} -> {:?} for {:?}", entry, &m, z_hex); - m.to_xattr(&ep); - }, - Err(e) => { - debug!("metadata not found for {:?} -> {:?}", entry, z_hex); - }, - }; + for digest in digests_from_path(ep, &digest_types) { + let z_hex = hex::encode(digest.fingerprint()); + + let fp = index_path.join(&z_hex); + match fp.canonicalize() { + Ok(v) => { + let f = File::open(&v).unwrap(); + let m = rdf_read(f); + info!("apply {:?} -> {:?} for {:?}", entry, &m, &digest); + m.to_xattr(&ep); + }, + Err(e) => { + debug!("metadata not found for {:?} -> {:?}", entry, z_hex); + }, + }; + } } true } @@ -339,7 +343,7 @@ fn main() { Some(v) => { let p = str_to_path(v); info!("apply from path {:?}", &p); - if !exec_apply(p.as_path(), index_dir.as_path()) { + if !exec_apply(p.as_path(), index_dir.as_path(), vec!()) { r = false; } }, diff --git a/src/meta.rs b/src/meta.rs @@ -25,6 +25,9 @@ use std::os::linux::fs::MetadataExt; use biblatex::EntryType; +#[cfg(feature = "md5")] +use md5::Context; + #[cfg(feature = "magic")] use tree_magic; @@ -65,13 +68,36 @@ pub struct MetaData { publish_date: PublishDate, } +pub fn digests_from_path(filepath: &path::Path, digest_types: &Vec<digest::DigestType>) -> Vec<digest::RecordDigest> { + let mut r: Vec<digest::RecordDigest> = vec!(); + for v in digest_types { + match v { + digest::DigestType::Sha512 => { + let digest = digest_sha512_from_path(filepath); + r.push(digest); + }, + #[cfg(feature = "md5")] + digest::DigestType::MD5 => { + let digest = digest_md5_from_path(filepath); + r.push(digest); + }, + }; + } + r +} + +#[cfg(feature = "md5")] +pub fn digest_md5_from_path(filepath: &path::Path) -> digest::RecordDigest { + let ctx = md5::Context::new(); + digest::RecordDigest::MD5(vec!()) +} /// Generates the native `sha512` digest of a file. /// /// # Arguments /// /// * `filepath` - Absolute path to file to calculate digest for. -pub fn digest_from_path(filepath: &path::Path) -> Vec<u8> { +pub fn digest_sha512_from_path(filepath: &path::Path) -> digest::RecordDigest { let mut h = Sha512::new(); let st = metadata(filepath).unwrap(); let bs: u64 = st.st_blksize(); @@ -84,7 +110,8 @@ pub fn digest_from_path(filepath: &path::Path) -> Vec<u8> { h.update(&b[..c]); i += c; } - h.finalize().to_vec() + let r = h.finalize().to_vec(); + digest::RecordDigest::Sha512(r) } impl MetaData { @@ -209,30 +236,11 @@ impl MetaData { self.dc.language.clone() } - /// Returns the digest value of the media as a hex-encoded string. /// - /// TODO: implememt in fmt for digest instead pub fn urn(&self) -> String { - match &self.digest { - digest::RecordDigest::Empty => { - return String::new(); - }, - digest::RecordDigest::Sha512(v) => { - return String::from("sha512:") + hex::encode(&v).as_str(); - }, - digest::RecordDigest::Sha256(v) => { - return String::from("sha256:") + hex::encode(&v).as_str(); - }, - digest::RecordDigest::MD5(v) => { - return String::from("md5:") + hex::encode(&v).as_str(); - }, - digest::RecordDigest::SwarmHash(v) => { - return hex::encode(&v); - }, - } + self.digest.urn() } - /// pub fn fingerprint(&self) -> String { let digest_fingerprint = self.digest.fingerprint(); @@ -248,8 +256,8 @@ impl MetaData { let filename: FileName; debug!("Calculate digest for file {:?}", &filepath); - let digest = digest_from_path(filepath); - debug!("Calculated digest {} for file {:?}", hex::encode(&digest), &filepath); + let digest = digest_sha512_from_path(filepath); + debug!("Calculated digest {} for file {:?}", hex::encode(digest.fingerprint()), &filepath); filename = filepath.file_name() .unwrap() @@ -292,7 +300,7 @@ impl MetaData { None => {}, } - let mut metadata = MetaData::new(title.as_str(), author.as_str(), typ, digest::RecordDigest::Sha512(digest), Some(filename)); + let mut metadata = MetaData::new(title.as_str(), author.as_str(), typ, digest, Some(filename)); if !metadata.validate() { return Err(ParseError::new("invalid input")); }