Skip to content

Commit d99f30d

Browse files
committed
Support git commit signing using OpenPGP
1 parent 48eed05 commit d99f30d

File tree

5 files changed

+385
-15
lines changed

5 files changed

+385
-15
lines changed

Diff for: asyncgit/src/error.rs

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ pub enum Error {
7676
///
7777
#[error("path string error")]
7878
PathString,
79+
80+
///
81+
#[error("sign builder error: {0}")]
82+
SignBuilder(#[from] crate::sync::sign::SignBuilderError),
83+
84+
///
85+
#[error("sign error: {0}")]
86+
Sign(#[from] crate::sync::sign::SignError),
7987
}
8088

8189
///

Diff for: asyncgit/src/sync/commit.rs

+35-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::{CommitId, RepoPath};
2+
use crate::sync::sign::{SignBuilder, SignError};
23
use crate::{
34
error::Result,
45
sync::{repository::repo, utils::get_head_repo},
@@ -65,7 +66,7 @@ pub fn commit(repo_path: &RepoPath, msg: &str) -> Result<CommitId> {
6566
scope_time!("commit");
6667

6768
let repo = repo(repo_path)?;
68-
69+
let config = repo.config()?;
6970
let signature = signature_allow_undefined_name(&repo)?;
7071
let mut index = repo.index()?;
7172
let tree_id = index.write_tree()?;
@@ -79,16 +80,46 @@ pub fn commit(repo_path: &RepoPath, msg: &str) -> Result<CommitId> {
7980

8081
let parents = parents.iter().collect::<Vec<_>>();
8182

82-
Ok(repo
83-
.commit(
83+
let commit_id = if config
84+
.get_bool("commit.gpgsign")
85+
.unwrap_or(false)
86+
{
87+
use crate::sync::sign::Sign;
88+
89+
let buffer = repo.commit_create_buffer(
90+
&signature,
91+
&signature,
92+
msg,
93+
&tree,
94+
parents.as_slice(),
95+
)?;
96+
97+
let commit = std::str::from_utf8(&buffer).map_err(|_e| {
98+
SignError::Shellout("utf8 conversion error".to_string())
99+
})?;
100+
101+
let sign = SignBuilder::from_gitconfig(&repo, &config)?;
102+
let signed_commit = sign.sign(commit)?;
103+
let commit_id =
104+
repo.commit_signed(commit, &signed_commit, None)?;
105+
106+
// manually advance to the new commit ID
107+
// repo.commit does that on its own, repo.commit_signed does not
108+
repo.head()?.set_target(commit_id, msg)?;
109+
110+
commit_id
111+
} else {
112+
repo.commit(
84113
Some("HEAD"),
85114
&signature,
86115
&signature,
87116
msg,
88117
&tree,
89118
parents.as_slice(),
90119
)?
91-
.into())
120+
};
121+
122+
Ok(commit_id.into())
92123
}
93124

94125
/// Tag a commit.

Diff for: asyncgit/src/sync/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod rebase;
2323
pub mod remotes;
2424
mod repository;
2525
mod reset;
26+
pub mod sign;
2627
mod staging;
2728
mod stash;
2829
mod state;

0 commit comments

Comments
 (0)