summaryrefslogtreecommitdiff
path: root/builtin/describe.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/describe.c')
-rw-r--r--builtin/describe.c109
1 files changed, 64 insertions, 45 deletions
diff --git a/builtin/describe.c b/builtin/describe.c
index 1409cedce2..e912ba50d7 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -12,10 +12,9 @@
#include "revision.h"
#include "diff.h"
#include "hashmap.h"
-#include "argv-array.h"
+#include "strvec.h"
#include "run-command.h"
#include "object-store.h"
-#include "revision.h"
#include "list-objects.h"
#include "commit-slab.h"
@@ -55,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;
};
@@ -64,19 +64,22 @@ static const char *prio_names[] = {
};
static int commit_name_neq(const void *unused_cmp_data,
- const void *entry,
- const void *entry_or_key,
+ 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 !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,
@@ -123,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 +194,7 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
}
/* Is it annotated? */
- if (!peel_ref(path, &peeled)) {
+ if (!peel_iterated_oid(oid, &peeled)) {
is_annotated = !oideq(oid, &peeled);
} else {
oidcpy(&peeled, oid);
@@ -273,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;
}
@@ -312,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;
@@ -330,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)
@@ -374,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;
@@ -447,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);
@@ -482,15 +501,15 @@ static void process_object(struct object *obj, const char *path, void *data)
static void describe_blob(struct object_id oid, struct strbuf *dst)
{
struct rev_info revs;
- struct argv_array args = ARGV_ARRAY_INIT;
- struct process_commit_data pcd = { null_oid, oid, dst, &revs};
+ struct strvec args = STRVEC_INIT;
+ struct process_commit_data pcd = { *null_oid(), oid, dst, &revs};
- argv_array_pushl(&args, "internal: The first arg is not parsed",
- "--objects", "--in-commit-order", "--reverse", "HEAD",
- NULL);
+ strvec_pushl(&args, "internal: The first arg is not parsed",
+ "--objects", "--in-commit-order", "--reverse", "HEAD",
+ NULL);
repo_init_revisions(the_repository, &revs, NULL);
- if (setup_revisions(args.argc, args.argv, &revs, NULL) > 1)
+ if (setup_revisions(args.nr, args.v, &revs, NULL) > 1)
BUG("setup_revisions could not handle all args?");
if (prepare_revision_walk(&revs))
@@ -575,26 +594,26 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
if (contains) {
struct string_list_item *item;
- struct argv_array args;
+ struct strvec args;
- argv_array_init(&args);
- argv_array_pushl(&args, "name-rev",
- "--peel-tag", "--name-only", "--no-undefined",
- NULL);
+ strvec_init(&args);
+ strvec_pushl(&args, "name-rev",
+ "--peel-tag", "--name-only", "--no-undefined",
+ NULL);
if (always)
- argv_array_push(&args, "--always");
+ strvec_push(&args, "--always");
if (!all) {
- argv_array_push(&args, "--tags");
+ strvec_push(&args, "--tags");
for_each_string_list_item(item, &patterns)
- argv_array_pushf(&args, "--refs=refs/tags/%s", item->string);
+ strvec_pushf(&args, "--refs=refs/tags/%s", item->string);
for_each_string_list_item(item, &exclude_patterns)
- argv_array_pushf(&args, "--exclude=refs/tags/%s", item->string);
+ strvec_pushf(&args, "--exclude=refs/tags/%s", item->string);
}
if (argc)
- argv_array_pushv(&args, argv);
+ strvec_pushv(&args, argv);
else
- argv_array_push(&args, "HEAD");
- return cmd_name_rev(args.argc, args.argv, prefix);
+ strvec_push(&args, "HEAD");
+ return cmd_name_rev(args.nr, args.v, prefix);
}
hashmap_init(&names, commit_name_neq, NULL, 0);
@@ -605,7 +624,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
if (argc == 0) {
if (broken) {
struct child_process cp = CHILD_PROCESS_INIT;
- argv_array_pushv(&cp.args, diff_index_args);
+ strvec_pushv(&cp.args, diff_index_args);
cp.git_cmd = 1;
cp.no_stdin = 1;
cp.no_stdout = 1;
@@ -627,7 +646,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
} else if (dirty) {
struct lock_file index_lock = LOCK_INIT;
struct rev_info revs;
- struct argv_array args = ARGV_ARRAY_INIT;
+ struct strvec args = STRVEC_INIT;
int fd, result;
setup_work_tree();
@@ -639,8 +658,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
repo_update_index_if_able(the_repository, &index_lock);
repo_init_revisions(the_repository, &revs, prefix);
- argv_array_pushv(&args, diff_index_args);
- if (setup_revisions(args.argc, args.argv, &revs, NULL) != 1)
+ strvec_pushv(&args, diff_index_args);
+ if (setup_revisions(args.nr, args.v, &revs, NULL) != 1)
BUG("malformed internal diff-index command line");
result = run_diff_index(&revs, 0);