Merge branch 'js/name-rev-use-oldest-ref' into maint

"git describe --contains" often made a hard-to-justify choice of
tag to give name to a given commit, because it tried to come up
with a name with smallest number of hops from a tag, causing an old
commit whose close descendant that is recently tagged were not
described with respect to an old tag but with a newer tag.  It did
not help that its computation of "hop" count was further tweaked to
penalize being on a side branch of a merge.  The logic has been
updated to favor using the tag with the oldest tagger date, which
is a lot easier to explain to the end users: "We describe a commit
in terms of the (chronologically) oldest tag that contains the
commit."

* js/name-rev-use-oldest-ref:
  name-rev: include taggerdate in considering the best name
This commit is contained in:
Junio C Hamano 2016-05-31 14:08:26 -07:00
commit 9ee8f9409c
2 changed files with 14 additions and 7 deletions

View file

@ -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;
@ -43,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
@ -66,11 +71,11 @@ static void name_rev(struct commit *commit,
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);
}
}
}
@ -140,6 +145,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
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;
@ -164,12 +170,13 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
break; /* broken repository */
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;
}

View file

@ -107,7 +107,7 @@ test_expect_success 'prompt - describe detached head - contains' '
'
test_expect_success 'prompt - describe detached head - branch' '
printf " ((b1~1))" >expected &&
printf " ((tags/t2~1))" >expected &&
git checkout b1^ &&
test_when_finished "git checkout master" &&
(