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:
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"));
}