Skip to content

Commit c3df27f

Browse files
rscharfegitster
authored andcommitted
blame: reserve mark column only if necessary
git blame prepends commit hashes of boundary commits with "^", ignored commits with "?" and unblamable commits with "*" and reserves one column for them by extending the hash abbreviation, to avoid showing ambiguous hashes. This reserved column wastes precious screen space, which can be especially irritating when using the option -b to blank out boundary commit hashes and not ignoring any commits. Reserve it only as needed, i.e. if any of those cases are actually shown. Pointed-out-by: Laszlo Ersek <laszlo.ersek@posteo.net> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent e9019fc commit c3df27f

3 files changed

Lines changed: 53 additions & 33 deletions

File tree

Documentation/git-blame.adoc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,12 @@ include::blame-options.adoc[]
8888
include::diff-algorithm-option.adoc[]
8989

9090
`--abbrev=<n>`::
91-
Instead of using the default _7+1_ hexadecimal digits as the
92-
abbreviated object name, use _<m>+1_ digits, where _<m>_ is at
93-
least _<n>_ but ensures the commit object names are unique.
94-
Note that 1 column
95-
is used for a caret to mark the boundary commit.
91+
Instead of using the default _7_ hexadecimal digits as the
92+
abbreviated object name, use at least _<n>_ digits, but ensure
93+
the commit object names are unique.
94+
If commits marked with caret (boundary), question mark (ignored)
95+
or asterisk (unblamable) are shown, extend unmarked object names
96+
to align them.
9697

9798

9899
THE DEFAULT FORMAT

builtin/blame.c

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,36 @@ static void determine_line_heat(struct commit_info *ci, const char **dest_color)
453453
*dest_color = colorfield[i].col;
454454
}
455455

456+
static inline int maybe_putc(int c, FILE *out)
457+
{
458+
return out ? putc(c, out) : 0;
459+
}
460+
461+
static size_t print_marks(FILE *out, const struct blame_entry *ent, int opt)
462+
{
463+
size_t len = 0;
464+
465+
if ((ent->suspect->commit->object.flags & UNINTERESTING) &&
466+
!blank_boundary && !(opt & OUTPUT_ANNOTATE_COMPAT)) {
467+
maybe_putc('^', out);
468+
len++;
469+
}
470+
if (mark_unblamable_lines && ent->unblamable) {
471+
maybe_putc('*', out);
472+
len++;
473+
}
474+
if (mark_ignored_lines && ent->ignored) {
475+
maybe_putc('?', out);
476+
len++;
477+
}
478+
return len;
479+
}
480+
481+
static size_t count_marks(const struct blame_entry *ent, int opt)
482+
{
483+
return print_marks(NULL, ent, opt);
484+
}
485+
456486
static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent,
457487
int opt, struct blame_entry *prev_ent)
458488
{
@@ -499,23 +529,10 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent,
499529
if (color)
500530
fputs(color, stdout);
501531

502-
if (suspect->commit->object.flags & UNINTERESTING) {
503-
if (blank_boundary) {
504-
memset(hex, ' ', strlen(hex));
505-
} else if (!(opt & OUTPUT_ANNOTATE_COMPAT)) {
506-
length--;
507-
putchar('^');
508-
}
509-
}
510-
511-
if (mark_unblamable_lines && ent->unblamable) {
512-
length--;
513-
putchar('*');
514-
}
515-
if (mark_ignored_lines && ent->ignored) {
516-
length--;
517-
putchar('?');
518-
}
532+
if ((suspect->commit->object.flags & UNINTERESTING) &&
533+
blank_boundary)
534+
memset(hex, ' ', strlen(hex));
535+
length -= print_marks(stdout, ent, opt);
519536

520537
printf("%.*s", (int)(length < GIT_MAX_HEXSZ ? length : GIT_MAX_HEXSZ), hex);
521538
if (opt & OUTPUT_ANNOTATE_COMPAT) {
@@ -647,11 +664,15 @@ static void find_alignment(struct blame_scoreboard *sb, int *option)
647664
struct blame_entry *e;
648665
int compute_auto_abbrev = (abbrev < 0);
649666
int auto_abbrev = DEFAULT_ABBREV;
667+
size_t max_marks_count = 0;
650668

651669
for (e = sb->ent; e; e = e->next) {
652670
struct blame_origin *suspect = e->suspect;
653671
int num;
672+
size_t marks_count = count_marks(e, *option);
654673

674+
if (max_marks_count < marks_count)
675+
max_marks_count = marks_count;
655676
if (compute_auto_abbrev)
656677
auto_abbrev = update_auto_abbrev(auto_abbrev, suspect);
657678
if (strcmp(suspect->path, sb->path))
@@ -685,8 +706,12 @@ static void find_alignment(struct blame_scoreboard *sb, int *option)
685706
max_score_digits = decimal_width(largest_score);
686707

687708
if (compute_auto_abbrev)
688-
/* one more abbrev length is needed for the boundary commit */
689-
abbrev = auto_abbrev + 1;
709+
abbrev = auto_abbrev;
710+
if (abbrev < (int)the_hash_algo->hexsz) {
711+
abbrev += max_marks_count;
712+
if (abbrev > (int)the_hash_algo->hexsz)
713+
abbrev = the_hash_algo->hexsz;
714+
}
690715
}
691716

692717
static void sanity_check_on_fail(struct blame_scoreboard *sb, int baa)
@@ -1047,10 +1072,7 @@ int cmd_blame(int argc,
10471072
} else if (show_progress < 0)
10481073
show_progress = isatty(2);
10491074

1050-
if (0 < abbrev && abbrev < (int)the_hash_algo->hexsz)
1051-
/* one more abbrev length is needed for the boundary commit */
1052-
abbrev++;
1053-
else if (!abbrev)
1075+
if (!abbrev)
10541076
abbrev = the_hash_algo->hexsz;
10551077

10561078
if (revs_file && read_ancestry(revs_file))

t/t8002-blame.sh

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,7 @@ test_expect_success 'set up abbrev tests' '
113113
'
114114

115115
test_expect_success 'blame --abbrev=<n> works' '
116-
# non-boundary commits get +1 for alignment
117-
check_abbrev 31 --abbrev=30 HEAD &&
116+
check_abbrev 30 --abbrev=30 HEAD &&
118117
check_abbrev 30 --abbrev=30 ^HEAD
119118
'
120119

@@ -141,10 +140,8 @@ test_expect_success 'blame --abbrev gets truncated with boundary commit' '
141140
'
142141

143142
test_expect_success 'blame --abbrev -b truncates the blank boundary' '
144-
# Note that `--abbrev=` always gets incremented by 1, which is why we
145-
# expect 11 leading spaces and not 10.
146143
cat >expect <<-EOF &&
147-
$(printf "%11s" "") (<author@example.com> 2005-04-07 15:45:13 -0700 1) abbrev
144+
$(printf "%10s" "") (<author@example.com> 2005-04-07 15:45:13 -0700 1) abbrev
148145
EOF
149146
git blame -b --abbrev=10 ^HEAD -- abbrev.t >actual &&
150147
test_cmp expect actual

0 commit comments

Comments
 (0)