static void add_to_known_names(const char *path, const unsigned char *peeled, int prio, const unsigned char *sha1) { struct commit_name *e = find_commit_name(peeled); struct tag *tag = NULL; if (replace_name(e, prio, sha1, &tag)) { if (!e) { e = xmalloc(sizeof(struct commit_name)); hashcpy(e->peeled, peeled); hashmap_entry_init(e, hash_sha1(peeled)); hashmap_add(&names, e); e->path = NULL; } e->tag = tag; e->prio = prio; e->name_checked = 0; hashcpy(e->sha1, sha1); free(e->path); e->path = xstrdup(path); } }
static void describe(const char *arg, int last_one) { unsigned char sha1[20]; struct commit *cmit, *gave_up_on = NULL; struct commit_list *list; struct commit_name *n; struct possible_tag all_matches[MAX_TAGS]; unsigned int match_cnt = 0, annotated_cnt = 0, cur_match; unsigned long seen_commits = 0; unsigned int unannotated_cnt = 0; 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); n = find_commit_name(cmit->object.sha1); if (n && (tags || all || n->prio == 2)) { /* * Exact match to an existing ref. */ display_name(n); if (longformat) show_suffix(0, n->tag ? n->tag->tagged->sha1 : sha1); if (dirty) printf("%s", dirty); printf("\n"); return; } if (!max_candidates) die(_("no tag exactly matches '%s'"), sha1_to_hex(cmit->object.sha1)); if (debug) fprintf(stderr, _("searching to describe %s\n"), arg); if (!have_util) { for_each_hash(&names, set_util, NULL); have_util = 1; } list = NULL; cmit->object.flags = SEEN; commit_list_insert(cmit, &list); while (list) { struct commit *c = pop_commit(&list); struct commit_list *parents = c->parents; seen_commits++; n = c->util; if (n) { if (!tags && !all && n->prio < 2) { unannotated_cnt++; } else if (match_cnt < max_candidates) { struct possible_tag *t = &all_matches[match_cnt++]; t->name = n; t->depth = seen_commits - 1; t->flag_within = 1u << match_cnt; t->found_order = match_cnt; c->object.flags |= t->flag_within; if (n->prio == 2) annotated_cnt++; } else { gave_up_on = c; break; } } for (cur_match = 0; cur_match < match_cnt; cur_match++) { struct possible_tag *t = &all_matches[cur_match]; if (!(c->object.flags & t->flag_within)) t->depth++; } if (annotated_cnt && !list) { if (debug) fprintf(stderr, _("finished search at %s\n"), sha1_to_hex(c->object.sha1)); break; } while (parents) { struct commit *p = parents->item; parse_commit(p); if (!(p->object.flags & SEEN)) commit_list_insert_by_date(p, &list); p->object.flags |= c->object.flags; parents = parents->next; } } if (!match_cnt) { const unsigned char *sha1 = cmit->object.sha1; if (always) { printf("%s", find_unique_abbrev(sha1, abbrev)); if (dirty) printf("%s", dirty); printf("\n"); return; } if (unannotated_cnt) die(_("No annotated tags can describe '%s'.\n" "However, there were unannotated tags: try --tags."), sha1_to_hex(sha1)); else die(_("No tags can describe '%s'.\n" "Try --always, or create some tags."), sha1_to_hex(sha1)); } qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt); if (gave_up_on) { commit_list_insert_by_date(gave_up_on, &list); seen_commits--; } seen_commits += finish_depth_computation(&list, &all_matches[0]); free_commit_list(list); if (debug) { for (cur_match = 0; cur_match < match_cnt; cur_match++) { struct possible_tag *t = &all_matches[cur_match]; fprintf(stderr, " %-11s %8d %s\n", prio_names[t->name->prio], t->depth, t->name->path); } fprintf(stderr, _("traversed %lu commits\n"), seen_commits); if (gave_up_on) { fprintf(stderr, _("more than %i tags found; listed %i most recent\n" "gave up search at %s\n"), max_candidates, max_candidates, sha1_to_hex(gave_up_on->object.sha1)); } } display_name(all_matches[0].name); if (abbrev) show_suffix(all_matches[0].depth, cmit->object.sha1); if (dirty) printf("%s", dirty); printf("\n"); if (!last_one) clear_commit_marks(cmit, -1); }