diff options
Diffstat (limited to 'builtin/describe.c')
| -rw-r--r-- | builtin/describe.c | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/builtin/describe.c b/builtin/describe.c index 41606c8a90..21d2cb9e57 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -1,3 +1,4 @@ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "cache.h" #include "config.h" #include "lockfile.h" @@ -14,7 +15,6 @@ #include "argv-array.h" #include "run-command.h" #include "object-store.h" -#include "revision.h" #include "list-objects.h" #include "commit-slab.h" @@ -54,6 +54,7 @@ struct commit_name { struct tag *tag; unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */ unsigned name_checked:1; + unsigned misnamed:1; struct object_id oid; char *path; }; @@ -62,20 +63,23 @@ static const char *prio_names[] = { N_("head"), N_("lightweight"), N_("annotated"), }; -static int commit_name_cmp(const void *unused_cmp_data, - const void *entry, - const void *entry_or_key, +static int commit_name_neq(const void *unused_cmp_data, + const struct hashmap_entry *eptr, + const struct hashmap_entry *entry_or_key, const void *peeled) { - const struct commit_name *cn1 = entry; - const struct commit_name *cn2 = entry_or_key; + const struct commit_name *cn1, *cn2; + + cn1 = container_of(eptr, const struct commit_name, entry); + cn2 = container_of(entry_or_key, const struct commit_name, entry); - return oidcmp(&cn1->peeled, peeled ? peeled : &cn2->peeled); + return !oideq(&cn1->peeled, peeled ? peeled : &cn2->peeled); } static inline struct commit_name *find_commit_name(const struct object_id *peeled) { - return hashmap_get_from_hash(&names, sha1hash(peeled->hash), peeled->hash); + return hashmap_get_entry_from_hash(&names, oidhash(peeled), peeled, + struct commit_name, entry); } static int replace_name(struct commit_name *e, @@ -122,13 +126,14 @@ static void add_to_known_names(const char *path, if (!e) { e = xmalloc(sizeof(struct commit_name)); oidcpy(&e->peeled, peeled); - hashmap_entry_init(e, sha1hash(peeled->hash)); - hashmap_add(&names, e); + hashmap_entry_init(&e->entry, oidhash(peeled)); + hashmap_add(&names, &e->entry); e->path = NULL; } e->tag = tag; e->prio = prio; e->name_checked = 0; + e->misnamed = 0; oidcpy(&e->oid, oid); free(e->path); e->path = xstrdup(path); @@ -190,7 +195,7 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi /* Is it annotated? */ if (!peel_ref(path, &peeled)) { - is_annotated = !!oidcmp(oid, &peeled); + is_annotated = !oideq(oid, &peeled); } else { oidcpy(&peeled, oid); is_annotated = 0; @@ -272,10 +277,11 @@ static void append_name(struct commit_name *n, struct strbuf *dst) die(_("annotated tag %s not available"), n->path); } if (n->tag && !n->name_checked) { - if (!n->tag->tag) - die(_("annotated tag %s has no embedded name"), n->path); - if (strcmp(n->tag->tag, all ? n->path + 5 : n->path)) - warning(_("tag '%s' is really '%s' here"), n->tag->tag, n->path); + if (strcmp(n->tag->tag, all ? n->path + 5 : n->path)) { + warning(_("tag '%s' is externally known as '%s'"), + n->path, n->tag->tag); + n->misnamed = 1; + } n->name_checked = 1; } @@ -311,8 +317,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) * Exact match to an existing ref. */ append_name(n, dst); - if (longformat) - append_suffix(0, n->tag ? &n->tag->tagged->oid : oid, dst); + if (n->misnamed || longformat) + append_suffix(0, n->tag ? get_tagged_oid(n->tag) : oid, dst); if (suffix) strbuf_addstr(dst, suffix); return; @@ -329,8 +335,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) struct commit_name *n; init_commit_names(&commit_names); - n = hashmap_iter_first(&names, &iter); - for (; n; n = hashmap_iter_next(&iter)) { + hashmap_for_each_entry(&names, &iter, n, + entry /* member name */) { c = lookup_commit_reference_gently(the_repository, &n->peeled, 1); if (c) @@ -373,11 +379,25 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) if (!(c->object.flags & t->flag_within)) t->depth++; } + /* Stop if last remaining path already covered by best candidate(s) */ if (annotated_cnt && !list) { - if (debug) - fprintf(stderr, _("finished search at %s\n"), - oid_to_hex(&c->object.oid)); - break; + int best_depth = INT_MAX; + unsigned best_within = 0; + for (cur_match = 0; cur_match < match_cnt; cur_match++) { + struct possible_tag *t = &all_matches[cur_match]; + if (t->depth < best_depth) { + best_depth = t->depth; + best_within = t->flag_within; + } else if (t->depth == best_depth) { + best_within |= t->flag_within; + } + } + if ((c->object.flags & best_within) == best_within) { + if (debug) + fprintf(stderr, _("finished search at %s\n"), + oid_to_hex(&c->object.oid)); + break; + } } while (parents) { struct commit *p = parents->item; @@ -446,7 +466,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst) } append_name(all_matches[0].name, dst); - if (abbrev) + if (all_matches[0].name->misnamed || abbrev) append_suffix(all_matches[0].depth, &cmit->object.oid, dst); if (suffix) strbuf_addstr(dst, suffix); @@ -469,7 +489,7 @@ static void process_object(struct object *obj, const char *path, void *data) { struct process_commit_data *pcd = data; - if (!oidcmp(&pcd->looking_for, &obj->oid) && !pcd->dst->len) { + if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) { reset_revision_walk(); describe_commit(&pcd->current_commit, pcd->dst); strbuf_addf(pcd->dst, ":%s", path); @@ -488,7 +508,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst) "--objects", "--in-commit-order", "--reverse", "HEAD", NULL); - init_revisions(&revs, NULL); + repo_init_revisions(the_repository, &revs, NULL); if (setup_revisions(args.argc, args.argv, &revs, NULL) > 1) BUG("setup_revisions could not handle all args?"); @@ -596,7 +616,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix) return cmd_name_rev(args.argc, args.argv, prefix); } - hashmap_init(&names, commit_name_cmp, NULL, 0); + hashmap_init(&names, commit_name_neq, NULL, 0); for_each_rawref(get_name, NULL); if (!hashmap_get_size(&names) && !always) die(_("No names found, cannot describe anything.")); @@ -629,14 +649,15 @@ int cmd_describe(int argc, const char **argv, const char *prefix) struct argv_array args = ARGV_ARRAY_INIT; int fd, result; - read_cache_preload(NULL); + setup_work_tree(); + read_cache(); refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL); fd = hold_locked_index(&index_lock, 0); if (0 <= fd) - update_index_if_able(&the_index, &index_lock); + repo_update_index_if_able(the_repository, &index_lock); - init_revisions(&revs, prefix); + repo_init_revisions(the_repository, &revs, prefix); argv_array_pushv(&args, diff_index_args); if (setup_revisions(args.argc, args.argv, &revs, NULL) != 1) BUG("malformed internal diff-index command line"); |
