-
-
Notifications
You must be signed in to change notification settings - Fork 95
support for openpgp, ssh, x509 signatures with tests #1538
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
base: master
Are you sure you want to change the base?
Conversation
36d6600
to
97c5af9
Compare
If I understand the deps situation correctly, we are waiting on:
The good news is that I believe @epage maintains both of those and has contributed to this project in the past. So, if you can open a PR to update I don't have any knowledge or experience w/ gpg or commit signing, but I may be able to do some code review to shepherd this along. It's a much requested feature! |
i pinged ed on #465 (comment) to ask whether there was a reason the dependency version was capped at 0.18 and request these updates. i suppose opening a PR to do the EDIT i forgot i tried to do that earlier. can't update the |
Sorry, no one had told me they were moving forward with this and needed a release with support for new git2 versions. I've released v0.6.3. |
no apology needed! thank you for implementing the signing functionality in the first place, and for doing this little chore to unblock integrating it! i'm using it at work every day and it works great! |
ef87113
to
2cd3c0f
Compare
Originally implemented by Thomas Ip in PR 966. Updated by Matt. Co-authored-by: Thomas Ip <[email protected]>
alright, updated remaining issue is apparently |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for shepherding this work through, and to the previous authors for getting it started. Most of this looked pretty straightforward and made sense to me, but there were a few places I requested some changes, most of which were to refactor this code into a similar style as the rest of the code base.
I'll take another look when that's done. Thanks again!
// Run smartlog without --show-signature flag | ||
{ | ||
let stdout = git.smartlog()?; | ||
// Without the flag, the signature indicators shouldn't be visible | ||
// However, we can't reliably check for absence of brackets since they might be used elsewhere | ||
// So we'll just ensure the command runs successfully | ||
assert!(!stdout.is_empty(), "Smartlog output should not be empty"); | ||
} | ||
|
||
// Run smartlog with --show-signature flag | ||
{ | ||
let (stdout, _) = git.branchless("smartlog", &["--show-signature"])?; | ||
// With the flag, the command should run successfully | ||
assert!(!stdout.is_empty(), "Smartlog output should not be empty"); | ||
// The signature status indicators should be present in some form, | ||
// but we don't validate exactly which status since that depends on the environment | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[please change] Many tests in this project use insta snapshots to capture the output of commands, and I think that it would be best for these tests to follow suit. Snapshots can be tedious to keep updated, but they tend to be much more pleasant to debug. You can see the test above (lines 800-810) for an example.
The first assertion here, that the smartlog works without the flag, may not be needed, since the rest of this file already tests that. It can be handy to have when running a single test though; in that case, it should also use a snapshot.
@@ -23,6 +23,7 @@ use chrono::{DateTime, Utc}; | |||
use cursive::theme::BaseColor; | |||
use cursive::utils::markup::StyledString; | |||
use git2::DiffOptions; | |||
use git2_ext::ops::Sign; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[suggestion (maybe/probably change)] I think that it would be best to wrap our own type around this (for example crate::git::sign::Signer
) to reduce the number of places we may have to rely on git2_ext
and make future refactoring easier. (eg if we ever switch to signing support directly in git2
, we can just update our implementation of Signer
(hopefully) without having to update all of the args, params, etc that depend on it.)
Here's an example of how this is done for Commit
:
git-branchless/git-branchless-lib/src/git/object.rs
Lines 19 to 23 in b1f7ae5
/// Represents a commit object in the Git object database. | |
#[derive(Clone, Debug)] | |
pub struct Commit<'repo> { | |
pub(super) inner: git2::Commit<'repo>, | |
} |
let mut args = vec!["commit"]; | ||
|
||
args.extend(messages.iter().flat_map(|message| ["--message", message])); | ||
|
||
if working_copy_changes_type == WorkingCopyChangesType::Unstaged { | ||
args.push("--all"); | ||
} | ||
|
||
let sign_flag = sign_option.as_git_flag(); | ||
if let Some(flag) = &sign_flag { | ||
args.push(flag); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Can you restore the block expression syntax (in other words let args = { ... }
) while including the new signing lines? That way args
can remain immutable in the else
.
let mut args = vec!["commit"]; | ||
|
||
if !message.is_empty() { | ||
args.extend(["--message", &message]); | ||
} | ||
|
||
let sign_flag = sign_option.as_git_flag(); | ||
if let Some(flag) = &sign_flag { | ||
args.push(flag); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[please change] Same here, please: let mut args = ...;
=> let args = { ... }
let mut args = vec!["commit"]; | ||
|
||
if !message.is_empty() { | ||
args.extend(["--message", &message]); | ||
} | ||
|
||
let sign_flag = sign_option.as_git_flag(); | ||
if let Some(flag) = &sign_flag { | ||
args.push(flag); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[please change] Same here, please: let mut args = ...;
=> let args = { ... }
let mut result = StyledString::new(); | ||
result.append_styled("[G]", BaseColor::Green.light()); | ||
Ok(Some(result)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick (maybe change)] It looks like other uses of StyledString
in this file seem to use let result = StyledString::styled("[G]", BaseColor::Green.light());
. To be consistent, can you update these uses of ::new()
to match. Or is there a reason that won't work in this context?
// Just create a regular commit without trying to sign it | ||
git.commit_file("signed_file", 1)?; | ||
git.commit_file("unsigned_file", 2)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[question] Are these filenames/comments correct? I don't know much about signing commits, but it seems like something is missing to actually do the signing.
#[test] | ||
fn test_show_signature_snapshot() -> eyre::Result<()> { | ||
let git = make_git()?; | ||
|
||
git.init_repo()?; | ||
|
||
// Create regular commits without trying to sign them | ||
git.commit_file("signed_file", 1)?; | ||
|
||
// Create a branch and make another commit | ||
git.run(&["checkout", "-b", "branch1", "master"])?; | ||
git.commit_file("another_file", 2)?; | ||
|
||
// Run smartlog with --show-signature flag | ||
let (stdout, _) = git.branchless("smartlog", &["--show-signature"])?; | ||
|
||
// Simply verify the command runs without error | ||
assert!(!stdout.is_empty(), "Smartlog output should not be empty"); | ||
|
||
Ok(()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[please change] This seems to be very similar to the previous test. Can you double to check and confirm that they're both really needed?
#[test] | ||
fn test_show_signature_argument_parsing() -> eyre::Result<()> { | ||
let git = make_git()?; | ||
git.init_repo()?; | ||
|
||
// Test that invalid flag combination reports error | ||
// For example, combine with a flag that doesn't make sense (if any) | ||
// If there are no incompatible flags, we can at least test that the flag is recognized | ||
|
||
// Test help output includes the flag | ||
let (help_stdout, _) = git.branchless("smartlog", &["--help"])?; | ||
assert!( | ||
help_stdout.contains("--show-signature"), | ||
"Help output should include --show-signature option" | ||
); | ||
|
||
// Test that the flag is recognized (should execute without error) | ||
let result = git.branchless("smartlog", &["--show-signature"]); | ||
assert!( | ||
result.is_ok(), | ||
"The --show-signature flag should be recognized" | ||
); | ||
|
||
// Test that the flag works when combined with other flags | ||
let result = git.branchless("smartlog", &["--show-signature", "--exact"]); | ||
assert!( | ||
result.is_ok(), | ||
"The --show-signature flag should work with --exact" | ||
); | ||
|
||
let result = git.branchless("smartlog", &["--show-signature", "--reverse"]); | ||
assert!( | ||
result.is_ok(), | ||
"The --show-signature flag should work with --reverse" | ||
); | ||
|
||
Ok(()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[please change] I also think that this test can be removed; mostly it seems to be testing that clap
is working as expected. If I'm misunderstanding, let's update it to be more clear about which flags may or may not work with the new --show-signature
flag.
yet another PR enters the mix for #465
mostly based on:
my additions:
git2-ext
MSRVgpg
,ssh-keygen
, andgpgsm
.there are three integration tests:
openpgp
signatures, which is gated by atest_gpg
feature flag and requires aTEST_GPG
env var to point at agpg
binaryssh
signatures, which is gated by atest_ssh
feature flag and requires aTEST_SSH_KEYGEN
env var to point at anssh-keygen
binaryx509
signatures, which is gated by atest_x509
feature flag and requires aTEST_GPGSM
env var to point at agpgsm
binarythe
openpgp
andx509
tests actually expect GnuPG tools because their keyring format or whatever is checked in (meaning, nosmimesign
for mac)run them with: