Skip to content

Add ssh sign feature #2023

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
753 changes: 741 additions & 12 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ tempfile = "3.4"
maintenance = { status = "actively-developed" }

[features]
default = ["ghemoji", "regex-fancy", "trace-libgit", "vendor-openssl"]
default = ["asyncgit/common-lib", "ghemoji", "regex-fancy", "trace-libgit", "vendor-openssl"]
ghemoji = ["gh-emoji"]
# regex-* features are mutually exclusive.
regex-fancy = ["syntect/regex-fancy"]
Expand Down
4 changes: 3 additions & 1 deletion asyncgit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ rayon = "1.8"
rayon-core = "1.12"
scopetime = { path = "../scopetime", version = "0.1" }
serde = { version = "1.0", features = ["derive"] }
ssh-key = { version = "0.6.4", features = ["crypto", "encryption"] }
thiserror = "1.0"
unicode-truncate = "0.2.0"
url = "2.5"
Expand All @@ -39,6 +40,7 @@ serial_test = "1.0"
tempfile = "3.4"

[features]
default = ["trace-libgit"]
common-lib = []
default = ["common-lib", "trace-libgit"]
trace-libgit = []
vendor-openssl = ["openssl-sys"]
4 changes: 4 additions & 0 deletions asyncgit/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ pub enum Error {
///
#[error("git hook error: {0}")]
Hooks(#[from] git2_hooks::HooksError),

///
#[error("ssh key error: {0}")]
SshKeyError(#[from] ssh_key::Error),
}

///
Expand Down
2 changes: 2 additions & 0 deletions asyncgit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ pub use crate::{
treefiles::AsyncTreeFilesJob,
};
pub use git2::message_prettify;
#[cfg(feature = "common-lib")]
pub use ssh_key;
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
Expand Down
8 changes: 4 additions & 4 deletions asyncgit/src/sync/blame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ mod tests {
File::create(root.join(file_path))?.write_all(b"line 1\n")?;

stage_add_file(repo_path, file_path)?;
commit(repo_path, "first commit")?;
commit(repo_path, "first commit", None)?;

let blame = blame_file(repo_path, "foo", None)?;

Expand All @@ -199,7 +199,7 @@ mod tests {
file.write(b"line 2\n")?;

stage_add_file(repo_path, file_path)?;
commit(repo_path, "second commit")?;
commit(repo_path, "second commit", None)?;

let blame = blame_file(repo_path, "foo", None)?;

Expand Down Expand Up @@ -233,7 +233,7 @@ mod tests {
assert_eq!(blame.lines.len(), 2);

stage_add_file(repo_path, file_path)?;
commit(repo_path, "third commit")?;
commit(repo_path, "third commit", None)?;

let blame = blame_file(repo_path, "foo", None)?;

Expand All @@ -258,7 +258,7 @@ mod tests {
.unwrap();

stage_add_file(repo_path, file_path).unwrap();
commit(repo_path, "first commit").unwrap();
commit(repo_path, "first commit", None).unwrap();

assert!(blame_file(repo_path, "bar\\foo", None).is_ok());
}
Expand Down
69 changes: 53 additions & 16 deletions asyncgit/src/sync/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
};
use git2::{ErrorCode, ObjectType, Repository, Signature};
use scopetime::scope_time;
use ssh_key::{HashAlg, LineEnding, PrivateKey};

///
pub fn amend(
Expand Down Expand Up @@ -61,7 +62,11 @@ pub(crate) fn signature_allow_undefined_name(
}

/// this does not run any git hooks, git-hooks have to be executed manually, checkout `hooks_commit_msg` for example
pub fn commit(repo_path: &RepoPath, msg: &str) -> Result<CommitId> {
pub fn commit(
repo_path: &RepoPath,
msg: &str,
sk: Option<&PrivateKey>,
) -> Result<CommitId> {
scope_time!("commit");

let repo = repo(repo_path)?;
Expand All @@ -78,17 +83,49 @@ pub fn commit(repo_path: &RepoPath, msg: &str) -> Result<CommitId> {
};

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

Ok(repo
.commit(
Some("HEAD"),
if let Some(sk) = sk {
let buffer = repo.commit_create_buffer(
&signature,
&signature,
msg,
&tree,
parents.as_slice(),
)?
.into())
)?;
let content = String::from_utf8(buffer.to_vec())?;
let sig = sk
.sign("git", HashAlg::Sha256, &buffer)?
.to_pem(LineEnding::LF)?;
let commit_id = repo.commit_signed(&content, &sig, None)?;
match repo.head() {
Ok(mut head) => {
head.set_target(commit_id, msg)?;
}
Err(_) => {
let config = repo.config()?;
let default_branch_name = config
.get_str("init.defaultBranch")
.unwrap_or("master");
repo.reference(
&format!("refs/heads/{}", default_branch_name),
commit_id,
true,
msg,
)?;
}
}
Ok(commit_id.into())
} else {
Ok(repo
.commit(
Some("HEAD"),
&signature,
&signature,
msg,
&tree,
parents.as_slice(),
)?
.into())
}
}

/// Tag a commit.
Expand Down Expand Up @@ -162,7 +199,7 @@ mod tests {

assert_eq!(get_statuses(repo_path), (0, 1));

commit(repo_path, "commit msg").unwrap();
commit(repo_path, "commit msg", None).unwrap();

assert_eq!(get_statuses(repo_path), (0, 0));
}
Expand All @@ -188,7 +225,7 @@ mod tests {

assert_eq!(get_statuses(repo_path), (0, 1));

commit(repo_path, "commit msg").unwrap();
commit(repo_path, "commit msg", None).unwrap();

assert_eq!(get_statuses(repo_path), (0, 0));
}
Expand All @@ -205,7 +242,7 @@ mod tests {
File::create(root.join(file_path1))?.write_all(b"test1")?;

stage_add_file(repo_path, file_path1)?;
let id = commit(repo_path, "commit msg")?;
let id = commit(repo_path, "commit msg", None)?;

assert_eq!(count_commits(&repo, 10), 1);

Expand Down Expand Up @@ -244,7 +281,7 @@ mod tests {

stage_add_file(repo_path, file_path)?;

let new_id = commit(repo_path, "commit msg")?;
let new_id = commit(repo_path, "commit msg", None)?;

tag_commit(repo_path, &new_id, "tag", None)?;

Expand Down Expand Up @@ -286,7 +323,7 @@ mod tests {

stage_add_file(repo_path, file_path)?;

let new_id = commit(repo_path, "commit msg")?;
let new_id = commit(repo_path, "commit msg", None)?;

tag_commit(repo_path, &new_id, "tag", Some("tag-message"))?;

Expand Down Expand Up @@ -322,13 +359,13 @@ mod tests {

repo.config()?.remove("user.email")?;

let error = commit(repo_path, "commit msg");
let error = commit(repo_path, "commit msg", None);

assert!(matches!(error, Err(_)));

repo.config()?.set_str("user.email", "email")?;

let success = commit(repo_path, "commit msg");
let success = commit(repo_path, "commit msg", None);

assert!(matches!(success, Ok(_)));
assert_eq!(count_commits(&repo, 10), 1);
Expand Down Expand Up @@ -358,7 +395,7 @@ mod tests {

repo.config()?.remove("user.name")?;

let mut success = commit(repo_path, "commit msg");
let mut success = commit(repo_path, "commit msg", None);

assert!(matches!(success, Ok(_)));
assert_eq!(count_commits(&repo, 10), 1);
Expand All @@ -371,7 +408,7 @@ mod tests {

repo.config()?.set_str("user.name", "name")?;

success = commit(repo_path, "commit msg");
success = commit(repo_path, "commit msg", None);

assert!(matches!(success, Ok(_)));
assert_eq!(count_commits(&repo, 10), 2);
Expand Down
2 changes: 1 addition & 1 deletion asyncgit/src/sync/commit_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ mod tests {
stage_add_file(repo_path, file_path).unwrap();

let msg = invalidstring::invalid_utf8("test msg");
let id = commit(repo_path, msg.as_str()).unwrap();
let id = commit(repo_path, msg.as_str(), None).unwrap();

let res = get_commit_details(repo_path, id).unwrap();

Expand Down
4 changes: 2 additions & 2 deletions asyncgit/src/sync/commit_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ mod tests {

stage_add_file(repo_path, file_path)?;

let id = commit(repo_path, "commit msg")?;
let id = commit(repo_path, "commit msg", None)?;

let diff = get_commit_files(repo_path, id, None)?;

Expand Down Expand Up @@ -222,7 +222,7 @@ mod tests {

File::create(root.join(file_path1))?.write_all(b"test")?;
stage_add_file(repo_path, file_path1)?;
commit(repo_path, "c1")?;
commit(repo_path, "c1", None)?;

File::create(root.join(file_path1))?
.write_all(b"modified")?;
Expand Down
4 changes: 3 additions & 1 deletion asyncgit/src/sync/commit_revert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
sync::{repository::repo, utils::read_file},
};
use scopetime::scope_time;
use ssh_key::PrivateKey;

const GIT_REVERT_HEAD_FILE: &str = "REVERT_HEAD";

Expand Down Expand Up @@ -40,10 +41,11 @@ pub fn revert_head(repo_path: &RepoPath) -> Result<CommitId> {
pub fn commit_revert(
repo_path: &RepoPath,
msg: &str,
sk: Option<&PrivateKey>,
) -> Result<CommitId> {
scope_time!("commit_revert");

let id = crate::sync::commit(repo_path, msg)?;
let id = crate::sync::commit(repo_path, msg, sk)?;

repo(repo_path)?.cleanup_state()?;

Expand Down
11 changes: 6 additions & 5 deletions asyncgit/src/sync/commits_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,10 @@ mod tests {

File::create(root.join(file_path))?.write_all(b"a")?;
stage_add_file(repo_path, file_path).unwrap();
let c1 = commit(repo_path, "commit1").unwrap();
let c1 = commit(repo_path, "commit1", None).unwrap();
File::create(root.join(file_path))?.write_all(b"a")?;
stage_add_file(repo_path, file_path).unwrap();
let c2 = commit(repo_path, "commit2").unwrap();
let c2 = commit(repo_path, "commit2", None).unwrap();

let res = get_commits_info(repo_path, &[c2, c1], 50).unwrap();

Expand All @@ -197,7 +197,7 @@ mod tests {

File::create(root.join(file_path))?.write_all(b"a")?;
stage_add_file(repo_path, file_path).unwrap();
let c1 = commit(repo_path, "subject\nbody").unwrap();
let c1 = commit(repo_path, "subject\nbody", None).unwrap();

let res = get_commits_info(repo_path, &[c1], 50).unwrap();

Expand All @@ -219,7 +219,7 @@ mod tests {
stage_add_file(repo_path, file_path).unwrap();

let msg = invalidstring::invalid_utf8("test msg");
commit(repo_path, msg.as_str()).unwrap();
commit(repo_path, msg.as_str(), None).unwrap();

let res = get_commits_info(
repo_path,
Expand All @@ -245,7 +245,8 @@ mod tests {
let foo_file = Path::new("foo");
File::create(root.join(foo_file))?.write_all(b"a")?;
stage_add_file(repo_path, foo_file).unwrap();
let c1 = commit(repo_path, "subject: foo\nbody").unwrap();
let c1 =
commit(repo_path, "subject: foo\nbody", None).unwrap();
let c1_rev = c1.get_short_string();

assert_eq!(
Expand Down
6 changes: 3 additions & 3 deletions asyncgit/src/sync/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ mod tests {

stage_add_file(repo_path, file_path).unwrap();

commit(repo_path, "commit").unwrap();
commit(repo_path, "commit", None).unwrap();

File::create(root.join(file_path))?.write_all(b"\x00\x02")?;

Expand Down Expand Up @@ -655,13 +655,13 @@ mod tests {

stage_add_file(repo_path, file_path).unwrap();

commit(repo_path, "").unwrap();
commit(repo_path, "", None).unwrap();

File::create(root.join(file_path))?.write_all(b"\x00\x02")?;

stage_add_file(repo_path, file_path).unwrap();

let id = commit(repo_path, "").unwrap();
let id = commit(repo_path, "", None).unwrap();

let diff =
get_diff_commit(repo_path, id, String::new(), None)
Expand Down
Loading