diff --git a/crates/keyfork-shard/src/openpgp.rs b/crates/keyfork-shard/src/openpgp.rs index 70724c9..ccfefe9 100644 --- a/crates/keyfork-shard/src/openpgp.rs +++ b/crates/keyfork-shard/src/openpgp.rs @@ -194,33 +194,35 @@ impl OpenPGP

{ } impl OpenPGP

{ - /// Read all OpenPGP certificates in a path and return a [`Vec`] of them. Certificates are read - /// from a file, or from files one level deep in a directory. + /// Read all OpenPGP certificates in a path and return a [`Vec`] of them. + /// + /// Certificates are read from a file, or from files one level deep in a directory. + /// Certificates with duplicated fingerprints will be discarded. /// /// # Errors - /// The function may return an error if it is unable to read the directory or if Sequoia is unable - /// to load certificates from the file. + /// The function may return an error if it is unable to read the directory or if Sequoia is + /// unable to load certificates from the file. pub fn discover_certs(path: impl AsRef) -> Result> { let path = path.as_ref(); + let mut certs = HashMap::new(); if path.is_file() { - let mut vec = vec![]; - for cert in CertParser::from_file(path).map_err(Error::Sequoia)? { - vec.push(cert.map_err(Error::Sequoia)?); + for maybe_cert in CertParser::from_file(path).map_err(Error::Sequoia)? { + let cert = maybe_cert.map_err(Error::Sequoia)?; + certs.insert(cert.fingerprint(), cert); } - Ok(vec) } else { - let mut vec = vec![]; for entry in path .read_dir() .map_err(Error::Io)? .filter_map(Result::ok) .filter(|p| p.path().is_file()) { - vec.push(Cert::from_file(entry.path()).map_err(Error::Sequoia)?); + let cert = Cert::from_file(entry.path()).map_err(Error::Sequoia)?; + certs.insert(cert.fingerprint(), cert); } - Ok(vec) } + Ok(certs.into_values().collect()) } }