Skip to content

Commit

Permalink
feat(rebase): support GPG-signing for all rebase-based commands
Browse files Browse the repository at this point in the history
  • Loading branch information
tommyip committed Jun 24, 2023
1 parent a7a5e9b commit feba5bd
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 19 deletions.
29 changes: 25 additions & 4 deletions git-branchless-lib/src/core/rewrite/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::core::formatting::Pluralize;
use crate::core::repo_ext::RepoExt;
use crate::git::{
BranchType, CategorizedReferenceName, GitRunInfo, MaybeZeroOid, NonZeroOid, ReferenceName,
Repo, ResolvedReferenceInfo,
Repo, ResolvedReferenceInfo, SignOption,
};
use crate::util::{ExitCode, EyreExitOr};

Expand Down Expand Up @@ -435,7 +435,8 @@ mod in_memory {
use crate::core::rewrite::move_branches;
use crate::core::rewrite::plan::{OidOrLabel, RebaseCommand, RebasePlan};
use crate::git::{
CherryPickFastError, CherryPickFastOptions, GitRunInfo, MaybeZeroOid, NonZeroOid, Repo,
self, CherryPickFastError, CherryPickFastOptions, GitRunInfo, MaybeZeroOid, NonZeroOid,
Repo,
};
use crate::util::EyreExitOr;

Expand Down Expand Up @@ -498,6 +499,7 @@ mod in_memory {
force_on_disk: _,
resolve_merge_conflicts: _, // May be needed once we can resolve merge conflicts in memory.
check_out_commit_options: _, // Caller is responsible for checking out to new HEAD.
sign_option,
} = options;

let mut current_oid = rebase_plan.first_dest_oid;
Expand Down Expand Up @@ -535,6 +537,8 @@ mod in_memory {
.count();
let (effects, progress) = effects.start_operation(OperationType::RebaseCommits);

let signer = git::get_signer(&repo, sign_option)?;

for command in rebase_plan.commands.iter() {
match command {
RebaseCommand::CreateLabel { label_name } => {
Expand Down Expand Up @@ -633,7 +637,7 @@ mod in_memory {
commit_message,
&commit_tree,
vec![&current_commit],
None,
signer.as_deref(),
)
.wrap_err("Applying rebased commit")?;

Expand Down Expand Up @@ -753,7 +757,7 @@ mod in_memory {
replacement_commit_message,
&replacement_tree,
parents.iter().collect(),
None,
signer.as_deref(),
)
.wrap_err("Applying rebased commit")?;

Expand Down Expand Up @@ -864,6 +868,7 @@ mod in_memory {
force_on_disk: _,
resolve_merge_conflicts: _,
check_out_commit_options,
sign_option: _,
} = options;

// Note that if an OID has been mapped to multiple other OIDs, then the last
Expand Down Expand Up @@ -959,6 +964,7 @@ mod on_disk {
force_on_disk: _,
resolve_merge_conflicts: _,
check_out_commit_options: _, // Checkout happens after rebase has concluded.
sign_option,
} = options;

let (effects, _progress) = effects.start_operation(OperationType::InitializeRebase);
Expand Down Expand Up @@ -1073,6 +1079,16 @@ mod on_disk {
)
})?;

let gpg_sign_opt_file = rebase_state_dir.join("gpg_sign_opt");
if let Some(sign_flag) = sign_option.as_rebase_flag(repo)? {
std::fs::write(&gpg_sign_opt_file, sign_flag).wrap_err_with(|| {
format!(
"Writing `gpg_sign_opt` to: {:?}",
gpg_sign_opt_file.as_path()
)
})?;
}

let end_file_path = rebase_state_dir.join("end");
std::fs::write(
end_file_path.as_path(),
Expand Down Expand Up @@ -1132,6 +1148,7 @@ mod on_disk {
force_on_disk: _,
resolve_merge_conflicts: _,
check_out_commit_options: _, // Checkout happens after rebase has concluded.
sign_option: _,
} = options;

match write_rebase_state_to_disk(effects, git_run_info, repo, rebase_plan, options)? {
Expand Down Expand Up @@ -1176,6 +1193,9 @@ pub struct ExecuteRebasePlanOptions {

/// If `HEAD` was moved, the options for checking out the new `HEAD` commit.
pub check_out_commit_options: CheckOutCommitOptions,

/// GPG-sign commits.
pub sign_option: SignOption,
}

/// The result of executing a rebase plan.
Expand Down Expand Up @@ -1221,6 +1241,7 @@ pub fn execute_rebase_plan(
force_on_disk,
resolve_merge_conflicts,
check_out_commit_options: _,
sign_option: _,
} = options;

if !force_on_disk {
Expand Down
18 changes: 17 additions & 1 deletion git-branchless-lib/src/git/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use tracing::instrument;
use super::{repo::Result, Repo, RepoError};

/// GPG-signing option.
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SignOption {
/// Sign commits conditionally based on the `commit.gpgsign` configuration and
/// and the key `user.signingkey`.
Expand All @@ -26,6 +26,22 @@ impl SignOption {
Self::Disable => Some("--no-gpg-sign".to_string()),
}
}

/// GPG-signing flag to use for interactive rebase
pub fn as_rebase_flag(&self, repo: &Repo) -> Result<Option<String>> {
Ok(match self {
Self::UseConfig => {
let config = repo.inner.config().map_err(RepoError::ReadConfig)?;
match config.get_bool("commit.gpgsign").ok() {
Some(true) => Some("-S".to_string()),
Some(false) | None => None,
}
}
Self::UseConfigKey => Some("-S".to_string()),
Self::KeyOverride(keyid) => Some(format!("-S{}", keyid)),
Self::Disable => None,
})
}
}

/// Get commit signer configured from CLI arguments and repository configurations.
Expand Down
2 changes: 2 additions & 0 deletions git-branchless-lib/tests/test_rewrite_plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use branchless::core::rewrite::{
execute_rebase_plan, BuildRebasePlanOptions, ExecuteRebasePlanOptions, ExecuteRebasePlanResult,
RebasePlan, RebasePlanBuilder, RepoResource,
};
use branchless::git::SignOption;
use git_branchless_testing::{make_git, Git};

#[test]
Expand Down Expand Up @@ -713,6 +714,7 @@ fn create_and_execute_plan(
reset: false,
render_smartlog: false,
},
sign_option: SignOption::Disable,
};
let git_run_info = git.get_git_run_info();
let result = execute_rebase_plan(
Expand Down
2 changes: 2 additions & 0 deletions git-branchless-move/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ pub fn r#move(
resolve_merge_conflicts,
dump_rebase_constraints,
dump_rebase_plan,
ref sign_options,
} = *move_options;
let now = SystemTime::now();
let event_tx_id = event_log_db.make_transaction_id(now, "move")?;
Expand Down Expand Up @@ -471,6 +472,7 @@ pub fn r#move(
force_on_disk,
resolve_merge_conflicts,
check_out_commit_options: Default::default(),
sign_option: sign_options.to_owned().into(),
};
execute_rebase_plan(
effects,
Expand Down
14 changes: 9 additions & 5 deletions git-branchless-opts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ pub struct MoveOptions {
/// executing it.
#[clap(action, long = "debug-dump-rebase-plan")]
pub dump_rebase_plan: bool,

/// GPG-sign commits.
#[clap(flatten)]
pub sign_options: SignOptions,
}

/// Options for traversing commits.
Expand Down Expand Up @@ -179,7 +183,7 @@ pub struct SwitchOptions {
}

/// Options for signing commits
#[derive(Args, Debug)]
#[derive(Args, Debug, Clone)]
pub struct SignOptions {
/// GPG-sign commits. The `keyid` argument is optional and defaults to the committer
/// identity.
Expand Down Expand Up @@ -464,10 +468,6 @@ pub enum Command {
/// formatting or refactoring changes.
#[clap(long)]
reparent: bool,

/// Options for signing commits.
#[clap(flatten)]
sign_options: SignOptions,
},

/// Gather information about recent operations to upload as part of a bug
Expand Down Expand Up @@ -650,6 +650,10 @@ pub enum Command {
/// use with `git rebase --autosquash`) targeting the supplied commit.
#[clap(value_parser, long = "fixup", conflicts_with_all(&["messages", "discard"]))]
commit_to_fixup: Option<Revset>,

/// GPG-sign commits.
#[clap(flatten)]
sign_options: SignOptions,
},

/// `smartlog` command.
Expand Down
5 changes: 4 additions & 1 deletion git-branchless-record/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ fn record(
effects,
git_run_info,
now,
event_tx_id
event_tx_id,
sign_option,
)?);
}

Expand Down Expand Up @@ -357,6 +358,7 @@ fn insert_before_siblings(
git_run_info: &GitRunInfo,
now: SystemTime,
event_tx_id: EventTransactionId,
sign_option: &SignOption,
) -> EyreExitOr<()> {
// Reopen the repository since references may have changed.
let repo = Repo::from_dir(&git_run_info.working_directory)?;
Expand Down Expand Up @@ -484,6 +486,7 @@ To proceed anyways, run: git move -f -s 'siblings(.)",
force_on_disk: false,
resolve_merge_conflicts: false,
check_out_commit_options: Default::default(),
sign_option: sign_option.to_owned(),
};
let result = execute_rebase_plan(
effects,
Expand Down
4 changes: 3 additions & 1 deletion git-branchless-reword/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use lib::core::rewrite::{
};
use lib::git::{message_prettify, Commit, GitRunInfo, MaybeZeroOid, NonZeroOid, Repo};

use git_branchless_opts::{ResolveRevsetOptions, Revset};
use git_branchless_opts::{ResolveRevsetOptions, Revset, SignOptions};
use git_branchless_revset::resolve_commits;

/// The commit message(s) provided by the user.
Expand All @@ -67,6 +67,7 @@ pub fn reword(
messages: InitialCommitMessages,
git_run_info: &GitRunInfo,
force_rewrite_public_commits: bool,
sign_options: SignOptions,
) -> EyreExitOr<()> {
let repo = Repo::from_current_dir()?;
let references_snapshot = repo.get_references_snapshot()?;
Expand Down Expand Up @@ -290,6 +291,7 @@ pub fn reword(
reset: false,
render_smartlog: false,
},
sign_option: sign_options.into(),
};
let result = execute_rebase_plan(
effects,
Expand Down
6 changes: 5 additions & 1 deletion git-branchless-submit/src/phabricator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ use lib::core::rewrite::{
execute_rebase_plan, BuildRebasePlanError, BuildRebasePlanOptions, ExecuteRebasePlanOptions,
ExecuteRebasePlanResult, RebasePlanBuilder, RebasePlanPermissions, RepoResource,
};
use lib::git::{Commit, GitRunInfo, MaybeZeroOid, NonZeroOid, Repo, RepoError, TestCommand};
use lib::git::{
Commit, GitRunInfo, MaybeZeroOid, NonZeroOid, Repo, RepoError, SignOption, TestCommand,
};
use lib::try_exit_code;
use lib::util::{ExitCode, EyreExitOr};
use rayon::ThreadPoolBuilder;
Expand Down Expand Up @@ -359,6 +361,7 @@ impl Forge for PhabricatorForge<'_> {
render_smartlog: false,
..Default::default()
},
sign_option: SignOption::Disable,
};
let permissions =
RebasePlanPermissions::verify_rewrite_set(self.dag, build_options, &commit_set)
Expand Down Expand Up @@ -608,6 +611,7 @@ Differential Revision: https://phabricator.example.com/D000$(git rev-list --coun
render_smartlog: false,
..Default::default()
},
sign_option: SignOption::Disable,
};
let permissions =
RebasePlanPermissions::verify_rewrite_set(self.dag, build_options, &commit_set)
Expand Down
8 changes: 6 additions & 2 deletions git-branchless-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ use lib::core::rewrite::{
use lib::git::{
get_latest_test_command_path, get_test_locks_dir, get_test_tree_dir, get_test_worktrees_dir,
make_test_command_slug, Commit, ConfigRead, GitRunInfo, GitRunResult, MaybeZeroOid, NonZeroOid,
Repo, SerializedNonZeroOid, SerializedTestResult, TestCommand, WorkingCopyChangesType,
TEST_ABORT_EXIT_CODE, TEST_INDETERMINATE_EXIT_CODE, TEST_SUCCESS_EXIT_CODE,
Repo, SerializedNonZeroOid, SerializedTestResult, SignOption, TestCommand,
WorkingCopyChangesType, TEST_ABORT_EXIT_CODE, TEST_INDETERMINATE_EXIT_CODE,
TEST_SUCCESS_EXIT_CODE,
};
use lib::try_exit_code;
use lib::util::{get_sh, ExitCode, EyreExitOr};
Expand Down Expand Up @@ -386,6 +387,7 @@ BUG: Expected resolved_interactive ({resolved_interactive:?}) to match interacti
resolve_merge_conflicts,
dump_rebase_constraints,
dump_rebase_plan,
sign_options,
} = move_options;

let force_in_memory = true;
Expand Down Expand Up @@ -414,6 +416,7 @@ BUG: Expected resolved_interactive ({resolved_interactive:?}) to match interacti
render_smartlog: false,
..Default::default()
},
sign_option: sign_options.to_owned().into(),
};
let permissions =
match RebasePlanPermissions::verify_rewrite_set(dag, build_options, commits)? {
Expand Down Expand Up @@ -730,6 +733,7 @@ fn set_abort_trap(
render_smartlog: false,
..Default::default()
},
sign_option: SignOption::Disable,
},
)? {
ExecuteRebasePlanResult::Succeeded { rewritten_oids: _ } => {
Expand Down
5 changes: 3 additions & 2 deletions git-branchless/src/commands/amend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use lib::core::rewrite::{
execute_rebase_plan, move_branches, BuildRebasePlanOptions, ExecuteRebasePlanOptions,
ExecuteRebasePlanResult, RebasePlanBuilder, RebasePlanPermissions, RepoResource,
};
use lib::git::{get_signer, SignOption};
use lib::git::get_signer;
use lib::git::{AmendFastOptions, GitRunInfo, MaybeZeroOid, Repo, ResolvedReferenceInfo};
use lib::try_exit_code;
use lib::util::{ExitCode, EyreExitOr};
Expand All @@ -41,7 +41,6 @@ pub fn amend(
resolve_revset_options: &ResolveRevsetOptions,
move_options: &MoveOptions,
reparent: bool,
sign_option: SignOption,
) -> EyreExitOr<()> {
let now = SystemTime::now();
let timestamp = now.duration_since(SystemTime::UNIX_EPOCH)?.as_secs_f64();
Expand Down Expand Up @@ -157,6 +156,7 @@ pub fn amend(
)
};

let sign_option = move_options.sign_options.to_owned().into();
let signer = get_signer(&repo, &sign_option)?;

let amended_commit_oid = repo.amend_commit(
Expand Down Expand Up @@ -305,6 +305,7 @@ pub fn amend(
reset: true,
render_smartlog: false,
},
sign_option,
};
match execute_rebase_plan(
effects,
Expand Down
4 changes: 2 additions & 2 deletions git-branchless/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,12 @@ fn command_main(ctx: CommandContext, opts: Opts) -> EyreExitOr<()> {
Command::Amend {
move_options,
reparent,
sign_options,
} => amend::amend(
&effects,
&git_run_info,
&ResolveRevsetOptions::default(),
&move_options,
reparent,
sign_options.into(),
)?,

Command::BugReport => bug_report::bug_report(&effects, &git_run_info)?,
Expand Down Expand Up @@ -140,6 +138,7 @@ fn command_main(ctx: CommandContext, opts: Opts) -> EyreExitOr<()> {
force_rewrite_public_commits,
discard,
commit_to_fixup,
sign_options,
} => {
let messages = if discard {
git_branchless_reword::InitialCommitMessages::Discard
Expand All @@ -155,6 +154,7 @@ fn command_main(ctx: CommandContext, opts: Opts) -> EyreExitOr<()> {
messages,
&git_run_info,
force_rewrite_public_commits,
sign_options,
)?
}

Expand Down
Loading

0 comments on commit feba5bd

Please sign in to comment.