commit 88080f1563b78b2114c5a011785b057a2f117010
parent 120b3b63a71b3a0ce0d54f4e8bc6e91a60d3d671
Author: lash <dev@holbrook.no>
Date:   Wed, 28 Sep 2022 07:42:14 +0000
Add multiple digests for xattr import
Diffstat:
3 files changed, 82 insertions(+), 32 deletions(-)
diff --git a/src/biblatex.rs b/src/biblatex.rs
@@ -77,8 +77,6 @@ pub fn read_all(mut r: impl Read, digests: &Vec<RecordDigest>) -> Result<Vec<Met
         // use clone instead
         let digest = parse_digest(&e);
         match digest {
-            RecordDigest::Empty => {
-            },
             RecordDigest::Sha512(r) => {
                 use_digests.push(RecordDigest::Sha512(r));
             },
@@ -91,6 +89,8 @@ pub fn read_all(mut r: impl Read, digests: &Vec<RecordDigest>) -> Result<Vec<Met
             RecordDigest::SwarmHash(r) => {
                 use_digests.push(RecordDigest::SwarmHash(r));
             },
+            _ => {
+            },
         }
 
         for v in digests {
diff --git a/src/digest.rs b/src/digest.rs
@@ -1,4 +1,5 @@
 use std::marker::Copy;
+use std::io::Read;
 use std::fmt;
 use std::str::FromStr;
 
@@ -12,6 +13,7 @@ use sha2::{
 
 use log::error;
 
+#[derive(Copy, Clone)]
 pub enum DigestType {
     Sha512,
     #[cfg(feature="digest_md5")]
@@ -35,21 +37,25 @@ impl FromStr for DigestType {
     }
 }
 
+impl DigestType {
+    pub fn digest_for(&self, f: impl Read) -> RecordDigest {
+        RecordDigest::Empty 
+    }
+}
+
 /// Encapsulations of supported digests for digest data.
 pub enum RecordDigest {
     Sha512(Vec<u8>),
     Sha256(Vec<u8>),
     MD5(Vec<u8>),
     SwarmHash(Vec<u8>),
+    EmptyWithType(DigestType),
     Empty,
 }
 
 impl Clone for RecordDigest {
     fn clone(&self) -> RecordDigest {
         match self {
-            RecordDigest::Empty => {
-                RecordDigest::Empty
-            },
             RecordDigest::Sha512(v) => {
                 RecordDigest::Sha512(v.to_vec())
             },
@@ -62,6 +68,9 @@ impl Clone for RecordDigest {
             RecordDigest::SwarmHash(v) => {
                 RecordDigest::SwarmHash(v.to_vec())
             },
+            _ => {
+                RecordDigest::Empty
+            },
         }
     }
 }
@@ -69,9 +78,6 @@ impl Clone for RecordDigest {
 impl RecordDigest {
     pub fn fingerprint(&self) -> Vec<u8> {
         match self {
-            RecordDigest::Empty => {
-                return vec!();
-            },
             RecordDigest::Sha512(v) => {
                 return v.to_vec();
             },
@@ -84,6 +90,9 @@ impl RecordDigest {
             RecordDigest::SwarmHash(v) => {
                 return v.to_vec();
             },
+            _ => {
+                return vec!()
+            },
         }
     }
 
@@ -92,9 +101,6 @@ impl RecordDigest {
     /// 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();
             },
@@ -107,6 +113,9 @@ impl RecordDigest {
             RecordDigest::SwarmHash(v) => {
                 return hex::encode(&v);
             },
+            _ => {
+                return String::new();
+            },
         }
     }
 }
@@ -139,7 +148,14 @@ pub fn from_urn(urn: &str) -> Result<RecordDigest, ParseError> {
     let mut v = urn.split(":");
     let r = match v.next() {
         Some("sha512") => {
-            let digest_hex = v.next().unwrap();
+            let digest_hex = match v.next() {
+                Some(r) => {
+                    r
+                },
+                None => {
+                    return Err(ParseError::new("not a valid digest urn"));
+                },
+            };
             let digest = hex::decode(digest_hex).unwrap();
             match from_vec(digest) {
                 Ok(vv) => {
@@ -162,7 +178,14 @@ pub fn from_urn(urn: &str) -> Result<RecordDigest, ParseError> {
             RecordDigest::Sha256(digest)
         },
         Some("md5") => {
-            let digest_hex = v.next().unwrap();
+            let digest_hex = match v.next() {
+                Some(r) => {
+                    r
+                },
+                None => {
+                    return Err(ParseError::new("not a valid digest urn"));
+                },
+            };
             let digest = hex::decode(digest_hex).unwrap();
 
             if digest.len() != 16 {
diff --git a/src/main.rs b/src/main.rs
@@ -188,8 +188,8 @@ fn store(index_path: &Path, m: &MetaData) {
     debug!("stored as rdf {:?}", fp);
 }
 
-fn exec_import_xattr(f: &Path, index_path: &Path) -> bool {
-    let m = match MetaData::from_xattr(f) {
+fn exec_import_xattr(f: &Path, index_path: &Path, digests: &Vec<RecordDigest>) -> bool {
+    let mut m = match MetaData::from_xattr(f) {
         Ok(r) => {
             r
         }
@@ -201,7 +201,27 @@ fn exec_import_xattr(f: &Path, index_path: &Path) -> bool {
     debug!("successfully processed xattr import source");
 
     info!("importing xattr source {:?}", &m);
-    store(index_path, &m);
+
+    let mut digest_types: Vec<DigestType> = vec!();
+
+    for v in digests.iter() {
+        match v {
+            RecordDigest::EmptyWithType(digest_typ) => {
+                digest_types.push(*digest_typ);
+            },
+            RecordDigest::Empty => {
+                digest_types.push(DigestType::Sha512);
+            },
+            _ => {
+                warn!("digest specifier {:?} is invalid in xattr import context.", v);
+            },
+        };
+    }
+
+    for v in digests_from_path(f, &digest_types) {
+        m.set_fingerprint(v);
+        store(index_path, &m);
+    }
     true
 }
 
@@ -240,7 +260,7 @@ fn exec_import_biblatex(f: &Path, index_path: &Path, digests: &Vec<RecordDigest>
 
     for m in entries {
         info!("importing biblatex source {:?}", &m);
-        store(index_path, &m);    
+        store(index_path, &m);
     }
 
     true
@@ -282,8 +302,7 @@ fn exec_import(p: &Path, index_path: &Path, digests: Vec<RecordDigest>) {
 
         let fp = entry.path();
         debug!("attempt xattr import {:?}", fp);
-        //if exec_import_xattr(fp, index_path, &digests) {
-        if exec_import_xattr(fp, index_path) {
+        if exec_import_xattr(fp, index_path, &digests) {
             continue;
         }
 
@@ -294,7 +313,6 @@ fn exec_import(p: &Path, index_path: &Path, digests: Vec<RecordDigest>) {
         }
 
         debug!("attempt rdf import {:?}", fp);
-        //if exec_import_rdf(fp, index_path, &digests) {
         if exec_import_rdf(fp, index_path) { 
             continue;
         } 
@@ -334,7 +352,16 @@ fn main() {
                                 digests.push(digest);
                             },
                             Err(e) => {
-                                panic!("invalid digest URN: {:?}", e);
+                                let digest_type = match DigestType::from_str(digest_str) {
+                                    Ok(v) => {
+                                        v
+                                    },
+                                    Err(e) => {
+                                        panic!("invalid digest specifier: {:?}", e);
+                                    },
+                                };
+                                let digest_empty = RecordDigest::EmptyWithType(digest_type);
+                                digests.push(digest_empty);
                             },
                         }
                     }
@@ -356,7 +383,7 @@ fn main() {
             match arg.values_of("adddigest") {
                 Some(r) => {
                     for digest_str in r {
-                        match DigestType::from_str(&digest_str) {
+                        match DigestType::from_str(digest_str.clone()) {
                             Ok(digest) => {
                                 info!("using digest type {}", digest_str);
                                 digests.push(digest);
@@ -378,14 +405,14 @@ fn main() {
         _ => {},
     }
 
-    match args.subcommand_matches("new") {
-        Some(v) => {
-            let p = str_to_path(v);
-            info!("new metadata for path {:?}", &p);
-            if !exec_entry(p.as_path(), index_dir.as_path()) {
-                r = false; 
-            }
-        },
-        _ => {},
-    }
+//    match args.subcommand_matches("new") {
+//        Some(v) => {
+//            let p = str_to_path(v);
+//            info!("new metadata for path {:?}", &p);
+//            if !exec_entry(p.as_path(), index_dir.as_path()) {
+//                r = false; 
+//            }
+//        },
+//        _ => {},
+//    }
 }