From 1aad2504202982631b73a038ec213521ef9c3f15 Mon Sep 17 00:00:00 2001 From: Vamsi Avula Date: Thu, 12 Jan 2023 00:00:31 +0530 Subject: [PATCH] Shorten the git push branch when possible using the short change ID hash. --- src/cli_util.rs | 6 +++++- src/commands.rs | 43 ++++++++++++++++++++++++++++++++++-------- tests/test_git_push.rs | 30 +++++++++++++++++++++++------ 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/cli_util.rs b/src/cli_util.rs index 41de37c0c..2ada03862 100644 --- a/src/cli_util.rs +++ b/src/cli_util.rs @@ -27,7 +27,7 @@ use clap::builder::{NonEmptyStringValueParser, TypedValueParser, ValueParserFact use clap::{Arg, ArgAction, ArgMatches, Command, Error, FromArgMatches}; use git2::{Oid, Repository}; use itertools::Itertools; -use jujutsu_lib::backend::{BackendError, CommitId, ObjectId, TreeId}; +use jujutsu_lib::backend::{BackendError, ChangeId, CommitId, ObjectId, TreeId}; use jujutsu_lib::commit::Commit; use jujutsu_lib::git::{GitExportError, GitImportError}; use jujutsu_lib::gitignore::GitIgnoreFile; @@ -1385,6 +1385,10 @@ pub fn short_commit_hash(commit_id: &CommitId) -> String { commit_id.hex()[0..12].to_string() } +pub fn short_change_hash(change_id: &ChangeId) -> String { + change_id.hex()[0..12].to_string() +} + pub fn short_operation_hash(operation_id: &OperationId) -> String { operation_id.hex()[0..12].to_string() } diff --git a/src/commands.rs b/src/commands.rs index c78024ed8..492d09a8e 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -51,7 +51,7 @@ use pest::Parser; use crate::cli_util::{ self, check_stale_working_copy, print_checkout_stats, print_failed_git_export, - resolve_base_revs, short_commit_description, short_commit_hash, user_error, + resolve_base_revs, short_change_hash, short_commit_description, short_commit_hash, user_error, user_error_with_hint, write_commit_summary, write_config_entry, Args, CommandError, CommandHelper, DescriptionArg, RevisionArg, WorkspaceCommandHelper, }; @@ -4179,7 +4179,7 @@ fn cmd_git_push( &args.remote )); for (change_str, commit) in std::iter::zip(args.change.iter(), commits) { - let branch_name = format!( + let mut branch_name = format!( "{}{}", command.settings().push_branch_prefix(), commit.change_id().hex() @@ -4193,12 +4193,39 @@ fn cmd_git_push( .get_local_branch(&branch_name) .is_none() { - writeln!( - ui, - "Creating branch {} for revision {}", - branch_name, - change_str.deref() - )?; + // A local branch with the full change ID doesn't exist already, so use the + // short ID if it's not ambiguous (which it shouldn't be most of the time). + let short_change_id = short_change_hash(commit.change_id()); + let new_branch_name = match workspace_command.resolve_single_rev(&short_change_id) { + Ok(_) => { + // Short change ID is not ambiguous but we do need to check if + // a branch already exists with the short ID. + branch_name = format!( + "{}{}", + command.settings().push_branch_prefix(), + short_change_id + ); + if workspace_command + .repo() + .view() + .get_local_branch(&branch_name) + .is_none() + { + Some(&branch_name) + } else { + None + } + } + Err(_) => Some(&branch_name), + }; + if let Some(branch_name) = new_branch_name { + writeln!( + ui, + "Creating branch {} for revision {}", + branch_name, + change_str.deref() + )?; + } } tx.mut_repo() .set_local_branch(branch_name.clone(), RefTarget::Normal(commit.id().clone())); diff --git a/tests/test_git_push.rs b/tests/test_git_push.rs index cff04bfe6..94bb1fb83 100644 --- a/tests/test_git_push.rs +++ b/tests/test_git_push.rs @@ -211,9 +211,9 @@ fn test_git_push_changes() { let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push", "--change", "@"]); insta::assert_snapshot!(stdout, @r###" - Creating branch push-1b76972398e6449e8e0701307e57d55a for revision @ + Creating branch push-1b76972398e6 for revision @ Branch changes to push to origin: - Add branch push-1b76972398e6449e8e0701307e57d55a to 28d7620ea63a + Add branch push-1b76972398e6 to 28d7620ea63a "###); // test pushing two changes at once std::fs::write(workspace_root.join("file"), "modified2").unwrap(); @@ -222,10 +222,10 @@ fn test_git_push_changes() { &["git", "push", "--change", "@", "--change", "@-"], ); insta::assert_snapshot!(stdout, @r###" - Creating branch push-19b790168e7347a7ba98deae21e807c0 for revision @- + Creating branch push-19b790168e73 for revision @- Branch changes to push to origin: - Force branch push-1b76972398e6449e8e0701307e57d55a from 28d7620ea63a to 48d8c7948133 - Add branch push-19b790168e7347a7ba98deae21e807c0 to fa16a14170fb + Force branch push-1b76972398e6 from 28d7620ea63a to 48d8c7948133 + Add branch push-19b790168e73 to fa16a14170fb "###); // specifying the same change twice doesn't break things std::fs::write(workspace_root.join("file"), "modified3").unwrap(); @@ -235,7 +235,25 @@ fn test_git_push_changes() { ); insta::assert_snapshot!(stdout, @r###" Branch changes to push to origin: - Force branch push-1b76972398e6449e8e0701307e57d55a from 48d8c7948133 to b5f030322b1d + Force branch push-1b76972398e6 from 48d8c7948133 to b5f030322b1d + "###); +} + +#[test] +fn test_git_push_existing_long_branch() { + let (test_env, workspace_root) = set_up(); + test_env.jj_cmd_success(&workspace_root, &["describe", "-m", "foo"]); + std::fs::write(workspace_root.join("file"), "contents").unwrap(); + test_env.jj_cmd_success( + &workspace_root, + &["branch", "create", "push-19b790168e7347a7ba98deae21e807c0"], + ); + + let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push", "--change=@"]); + + insta::assert_snapshot!(stdout, @r###" + Branch changes to push to origin: + Add branch push-19b790168e7347a7ba98deae21e807c0 to fa16a14170fb "###); }