From 013f276eb78967f9742654ebde303c2fbe7a6cd6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 11 Oct 2005 15:22:48 -0700 Subject: [PATCH 1/1] show-branch: optionally use unique prefix as name. git-show-branch acquires two new options. --sha1-name to name commits using the unique prefix of their object names, and --no-name to not to show names at all. This was outlined in <7vk6gpyuyr.fsf@assigned-by-dhcp.cox.net> Signed-off-by: Junio C Hamano --- Documentation/git-show-branch.txt | 26 +++++++---------- cache.h | 1 + sha1_name.c | 40 +++++++++++++++++++++----- show-branch.c | 59 +++++++++++++++++++++++++-------------- 4 files changed, 82 insertions(+), 44 deletions(-) diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index e0dce7ec..c6c97b21 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -7,7 +7,7 @@ git-show-branch - Show branches and their commits. SYNOPSIS -------- -'git-show-branch [--all] [--heads] [--tags] [--more= | --list | --independent | --merge-base] ...' +'git-show-branch [--all] [--heads] [--tags] [--more= | --list | --independent | --merge-base] [--no-name | --sha1-name] ...' DESCRIPTION ----------- @@ -44,6 +44,15 @@ OPTIONS Among the s given, display only the ones that cannot be reached from any other . +--no-name:: + Do not show naming strings for each commit. + +--sha1-name:: + Instead of naming the commits using the path to reach + them from heads (e.g. "master~2" to mean the grandparent + of "master"), name them with the unique prefix of their + object names. + Note that --more, --list, --independent and --merge-base options are mutually exclusive. @@ -88,21 +97,6 @@ whose commit message is "Add 'git show-branch'. "fixes" branch adds one commit 'Introduce "reset type"'. "mhf" branch has many other commits. -When only one head is given, the output format changes slightly -to conserve space. The '+' sign to show which commit is -reachable from which head and the first N lines to show the list -of heads being displayed are both meaningless so they are -omitted. Also the label given to each commit does not repeat -the name of the branch because it is obvious. - ------------------------------------------------- -$ git show-branch --more=4 master -[master] Add 'git show-branch'. -[~1] Add a new extended SHA1 syntax ~ -[~2] Fix "git-diff A B" -[~3] git-ls-files: generalized pathspecs -[~4] Make "git-ls-files" work in subdirectories ------------------------------------------------- Author ------ diff --git a/cache.h b/cache.h index 64cbcac5..41cc22c1 100644 --- a/cache.h +++ b/cache.h @@ -194,6 +194,7 @@ extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2) extern char *sha1_file_name(const unsigned char *sha1); extern char *sha1_pack_name(const unsigned char *sha1); extern char *sha1_pack_index_name(const unsigned char *sha1); +extern const char *find_unique_abbrev(const unsigned char *sha1, int); extern const unsigned char null_sha1[20]; int git_mkstemp(char *path, size_t n, const char *template); diff --git a/sha1_name.c b/sha1_name.c index f64755fb..4e9a0523 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -119,6 +119,9 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne return found; } +#define SHORT_NAME_NOT_FOUND (-1) +#define SHORT_NAME_AMBIGUOUS (-2) + static int find_unique_short_object(int len, char *canonical, unsigned char *res, unsigned char *sha1) { @@ -128,23 +131,24 @@ static int find_unique_short_object(int len, char *canonical, has_unpacked = find_short_object_filename(len, canonical, unpacked_sha1); has_packed = find_short_packed_object(len, res, packed_sha1); if (!has_unpacked && !has_packed) - return -1; + return SHORT_NAME_NOT_FOUND; if (1 < has_unpacked || 1 < has_packed) - return error("short SHA1 %.*s is ambiguous.", len, canonical); + return SHORT_NAME_AMBIGUOUS; if (has_unpacked != has_packed) { memcpy(sha1, (has_packed ? packed_sha1 : unpacked_sha1), 20); return 0; } /* Both have unique ones -- do they match? */ if (memcmp(packed_sha1, unpacked_sha1, 20)) - return error("short SHA1 %.*s is ambiguous.", len, canonical); + return -2; memcpy(sha1, packed_sha1, 20); return 0; } -static int get_short_sha1(const char *name, int len, unsigned char *sha1) +static int get_short_sha1(const char *name, int len, unsigned char *sha1, + int quietly) { - int i; + int i, status; char canonical[40]; unsigned char res[20]; @@ -171,7 +175,29 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1) res[i >> 1] |= val; } - return find_unique_short_object(i, canonical, res, sha1); + status = find_unique_short_object(i, canonical, res, sha1); + if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) + return error("short SHA1 %.*s is ambiguous.", len, canonical); + return status; +} + +const char *find_unique_abbrev(const unsigned char *sha1, int len) +{ + int status; + static char hex[41]; + memcpy(hex, sha1_to_hex(sha1), 40); + while (len < 40) { + unsigned char sha1_ret[20]; + status = get_short_sha1(hex, len, sha1_ret, 1); + if (!status) { + hex[len] = 0; + return hex; + } + if (status != SHORT_NAME_AMBIGUOUS) + return NULL; + len++; + } + return NULL; } static int get_sha1_basic(const char *str, int len, unsigned char *sha1) @@ -292,7 +318,7 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1) ret = get_sha1_basic(name, len, sha1); if (!ret) return 0; - return get_short_sha1(name, len, sha1); + return get_short_sha1(name, len, sha1, 0); } /* diff --git a/show-branch.c b/show-branch.c index 8429c171..bb14c867 100644 --- a/show-branch.c +++ b/show-branch.c @@ -133,25 +133,28 @@ static void name_commits(struct commit_list *list, nth = 0; while (parents) { struct commit *p = parents->item; - char newname[1000]; + char newname[1000], *en; parents = parents->next; nth++; if (p->object.util) continue; + en = newname; switch (n->generation) { case 0: - sprintf(newname, "%s^%d", - n->head_name, nth); + en += sprintf(en, "%s", n->head_name); break; case 1: - sprintf(newname, "%s^^%d", - n->head_name, nth); + en += sprintf(en, "%s^", n->head_name); break; default: - sprintf(newname, "%s~%d^%d", - n->head_name, n->generation, - nth); + en += sprintf(en, "%s~%d", + n->head_name, n->generation); + break; } + if (nth == 1) + en += sprintf(en, "^"); + else + en += sprintf(en, "^%d", nth); name_commit(p, strdup(newname), 0); i++; name_first_parent_chain(p); @@ -205,7 +208,7 @@ static void join_revs(struct commit_list **list_p, } } -static void show_one_commit(struct commit *commit) +static void show_one_commit(struct commit *commit, int no_name) { char pretty[128], *cp; struct commit_name *name = commit->object.util; @@ -218,11 +221,21 @@ static void show_one_commit(struct commit *commit) cp = pretty + 8; else cp = pretty; - if (name && name->head_name) { - printf("[%s", name->head_name); - if (name->generation) - printf("~%d", name->generation); - printf("] "); + + if (!no_name) { + if (name && name->head_name) { + printf("[%s", name->head_name); + if (name->generation) { + if (name->generation == 1) + printf("^"); + else + printf("~%d", name->generation); + } + printf("] "); + } + else + printf("[%s] ", + find_unique_abbrev(commit->object.sha1, 7)); } puts(cp); } @@ -354,7 +367,8 @@ int main(int ac, char **av) unsigned char head_sha1[20]; int merge_base = 0; int independent = 0; - char **label; + int no_name = 0; + int sha1_name = 0; setup_git_directory(); @@ -370,6 +384,10 @@ int main(int ac, char **av) extra = 1; else if (!strcmp(arg, "--list")) extra = -1; + else if (!strcmp(arg, "--no-name")) + no_name = 1; + else if (!strcmp(arg, "--sha1-name")) + sha1_name = 1; else if (!strncmp(arg, "--more=", 7)) extra = atoi(arg + 7); else if (!strcmp(arg, "--merge-base")) @@ -465,7 +483,8 @@ int main(int ac, char **av) printf("%c [%s] ", is_head ? '*' : '!', ref_name[i]); } - show_one_commit(rev[i]); + /* header lines never need name */ + show_one_commit(rev[i], 1); } if (0 <= extra) { for (i = 0; i < num_rev; i++) @@ -480,7 +499,8 @@ int main(int ac, char **av) sort_in_topological_order(&seen); /* Give names to commits */ - name_commits(seen, rev, ref_name, num_rev); + if (!sha1_name && !no_name) + name_commits(seen, rev, ref_name, num_rev); all_mask = ((1u << (REV_SHIFT + num_rev)) - 1); all_revs = all_mask & ~((1u << REV_SHIFT) - 1); @@ -490,7 +510,6 @@ int main(int ac, char **av) struct commit *commit = pop_one_commit(&seen); int this_flag = commit->object.flags; int is_merge_point = (this_flag & all_revs) == all_revs; - static char *obvious[] = { "" }; if (is_merge_point) shown_merge_point = 1; @@ -501,9 +520,7 @@ int main(int ac, char **av) ? '+' : ' '); putchar(' '); } - show_one_commit(commit); - if (num_rev == 1) - label = obvious; + show_one_commit(commit, no_name); if (shown_merge_point && is_merge_point) if (--extra < 0) break; -- 2.11.0