X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=describe.c;h=8a9cd5d52c555330c512b977179ab030ccd28861;hb=fb6a9f93d39e4e5fdb83673a927f71a34e9fb7c0;hp=e1b6588c9b8d0bd70702a56e182b2352dacc4386;hpb=635d413430d5419cfd0ac18e2318cf46c1984750;p=git.git diff --git a/describe.c b/describe.c index e1b6588c..8a9cd5d5 100644 --- a/describe.c +++ b/describe.c @@ -5,14 +5,19 @@ #define SEEN (1u << 0) -static const char describe_usage[] = "git-describe [--all] *"; +static const char describe_usage[] = +"git-describe [--all] [--tags] [--abbrev=] *"; static int all = 0; /* Default to annotated tags only */ +static int tags = 0; /* But allow any tags if --tags is specified */ + +static int abbrev = DEFAULT_ABBREV; static int names = 0, allocs = 0; static struct commit_name { const struct commit *commit; - char path[]; + int prio; /* annotated tag = 2, tag = 1, head = 0 */ + char path[FLEX_ARRAY]; /* more */ } **name_array = NULL; static struct commit_name *match(struct commit *cmit) @@ -28,13 +33,16 @@ static struct commit_name *match(struct commit *cmit) return NULL; } -static void add_to_known_names(const char *path, const struct commit *commit) +static void add_to_known_names(const char *path, + const struct commit *commit, + int prio) { int idx; int len = strlen(path)+1; struct commit_name *name = xmalloc(sizeof(struct commit_name) + len); name->commit = commit; + name->prio = prio; memcpy(name->path, path, len); idx = names; if (idx >= allocs) { @@ -48,17 +56,32 @@ static void add_to_known_names(const char *path, const struct commit *commit) static int get_name(const char *path, const unsigned char *sha1) { struct commit *commit = lookup_commit_reference_gently(sha1, 1); + struct object *object; + int prio; + if (!commit) return 0; + object = parse_object(sha1); + /* If --all, then any refs are used. + * If --tags, then any tags are used. + * Otherwise only annotated tags are used. + */ + if (!strncmp(path, "refs/tags/", 10)) { + if (object->type == tag_type) + prio = 2; + else + prio = 1; + } + else + prio = 0; + if (!all) { - struct object *object; - if (strncmp(path, "refs/tags/", 10)) + if (!prio) return 0; - object = parse_object(sha1); - if (object->type != tag_type) + if (!tags && prio < 2) return 0; } - add_to_known_names(all ? path : path + 10, commit); + add_to_known_names(all ? path + 5 : path + 10, commit, prio); return 0; } @@ -68,15 +91,26 @@ static int compare_names(const void *_a, const void *_b) struct commit_name *b = *(struct commit_name **)_b; unsigned long a_date = a->commit->date; unsigned long b_date = b->commit->date; + + if (a->prio != b->prio) + return b->prio - a->prio; return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1; } -static void describe(struct commit *cmit) +static void describe(char *arg, int last_one) { + unsigned char sha1[20]; + struct commit *cmit; struct commit_list *list; static int initialized = 0; struct commit_name *n; + if (get_sha1(arg, sha1)) + die("Not a valid object name %s", arg); + cmit = lookup_commit_reference(sha1); + if (!cmit) + die("%s is not a valid '%s' object", arg, commit_type); + if (!initialized) { initialized = 1; for_each_ref(get_name); @@ -95,10 +129,14 @@ static void describe(struct commit *cmit) struct commit *c = pop_most_recent_commit(&list, SEEN); n = match(c); if (n) { - printf("%s-g%.8s\n", n->path, sha1_to_hex(cmit->object.sha1)); + printf("%s-g%s\n", n->path, + find_unique_abbrev(cmit->object.sha1, abbrev)); + if (!last_one) + clear_commit_marks(cmit, SEEN); return; } } + die("cannot describe '%s'", sha1_to_hex(cmit->object.sha1)); } int main(int argc, char **argv) @@ -107,19 +145,29 @@ int main(int argc, char **argv) for (i = 1; i < argc; i++) { const char *arg = argv[i]; - unsigned char sha1[20]; - struct commit *cmit; - if (!strcmp(arg, "--all")) { + if (*arg != '-') + break; + else if (!strcmp(arg, "--all")) all = 1; - continue; + else if (!strcmp(arg, "--tags")) + tags = 1; + else if (!strncmp(arg, "--abbrev=", 9)) { + abbrev = strtoul(arg + 9, NULL, 10); + if (abbrev < MINIMUM_ABBREV || 40 <= abbrev) + abbrev = DEFAULT_ABBREV; } - if (get_sha1(arg, sha1) < 0) - usage(describe_usage); - cmit = lookup_commit_reference(sha1); - if (!cmit) + else usage(describe_usage); - describe(cmit); } + + if (i == argc) + describe("HEAD", 1); + else + while (i < argc) { + describe(argv[i], (i == argc - 1)); + i++; + } + return 0; }