blame: compute abbreviation width that ensures uniqueness

Julia Lawall noticed that in linux-next repository the commit object 60d5c9f5 (shown with the default abbreviation width baked into "git blame") in output from $ git blame -L 3675,3675 60d5c9f5b -- \ drivers/staging/brcm80211/brcmfmac/wl_iw.c is no longer unique in the repository, which results in "short SHA1 60d5c9f5 is ambiguous". Compute the minimum abbreviation width that ensures uniqueness when the user did not specify the --abbrev option to avoid this. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Jul 2, 2012 at 00:54 UTC b31272f704d03258a90b0e83e0f5c8df5c038ae6
1 file changed +21 -4
builtin/blame.c
+21 -4
@@ -1828,6 +1828,16 @@ static int read_ancestry(const char *graft_file)
1828 return 0;
1829 }
1830
1831 +static int update_auto_abbrev(int auto_abbrev, struct origin *suspect)
1832 +{
1833 + const char *uniq = find_unique_abbrev(suspect->commit->object.sha1,
1834 + auto_abbrev);
1835 + int len = strlen(uniq);
1836 + if (auto_abbrev < len)
1837 + return len;
1838 + return auto_abbrev;
1839 +}
1840 +
1841 /*
1842 * How many columns do we need to show line numbers in decimal?
1843 */
@@ -1850,12 +1860,16 @@ static void find_alignment(struct scoreboard *sb, int *option)
1860 int longest_dst_lines = 0;
1861 unsigned largest_score = 0;
1862 struct blame_entry *e;
1863 + int compute_auto_abbrev = (abbrev < 0);
1864 + int auto_abbrev = default_abbrev;
1865
1866 for (e = sb->ent; e; e = e->next) {
1867 struct origin *suspect = e->suspect;
1868 struct commit_info ci;
1869 int num;
1870
1871 + if (compute_auto_abbrev)
1872 + auto_abbrev = update_auto_abbrev(auto_abbrev, suspect);
1873 if (strcmp(suspect->path, sb->path))
1874 *option |= OUTPUT_SHOW_NAME;
1875 num = strlen(suspect->path);
@@ -1883,6 +1897,10 @@ static void find_alignment(struct scoreboard *sb, int *option)
1897 max_orig_digits = lineno_width(longest_src_lines);
1898 max_digits = lineno_width(longest_dst_lines);
1899 max_score_digits = lineno_width(largest_score);
1900 +
1901 + if (compute_auto_abbrev)
1902 + /* one more abbrev length is needed for the boundary commit */
1903 + abbrev = auto_abbrev + 1;
1904 }
1905
1906 /*
@@ -2360,10 +2378,9 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2378 parse_done:
2379 argc = parse_options_end(&ctx);
2380
2363 - if (abbrev == -1)
2364 - abbrev = default_abbrev;
2365 - /* one more abbrev length is needed for the boundary commit */
2366 - abbrev++;
2381 + if (0 < abbrev)
2382 + /* one more abbrev length is needed for the boundary commit */
2383 + abbrev++;
2384
2385 if (revs_file && read_ancestry(revs_file))
2386 die_errno("reading graft file '%s' failed", revs_file);