diff options
Diffstat (limited to 'builtin/name-rev.c')
-rw-r--r-- | builtin/name-rev.c | 68 |
1 files changed, 34 insertions, 34 deletions
diff --git a/builtin/name-rev.c b/builtin/name-rev.c index c824d4ec5f..57be35faf5 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -10,6 +10,7 @@ typedef struct rev_name { const char *tip_name; + unsigned long taggerdate; int generation; int distance; } rev_name; @@ -20,7 +21,8 @@ static long cutoff = LONG_MAX; #define MERGE_TRAVERSAL_WEIGHT 65535 static void name_rev(struct commit *commit, - const char *tip_name, int generation, int distance, + const char *tip_name, unsigned long taggerdate, + int generation, int distance, int deref) { struct rev_name *name = (struct rev_name *)commit->util; @@ -33,10 +35,7 @@ static void name_rev(struct commit *commit, return; if (deref) { - char *new_name = xmalloc(strlen(tip_name)+3); - strcpy(new_name, tip_name); - strcat(new_name, "^0"); - tip_name = new_name; + tip_name = xstrfmt("%s^0", tip_name); if (generation) die("generation: %d, but deref?", generation); @@ -46,9 +45,12 @@ static void name_rev(struct commit *commit, name = xmalloc(sizeof(rev_name)); commit->util = name; goto copy_data; - } else if (name->distance > distance) { + } else if (name->taggerdate > taggerdate || + (name->taggerdate == taggerdate && + name->distance > distance)) { copy_data: name->tip_name = tip_name; + name->taggerdate = taggerdate; name->generation = generation; name->distance = distance; } else @@ -58,26 +60,22 @@ copy_data: parents; parents = parents->next, parent_number++) { if (parent_number > 1) { - int len = strlen(tip_name); - char *new_name = xmalloc(len + - 1 + decimal_length(generation) + /* ~<n> */ - 1 + 2 + /* ^NN */ - 1); - - if (len > 2 && !strcmp(tip_name + len - 2, "^0")) - len -= 2; + size_t len; + char *new_name; + + strip_suffix(tip_name, "^0", &len); if (generation > 0) - sprintf(new_name, "%.*s~%d^%d", len, tip_name, - generation, parent_number); + new_name = xstrfmt("%.*s~%d^%d", (int)len, tip_name, + generation, parent_number); else - sprintf(new_name, "%.*s^%d", len, tip_name, - parent_number); + new_name = xstrfmt("%.*s^%d", (int)len, tip_name, + parent_number); - name_rev(parents->item, new_name, 0, + name_rev(parents->item, new_name, taggerdate, 0, distance + MERGE_TRAVERSAL_WEIGHT, 0); } else { - name_rev(parents->item, tip_name, generation + 1, - distance + 1, 0); + name_rev(parents->item, tip_name, taggerdate, + generation + 1, distance + 1, 0); } } } @@ -141,12 +139,13 @@ static int tipcmp(const void *a_, const void *b_) return hashcmp(a->sha1, b->sha1); } -static int name_ref(const char *path, const unsigned char *sha1, int flags, void *cb_data) +static int name_ref(const char *path, const struct object_id *oid, int flags, void *cb_data) { - struct object *o = parse_object(sha1); + struct object *o = parse_object(oid->hash); struct name_ref_data *data = cb_data; int can_abbreviate_output = data->tags_only && data->name_only; int deref = 0; + unsigned long taggerdate = ULONG_MAX; if (data->tags_only && !starts_with(path, "refs/tags/")) return 0; @@ -163,20 +162,21 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void } } - add_to_tip_table(sha1, path, can_abbreviate_output); + add_to_tip_table(oid->hash, path, can_abbreviate_output); while (o && o->type == OBJ_TAG) { struct tag *t = (struct tag *) o; if (!t->tagged) break; /* broken repository */ - o = parse_object(t->tagged->sha1); + o = parse_object(t->tagged->oid.hash); deref = 1; + taggerdate = t->date; } if (o && o->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)o; path = name_ref_abbrev(path, can_abbreviate_output); - name_rev(commit, xstrdup(path), 0, 0, deref); + name_rev(commit, xstrdup(path), taggerdate, 0, 0, deref); } return 0; } @@ -200,7 +200,7 @@ static const char *get_exact_ref_match(const struct object *o) tip_table.sorted = 1; } - found = sha1_pos(o->sha1, tip_table.table, tip_table.nr, + found = sha1_pos(o->oid.hash, tip_table.table, tip_table.nr, nth_tip_table_ent); if (0 <= found) return tip_table.table[found].refname; @@ -239,25 +239,25 @@ static void show_name(const struct object *obj, int always, int allow_undefined, int name_only) { const char *name; - const unsigned char *sha1 = obj->sha1; + const struct object_id *oid = &obj->oid; if (!name_only) - printf("%s ", caller_name ? caller_name : sha1_to_hex(sha1)); + printf("%s ", caller_name ? caller_name : oid_to_hex(oid)); name = get_rev_name(obj); if (name) printf("%s\n", name); else if (allow_undefined) printf("undefined\n"); else if (always) - printf("%s\n", find_unique_abbrev(sha1, DEFAULT_ABBREV)); + printf("%s\n", find_unique_abbrev(oid->hash, DEFAULT_ABBREV)); else - die("cannot describe '%s'", sha1_to_hex(sha1)); + die("cannot describe '%s'", oid_to_hex(oid)); } static char const * const name_rev_usage[] = { - N_("git name-rev [options] <commit>..."), - N_("git name-rev [options] --all"), - N_("git name-rev [options] --stdin"), + N_("git name-rev [<options>] <commit>..."), + N_("git name-rev [<options>] --all"), + N_("git name-rev [<options>] --stdin"), NULL }; |