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
Родитель b051c59a00 7550424804
Коммит 9ee8f9409c
2 изменённых файлов: 14 добавлений и 7 удалений

Просмотреть файл

@ -10,6 +10,7 @@
typedef struct rev_name { typedef struct rev_name {
const char *tip_name; const char *tip_name;
unsigned long taggerdate;
int generation; int generation;
int distance; int distance;
} rev_name; } rev_name;
@ -20,7 +21,8 @@ static long cutoff = LONG_MAX;
#define MERGE_TRAVERSAL_WEIGHT 65535 #define MERGE_TRAVERSAL_WEIGHT 65535
static void name_rev(struct commit *commit, 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) int deref)
{ {
struct rev_name *name = (struct rev_name *)commit->util; 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)); name = xmalloc(sizeof(rev_name));
commit->util = name; commit->util = name;
goto copy_data; goto copy_data;
} else if (name->distance > distance) { } else if (name->taggerdate > taggerdate ||
(name->taggerdate == taggerdate &&
name->distance > distance)) {
copy_data: copy_data:
name->tip_name = tip_name; name->tip_name = tip_name;
name->taggerdate = taggerdate;
name->generation = generation; name->generation = generation;
name->distance = distance; name->distance = distance;
} else } else
@ -66,11 +71,11 @@ copy_data:
new_name = xstrfmt("%.*s^%d", (int)len, tip_name, new_name = xstrfmt("%.*s^%d", (int)len, tip_name,
parent_number); parent_number);
name_rev(parents->item, new_name, 0, name_rev(parents->item, new_name, taggerdate, 0,
distance + MERGE_TRAVERSAL_WEIGHT, 0); distance + MERGE_TRAVERSAL_WEIGHT, 0);
} else { } else {
name_rev(parents->item, tip_name, generation + 1, name_rev(parents->item, tip_name, taggerdate,
distance + 1, 0); 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; struct name_ref_data *data = cb_data;
int can_abbreviate_output = data->tags_only && data->name_only; int can_abbreviate_output = data->tags_only && data->name_only;
int deref = 0; int deref = 0;
unsigned long taggerdate = ULONG_MAX;
if (data->tags_only && !starts_with(path, "refs/tags/")) if (data->tags_only && !starts_with(path, "refs/tags/"))
return 0; return 0;
@ -164,12 +170,13 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
break; /* broken repository */ break; /* broken repository */
o = parse_object(t->tagged->oid.hash); o = parse_object(t->tagged->oid.hash);
deref = 1; deref = 1;
taggerdate = t->date;
} }
if (o && o->type == OBJ_COMMIT) { if (o && o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o; struct commit *commit = (struct commit *)o;
path = name_ref_abbrev(path, can_abbreviate_output); 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; return 0;
} }

Просмотреть файл

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