X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=describe.c;h=84d96b5b82bf5d1b688da39208077df5ca6ef6d9;hb=c06818e20a88f58294de0a948a437c7c32c382fe;hp=ba49d0027092393a6b0b578dafdbfef15f791eaf;hpb=4cdf78bf964912698ab33579977f21a3e0b832ed;p=git.git diff --git a/describe.c b/describe.c index ba49d002..84d96b5b 100644 --- a/describe.c +++ b/describe.c @@ -5,13 +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 */ + +#define DEFAULT_ABBREV 8 /* maybe too many */ +static int abbrev = DEFAULT_ABBREV; static int names = 0, allocs = 0; static struct commit_name { const struct commit *commit; + int prio; /* annotated tag = 2, tag = 1, head = 0 */ char path[]; } **name_array = NULL; @@ -28,13 +34,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 +57,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,6 +92,9 @@ 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; } @@ -96,7 +123,7 @@ static void describe(struct commit *cmit) n = match(c); if (n) { printf("%s-g%s\n", n->path, - find_unique_abbrev(cmit->object.sha1, 8)); + find_unique_abbrev(cmit->object.sha1, abbrev)); return; } } @@ -115,6 +142,16 @@ int main(int argc, char **argv) all = 1; continue; } + if (!strcmp(arg, "--tags")) { + tags = 1; + continue; + } + if (!strncmp(arg, "--abbrev=", 9)) { + abbrev = strtoul(arg + 9, NULL, 10); + if (abbrev < 4 || 40 <= abbrev) + abbrev = DEFAULT_ABBREV; + continue; + } if (get_sha1(arg, sha1) < 0) usage(describe_usage); cmit = lookup_commit_reference(sha1);