7 #include "parse-options.h"
 
  12 #define MAX_TAGS        (FLAG_BITS - 1)
 
  14 static const char * const describe_usage[] = {
 
  15         "git describe [options] <committish>*",
 
  16         "git describe [options] --dirty",
 
  20 static int debug;       /* Display lots of verbose info */
 
  21 static int all; /* Any valid ref can be used */
 
  22 static int tags;        /* Allow lightweight tags */
 
  23 static int longformat;
 
  24 static int abbrev = -1; /* unspecified */
 
  25 static int max_candidates = 10;
 
  26 static struct hash_table names;
 
  28 static const char *pattern;
 
  30 static const char *dirty;
 
  32 /* diff-index command arguments to check if working tree is dirty. */
 
  33 static const char *diff_index_args[] = {
 
  34         "diff-index", "--quiet", "HEAD", "--", NULL
 
  39         struct commit_name *next;
 
  40         unsigned char peeled[20];
 
  42         unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
 
  43         unsigned name_checked:1;
 
  44         unsigned char sha1[20];
 
  47 static const char *prio_names[] = {
 
  48         "head", "lightweight", "annotated",
 
  51 static inline unsigned int hash_sha1(const unsigned char *sha1)
 
  54         memcpy(&hash, sha1, sizeof(hash));
 
  58 static inline struct commit_name *find_commit_name(const unsigned char *peeled)
 
  60         struct commit_name *n = lookup_hash(hash_sha1(peeled), &names);
 
  61         while (n && !!hashcmp(peeled, n->peeled))
 
  66 static int set_util(void *chain, void *data)
 
  68         struct commit_name *n;
 
  69         for (n = chain; n; n = n->next) {
 
  70                 struct commit *c = lookup_commit_reference_gently(n->peeled, 1);
 
  77 static int replace_name(struct commit_name *e,
 
  79                                const unsigned char *sha1,
 
  82         if (!e || e->prio < prio)
 
  85         if (e->prio == 2 && prio == 2) {
 
  86                 /* Multiple annotated tags point to the same commit.
 
  87                  * Select one to keep based upon their tagger date.
 
  92                         t = lookup_tag(e->sha1);
 
  93                         if (!t || parse_tag(t))
 
  99                 if (!t || parse_tag(t))
 
 103                 if (e->tag->date < t->date)
 
 110 static void add_to_known_names(const char *path,
 
 111                                const unsigned char *peeled,
 
 113                                const unsigned char *sha1)
 
 115         struct commit_name *e = find_commit_name(peeled);
 
 116         struct tag *tag = NULL;
 
 117         if (replace_name(e, prio, sha1, &tag)) {
 
 120                         e = xmalloc(sizeof(struct commit_name));
 
 121                         hashcpy(e->peeled, peeled);
 
 122                         pos = insert_hash(hash_sha1(peeled), e, &names);
 
 133                 hashcpy(e->sha1, sha1);
 
 138 static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 
 140         int might_be_tag = !prefixcmp(path, "refs/tags/");
 
 141         unsigned char peeled[20];
 
 144         if (!all && !might_be_tag)
 
 147         if (!peel_ref(path, peeled) && !is_null_sha1(peeled)) {
 
 148                 is_tag = !!hashcmp(sha1, peeled);
 
 150                 hashcpy(peeled, sha1);
 
 154         /* If --all, then any refs are used.
 
 155          * If --tags, then any tags are used.
 
 156          * Otherwise only annotated tags are used.
 
 164                 if (pattern && fnmatch(pattern, path + 10, 0))
 
 174         add_to_known_names(all ? path + 5 : path + 10, peeled, prio, sha1);
 
 178 struct possible_tag {
 
 179         struct commit_name *name;
 
 182         unsigned flag_within;
 
 185 static int compare_pt(const void *a_, const void *b_)
 
 187         struct possible_tag *a = (struct possible_tag *)a_;
 
 188         struct possible_tag *b = (struct possible_tag *)b_;
 
 189         if (a->depth != b->depth)
 
 190                 return a->depth - b->depth;
 
 191         if (a->found_order != b->found_order)
 
 192                 return a->found_order - b->found_order;
 
 196 static unsigned long finish_depth_computation(
 
 197         struct commit_list **list,
 
 198         struct possible_tag *best)
 
 200         unsigned long seen_commits = 0;
 
 202                 struct commit *c = pop_commit(list);
 
 203                 struct commit_list *parents = c->parents;
 
 205                 if (c->object.flags & best->flag_within) {
 
 206                         struct commit_list *a = *list;
 
 208                                 struct commit *i = a->item;
 
 209                                 if (!(i->object.flags & best->flag_within))
 
 218                         struct commit *p = parents->item;
 
 220                         if (!(p->object.flags & SEEN))
 
 221                                 commit_list_insert_by_date(p, list);
 
 222                         p->object.flags |= c->object.flags;
 
 223                         parents = parents->next;
 
 229 static void display_name(struct commit_name *n)
 
 231         if (n->prio == 2 && !n->tag) {
 
 232                 n->tag = lookup_tag(n->sha1);
 
 233                 if (!n->tag || parse_tag(n->tag))
 
 234                         die(_("annotated tag %s not available"), n->path);
 
 236         if (n->tag && !n->name_checked) {
 
 238                         die(_("annotated tag %s has no embedded name"), n->path);
 
 239                 if (strcmp(n->tag->tag, all ? n->path + 5 : n->path))
 
 240                         warning(_("tag '%s' is really '%s' here"), n->tag->tag, n->path);
 
 245                 printf("%s", n->tag->tag);
 
 247                 printf("%s", n->path);
 
 250 static void show_suffix(int depth, const unsigned char *sha1)
 
 252         printf("-%d-g%s", depth, find_unique_abbrev(sha1, abbrev));
 
 255 static void describe(const char *arg, int last_one)
 
 257         unsigned char sha1[20];
 
 258         struct commit *cmit, *gave_up_on = NULL;
 
 259         struct commit_list *list;
 
 260         struct commit_name *n;
 
 261         struct possible_tag all_matches[MAX_TAGS];
 
 262         unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
 
 263         unsigned long seen_commits = 0;
 
 264         unsigned int unannotated_cnt = 0;
 
 266         if (get_sha1(arg, sha1))
 
 267                 die(_("Not a valid object name %s"), arg);
 
 268         cmit = lookup_commit_reference(sha1);
 
 270                 die(_("%s is not a valid '%s' object"), arg, commit_type);
 
 272         n = find_commit_name(cmit->object.sha1);
 
 273         if (n && (tags || all || n->prio == 2)) {
 
 275                  * Exact match to an existing ref.
 
 279                         show_suffix(0, n->tag ? n->tag->tagged->sha1 : sha1);
 
 287                 die(_("no tag exactly matches '%s'"), sha1_to_hex(cmit->object.sha1));
 
 289                 fprintf(stderr, _("searching to describe %s\n"), arg);
 
 292                 for_each_hash(&names, set_util, NULL);
 
 297         cmit->object.flags = SEEN;
 
 298         commit_list_insert(cmit, &list);
 
 300                 struct commit *c = pop_commit(&list);
 
 301                 struct commit_list *parents = c->parents;
 
 305                         if (!tags && !all && n->prio < 2) {
 
 307                         } else if (match_cnt < max_candidates) {
 
 308                                 struct possible_tag *t = &all_matches[match_cnt++];
 
 310                                 t->depth = seen_commits - 1;
 
 311                                 t->flag_within = 1u << match_cnt;
 
 312                                 t->found_order = match_cnt;
 
 313                                 c->object.flags |= t->flag_within;
 
 322                 for (cur_match = 0; cur_match < match_cnt; cur_match++) {
 
 323                         struct possible_tag *t = &all_matches[cur_match];
 
 324                         if (!(c->object.flags & t->flag_within))
 
 327                 if (annotated_cnt && !list) {
 
 329                                 fprintf(stderr, _("finished search at %s\n"),
 
 330                                         sha1_to_hex(c->object.sha1));
 
 334                         struct commit *p = parents->item;
 
 336                         if (!(p->object.flags & SEEN))
 
 337                                 commit_list_insert_by_date(p, &list);
 
 338                         p->object.flags |= c->object.flags;
 
 339                         parents = parents->next;
 
 344                 const unsigned char *sha1 = cmit->object.sha1;
 
 346                         printf("%s", find_unique_abbrev(sha1, abbrev));
 
 353                         die(_("No annotated tags can describe '%s'.\n"
 
 354                             "However, there were unannotated tags: try --tags."),
 
 357                         die(_("No tags can describe '%s'.\n"
 
 358                             "Try --always, or create some tags."),
 
 362         qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt);
 
 365                 commit_list_insert_by_date(gave_up_on, &list);
 
 368         seen_commits += finish_depth_computation(&list, &all_matches[0]);
 
 369         free_commit_list(list);
 
 372                 for (cur_match = 0; cur_match < match_cnt; cur_match++) {
 
 373                         struct possible_tag *t = &all_matches[cur_match];
 
 374                         fprintf(stderr, " %-11s %8d %s\n",
 
 375                                 prio_names[t->name->prio],
 
 376                                 t->depth, t->name->path);
 
 378                 fprintf(stderr, _("traversed %lu commits\n"), seen_commits);
 
 381                                 _("more than %i tags found; listed %i most recent\n"
 
 382                                 "gave up search at %s\n"),
 
 383                                 max_candidates, max_candidates,
 
 384                                 sha1_to_hex(gave_up_on->object.sha1));
 
 388         display_name(all_matches[0].name);
 
 390                 show_suffix(all_matches[0].depth, cmit->object.sha1);
 
 396                 clear_commit_marks(cmit, -1);
 
 399 int cmd_describe(int argc, const char **argv, const char *prefix)
 
 402         struct option options[] = {
 
 403                 OPT_BOOLEAN(0, "contains",   &contains, "find the tag that comes after the commit"),
 
 404                 OPT_BOOLEAN(0, "debug",      &debug, "debug search strategy on stderr"),
 
 405                 OPT_BOOLEAN(0, "all",        &all, "use any ref in .git/refs"),
 
 406                 OPT_BOOLEAN(0, "tags",       &tags, "use any tag in .git/refs/tags"),
 
 407                 OPT_BOOLEAN(0, "long",       &longformat, "always use long format"),
 
 408                 OPT__ABBREV(&abbrev),
 
 409                 OPT_SET_INT(0, "exact-match", &max_candidates,
 
 410                             "only output exact matches", 0),
 
 411                 OPT_INTEGER(0, "candidates", &max_candidates,
 
 412                             "consider <n> most recent tags (default: 10)"),
 
 413                 OPT_STRING(0, "match",       &pattern, "pattern",
 
 414                            "only consider tags matching <pattern>"),
 
 415                 OPT_BOOLEAN(0, "always",     &always,
 
 416                            "show abbreviated commit object as fallback"),
 
 417                 {OPTION_STRING, 0, "dirty",  &dirty, "mark",
 
 418                            "append <mark> on dirty working tree (default: \"-dirty\")",
 
 419                  PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
 
 423         git_config(git_default_config, NULL);
 
 424         argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
 
 426                 abbrev = DEFAULT_ABBREV;
 
 428         if (max_candidates < 0)
 
 430         else if (max_candidates > MAX_TAGS)
 
 431                 max_candidates = MAX_TAGS;
 
 433         save_commit_buffer = 0;
 
 435         if (longformat && abbrev == 0)
 
 436                 die(_("--long is incompatible with --abbrev=0"));
 
 439                 const char **args = xmalloc((7 + argc) * sizeof(char *));
 
 441                 args[i++] = "name-rev";
 
 442                 args[i++] = "--name-only";
 
 443                 args[i++] = "--no-undefined";
 
 445                         args[i++] = "--always";
 
 447                         args[i++] = "--tags";
 
 449                                 char *s = xmalloc(strlen("--refs=refs/tags/") + strlen(pattern) + 1);
 
 450                                 sprintf(s, "--refs=refs/tags/%s", pattern);
 
 454                 memcpy(args + i, argv, argc * sizeof(char *));
 
 455                 args[i + argc] = NULL;
 
 456                 return cmd_name_rev(i + argc, args, prefix);
 
 460         for_each_rawref(get_name, NULL);
 
 461         if (!names.nr && !always)
 
 462                 die(_("No names found, cannot describe anything."));
 
 465                 if (dirty && !cmd_diff_index(ARRAY_SIZE(diff_index_args) - 1, diff_index_args, prefix))
 
 469                 die(_("--dirty is incompatible with committishes"));
 
 472                         describe(*argv++, argc == 0);