From 17af119089379ec1b65b327c72eee3aac93fada7 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 25 Oct 2015 18:34:08 +0000 Subject: 36958: _git: Fix recent commit completion descriptions. The uniquifiers 'HEAD~$n' were incorrect when a recent commit was the second parent of a merge commit. Detect that case and print something correct instead. --- Completion/Unix/Command/_git | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'Completion') diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index e38b1c6e7..279331b00 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5650,6 +5650,8 @@ __git_recent_commits () { local i j k ret integer distance_from_head local label + local parents + local next_first_parent_ancestral_line_commit zparseopts -D -E O:=argument_array_names # Turn (-O foo:bar) to (foo bar) @@ -5659,10 +5661,10 @@ __git_recent_commits () { # Careful: most %d will expand to the empty string. Quote properly! # NOTE: we could use %D directly, but it's not available in git 1.9.1 at least. - commits=("${(f)"$(_call_program commits git --no-pager log $commit_opts -20 --format='%h%n%d%n%s\ \(%cr\)')"}") + commits=("${(f)"$(_call_program commits git --no-pager log $commit_opts -20 --format='%h%n%d%n%s\ \(%cr\)%n%p')"}") __git_command_successful $pipestatus || return 1 - for i j k in "$commits[@]" ; do + for i j k parents in "$commits[@]" ; do # Note: the after-the-colon part must be unique across the entire array; # see workers/34768 if (( $#commit_opts )); then @@ -5671,20 +5673,35 @@ __git_recent_commits () { # description unique (due to workers/34768), which we do by including the # hash. Git always prints enough hash digits to make the output unique.) label="[$i]" - elif (( distance_from_head == 0 )); then - label="[HEAD] " - elif (( distance_from_head == 1 )); then - label="[HEAD^] " - elif (( distance_from_head == 2 )); then - label="[HEAD^^] " - elif (( distance_from_head < 10 )); then - label="[HEAD~$distance_from_head] " + elif (( distance_from_head )) && [[ $i != $next_first_parent_ancestral_line_commit ]]; then + # The first commit (HEAD), and its ancestors along the first-parent line, + # get HEAD~$n labels. + # + # For other commits, we just print the hash. (${parents} does provide enough + # information to compute HEAD~3^2~4 -style labels, though, if somebody cared + # enough to implement that.) + label="[$i]" else - label="[HEAD~$distance_from_head]" + # Compute a first-parent-ancestry commit's label. + if false ; then + elif (( distance_from_head == 0 )); then + label="[HEAD] " + elif (( distance_from_head == 1 )); then + label="[HEAD^] " + elif (( distance_from_head == 2 )); then + label="[HEAD^^] " + elif (( distance_from_head < 10 )); then + label="[HEAD~$distance_from_head] " + else + label="[HEAD~$distance_from_head]" + fi + + # Prepare for the next first-parent-ancestry commit. + (( ++distance_from_head )) + next_first_parent_ancestral_line_commit=${parents%% *} fi # label is now 9 bytes, so the descriptions ($k) will be aligned. descr+=($i:"${label} $k") - (( ++distance_from_head )) j=${${j# \(}%\)} # strip leading ' (' and trailing ')' j=${j/ ->/,} # Convert " -> master, origin/master". -- cgit 1.4.1