diff --git a/src/raw/verify.rs b/src/raw/verify.rs index edc4f6a..16cae35 100644 --- a/src/raw/verify.rs +++ b/src/raw/verify.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use anyhow::Result; +use either::*; use git2::{Oid, Repository}; use crate::utils; @@ -11,10 +12,15 @@ use crate::utils; pub fn command(key_path: PathBuf, recover: bool, tree_rev: String) -> Result<()> { let repo = utils::open_repository()?; for public_key in utils::get_public_keys(key_path)?.into_values() { - let recovered_oid = verify(&repo, &public_key, &tree_rev, recover)?; - if let Some(recovered_oid) = recovered_oid { - println!("{recovered_oid}"); - } + verify(&repo, &public_key, &tree_rev, recover)?.either( + |_| anyhow::bail!("No signature found for tree {tree_rev}"), + |recovered_oid| { + if let Some(recovered_oid) = recovered_oid { + println!("{recovered_oid}"); + } + Ok(()) + }, + )?; } Ok(()) } @@ -25,8 +31,13 @@ pub fn verify( public_key: &utils::PublicKey, tree_rev: &str, recover: bool, -) -> Result> { - let tree_sig = utils::TreeSignature::load(repo, tree_rev)?; +) -> Result>> { + let Some(tree_sig) = utils::TreeSignature::load(repo, tree_rev)? else { + return Ok(Left(())); + }; tree_sig.verify(public_key)?; - recover.then(|| tree_sig.dereference()).transpose() + recover + .then(|| tree_sig.dereference()) + .transpose() + .map(Right) } diff --git a/src/utils.rs b/src/utils.rs index 053131f..6acc4b3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,7 +8,7 @@ use std::io::Cursor; use std::path::{Path, PathBuf}; use anyhow::{anyhow, Context, Result}; -use git2::{Blob, Object, ObjectType, Oid, Repository, RepositoryOpenFlags}; +use git2::{Blob, ErrorCode, Object, ObjectType, Oid, Repository, RepositoryOpenFlags}; use libsignify::Codeable; use zeroize::Zeroizing; @@ -155,14 +155,15 @@ pub struct TreeSignature<'repo> { impl<'repo> TreeSignature<'repo> { /// Load a [`TreeSignature`] at the given `tree_rev` from the - /// provided git repository. + /// provided git repository. The value of `tree_rev` is expected + /// to follow the refspec [`ALL_SIGNIFY_SIGNATURE_REFS`]. #[inline] - pub fn load(repo: &'repo Repository, tree_rev: &str) -> Result { - let oid = repo - .revparse_single(tree_rev) - .context("Failed to look-up git tree oid")? - .id(); - Self::load_oid(repo, oid) + pub fn load(repo: &'repo Repository, tree_rev: &str) -> Result> { + match repo.revparse_single(tree_rev) { + Ok(obj) => Self::load_oid(repo, obj.id()).map(Some), + Err(e) if e.code() == ErrorCode::NotFound => Ok(None), + Err(e) => Err(e).context("Failed to look-up tree signature"), + } } /// Like [`TreeSignature::load`], but uses a concrete revision pointing diff --git a/src/verify.rs b/src/verify.rs index 022bfd4..d5bcf16 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -20,8 +20,11 @@ pub fn command(key_path: PathBuf, rev: String) -> Result<()> { let key_fingerprint = public_key.fingerprint()?; utils::craft_signature_reference(key_fingerprint, object_oid) }; - verify(&repo, &public_key, &tree_rev, false)?; - println!("Signature verified successfully with {}", path.display()); + if verify(&repo, &public_key, &tree_rev, false)?.is_right() { + println!("Signature verified successfully with {}", path.display()); + } else { + println!("No signature found for key {}", path.display()); + } } Ok(()) }