From f4d7b58489965b1af88dd9ad166b49ae2200ba31 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 30 Dec 2024 12:15:19 +0000 Subject: [PATCH] impl signature rm command --- src/main.rs | 27 +++++++++++++++++++++ src/rm.rs | 3 +++ src/rm/signature.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/rm.rs create mode 100644 src/rm/signature.rs diff --git a/src/main.rs b/src/main.rs index f69a412..29f77a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod pull; mod push; mod raw; mod rev_lookup; +mod rm; mod shell_completions; mod sign; mod utils; @@ -29,6 +30,9 @@ enum Action { /// Primitive signing and verification commands #[command(subcommand)] Raw(RawAction), + /// Remove git-signify data + #[command(subcommand)] + Rm(RmAction), /// Hash a key and return it Fingerprint { /// The path to the base64 encoded key to hash @@ -111,6 +115,24 @@ enum RawAction { }, } +#[derive(Subcommand)] +enum RmAction { + /// Remove git-signify signatures + Signature { + /// The path to the base64 encoded public key of the signer + #[arg(short = 'k', long, env = "GIT_KEY_PUB")] + public_key: PathBuf, + + /// The name of the remote repository, in case + /// we wish to remove a remote signature + #[arg(short = 'R', long)] + remote: Option, + + /// The git revision whose signature we wish to remove + git_rev: String, + }, +} + fn main() -> Result<()> { let args = Args::parse(); @@ -124,6 +146,11 @@ fn main() -> Result<()> { print_signed_oid: recover, git_tree: rev, }) => raw::verify::command(public_key, recover, rev), + Action::Rm(RmAction::Signature { + public_key, + git_rev, + remote, + }) => rm::signature::command(public_key, git_rev, remote), Action::Fingerprint { key } => fingerprint::command(key), Action::Sign { secret_key, diff --git a/src/rm.rs b/src/rm.rs new file mode 100644 index 0000000..07e7e1a --- /dev/null +++ b/src/rm.rs @@ -0,0 +1,3 @@ +//! Remove git-signify data. + +pub mod signature; diff --git a/src/rm/signature.rs b/src/rm/signature.rs new file mode 100644 index 0000000..6582c7d --- /dev/null +++ b/src/rm/signature.rs @@ -0,0 +1,58 @@ +//! Remove git-signify signatures. + +use std::fs; +use std::io; +use std::path::PathBuf; +use std::process::Command; + +use anyhow::{anyhow, Context, Result}; + +use crate::utils; + +/// Execute the `rm signature` command. +pub fn command(public_key: PathBuf, rev: String, remote: Option) -> Result<()> { + let repo = utils::open_repository()?; + + for public_key in utils::get_public_keys(public_key)?.into_values() { + let tree_rev = { + let object_oid = repo + .revparse_single(&rev) + .context("Failed to look-up git object")? + .id(); + let key_fingerprint = public_key.fingerprint()?; + utils::craft_signature_reference(key_fingerprint, object_oid) + }; + + if let Some(remote) = remote.as_ref() { + let exit_code = Command::new("git") + .arg("push") + .arg("-d") + .arg(remote) + .arg(tree_rev) + .spawn() + .context("Failed to spawn git command to remove remote signature")? + .wait() + .context("Failed to wait for git command to remove remote signature")?; + if !exit_code.success() { + return Err(anyhow!("Exit code of git: {exit_code}")); + } + } else { + let mut path = PathBuf::new(); + + path.push(".git"); + path.push(tree_rev); + + fs::remove_file(path) + .or_else(|e| { + if e.kind() == io::ErrorKind::NotFound { + Ok(()) + } else { + Err(e) + } + }) + .context("Failed to remove local git reference")?; + } + } + + Ok(()) +} -- 2.51.2