Skip to content

Commit

Permalink
feat: add gix commit verify-signature to do something akin to `git …
Browse files Browse the repository at this point in the history
…... --show-signature`.
  • Loading branch information
Byron committed Aug 8, 2023
1 parent 5c13459 commit cd6cfe4
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
41 changes: 40 additions & 1 deletion gitoxide-core/src/repository/commit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,43 @@
use anyhow::{Context, Result};
use anyhow::{anyhow, bail, Context, Result};
use std::io::Write;
use std::process::Stdio;

/// Note that this is a quick implementation of commit signature verification that ignores a lot of what
/// git does and can do, while focussing on the gist of it.
/// For this to go into `gix`, one will have to implement many more options and various validation programs.
pub fn verify(repo: gix::Repository, rev_spec: Option<&str>) -> Result<()> {
let rev_spec = rev_spec.unwrap_or("HEAD");
let commit = repo
.rev_parse_single(format!("{rev_spec}^{{commit}}").as_str())?
.object()?
.into_commit();
let (signature, signed_data) = commit
.signature()
.context("Could not parse commit to obtain signature")?
.ok_or_else(|| anyhow!("Commit at {rev_spec} is not signed"))?;

let mut signature_storage = tempfile::NamedTempFile::new()?;
signature_storage.write_all(signature.as_ref())?;
let signed_storage = signature_storage.into_temp_path();

let mut cmd = std::process::Command::new("gpg");
cmd.args(["--keyid-format=long", "--status-fd=1", "--verify"])
.arg(&signed_storage)
.arg("-")
.stdin(Stdio::piped());
gix::trace::debug!("About to execute {cmd:?}");
let mut child = cmd.spawn()?;
child
.stdin
.take()
.expect("configured")
.write_all(signed_data.to_bstring().as_ref())?;

if !child.wait()?.success() {
bail!("Command {cmd:?} failed");
}
Ok(())
}

pub fn describe(
mut repo: gix::Repository,
Expand Down
11 changes: 11 additions & 0 deletions src/plumbing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,17 @@ pub fn main() -> Result<()> {
),
},
Subcommands::Commit(cmd) => match cmd {
commit::Subcommands::Verify { rev_spec } => prepare_and_run(
"commit-verify",
trace,
auto_verbose,
progress,
progress_keep_open,
None,
move |_progress, _out, _err| {
core::repository::commit::verify(repository(Mode::Lenient)?, rev_spec.as_deref())
},
),
commit::Subcommands::Describe {
annotated_tags,
all_refs,
Expand Down
5 changes: 5 additions & 0 deletions src/plumbing/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,11 @@ pub mod tree {
pub mod commit {
#[derive(Debug, clap::Subcommand)]
pub enum Subcommands {
/// Verify the signature of a commit.
Verify {
/// A specification of the revision to verify, or the current `HEAD` if unset.
rev_spec: Option<String>,
},
/// Describe the current commit or the given one using the name of the closest annotated tag in its ancestry.
Describe {
/// Use annotated tag references only, not all tags.
Expand Down

0 comments on commit cd6cfe4

Please sign in to comment.