Merge branch 'jk/name-rev-w-genno'
"git name-rev" learned to use the generation numbers when setting the lower bound of searching commits used to explain the revision, when available, instead of committer time. * jk/name-rev-w-genno: name-rev: use generation numbers if available
This commit is contained in:
commit
94cb657f22
@ -9,6 +9,7 @@
|
||||
#include "prio-queue.h"
|
||||
#include "hash-lookup.h"
|
||||
#include "commit-slab.h"
|
||||
#include "commit-graph.h"
|
||||
|
||||
/*
|
||||
* One day. See the 'name a rev shortly after epoch' test in t6120 when
|
||||
@ -26,9 +27,58 @@ struct rev_name {
|
||||
|
||||
define_commit_slab(commit_rev_name, struct rev_name);
|
||||
|
||||
static timestamp_t generation_cutoff = GENERATION_NUMBER_INFINITY;
|
||||
static timestamp_t cutoff = TIME_MAX;
|
||||
static struct commit_rev_name rev_names;
|
||||
|
||||
/* Disable the cutoff checks entirely */
|
||||
static void disable_cutoff(void)
|
||||
{
|
||||
generation_cutoff = 0;
|
||||
cutoff = 0;
|
||||
}
|
||||
|
||||
/* Cutoff searching any commits older than this one */
|
||||
static void set_commit_cutoff(struct commit *commit)
|
||||
{
|
||||
|
||||
if (cutoff > commit->date)
|
||||
cutoff = commit->date;
|
||||
|
||||
if (generation_cutoff) {
|
||||
timestamp_t generation = commit_graph_generation(commit);
|
||||
|
||||
if (generation_cutoff > generation)
|
||||
generation_cutoff = generation;
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust the commit date cutoff with a slop to allow for slightly incorrect
|
||||
* commit timestamps in case of clock skew.
|
||||
*/
|
||||
static void adjust_cutoff_timestamp_for_slop(void)
|
||||
{
|
||||
if (cutoff) {
|
||||
/* check for undeflow */
|
||||
if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP)
|
||||
cutoff = cutoff - CUTOFF_DATE_SLOP;
|
||||
else
|
||||
cutoff = TIME_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if a commit is before the cutoff. Prioritize generation numbers
|
||||
* first, but use the commit timestamp if we lack generation data.
|
||||
*/
|
||||
static int commit_is_before_cutoff(struct commit *commit)
|
||||
{
|
||||
if (generation_cutoff < GENERATION_NUMBER_INFINITY)
|
||||
return generation_cutoff &&
|
||||
commit_graph_generation(commit) < generation_cutoff;
|
||||
|
||||
return commit->date < cutoff;
|
||||
}
|
||||
|
||||
/* How many generations are maximally preferred over _one_ merge traversal? */
|
||||
#define MERGE_TRAVERSAL_WEIGHT 65535
|
||||
|
||||
@ -151,7 +201,7 @@ static void name_rev(struct commit *start_commit,
|
||||
struct rev_name *start_name;
|
||||
|
||||
parse_commit(start_commit);
|
||||
if (start_commit->date < cutoff)
|
||||
if (commit_is_before_cutoff(start_commit))
|
||||
return;
|
||||
|
||||
start_name = create_or_update_name(start_commit, taggerdate, 0, 0,
|
||||
@ -181,7 +231,7 @@ static void name_rev(struct commit *start_commit,
|
||||
int generation, distance;
|
||||
|
||||
parse_commit(parent);
|
||||
if (parent->date < cutoff)
|
||||
if (commit_is_before_cutoff(parent))
|
||||
continue;
|
||||
|
||||
if (parent_number > 1) {
|
||||
@ -568,7 +618,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
||||
usage_with_options(name_rev_usage, opts);
|
||||
}
|
||||
if (all || annotate_stdin)
|
||||
cutoff = 0;
|
||||
disable_cutoff();
|
||||
|
||||
for (; argc; argc--, argv++) {
|
||||
struct object_id oid;
|
||||
@ -596,10 +646,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (commit) {
|
||||
if (cutoff > commit->date)
|
||||
cutoff = commit->date;
|
||||
}
|
||||
if (commit)
|
||||
set_commit_cutoff(commit);
|
||||
|
||||
if (peel_tag) {
|
||||
if (!commit) {
|
||||
@ -612,13 +660,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
||||
add_object_array(object, *argv, &revs);
|
||||
}
|
||||
|
||||
if (cutoff) {
|
||||
/* check for undeflow */
|
||||
if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP)
|
||||
cutoff = cutoff - CUTOFF_DATE_SLOP;
|
||||
else
|
||||
cutoff = TIME_MIN;
|
||||
}
|
||||
adjust_cutoff_timestamp_for_slop();
|
||||
|
||||
for_each_ref(name_ref, &data);
|
||||
name_tips();
|
||||
|
||||
|
@ -488,6 +488,124 @@ test_expect_success 'name-rev covers all conditions while looking at parents' '
|
||||
)
|
||||
'
|
||||
|
||||
# A-B-C-D-E-main
|
||||
#
|
||||
# Where C has a non-monotonically increasing commit timestamp w.r.t. other
|
||||
# commits
|
||||
test_expect_success 'non-monotonic commit dates setup' '
|
||||
UNIX_EPOCH_ZERO="@0 +0000" &&
|
||||
git init non-monotonic &&
|
||||
test_commit -C non-monotonic A &&
|
||||
test_commit -C non-monotonic --no-tag B &&
|
||||
test_commit -C non-monotonic --no-tag --date "$UNIX_EPOCH_ZERO" C &&
|
||||
test_commit -C non-monotonic D &&
|
||||
test_commit -C non-monotonic E
|
||||
'
|
||||
|
||||
test_expect_success 'name-rev with commitGraph handles non-monotonic timestamps' '
|
||||
test_config -C non-monotonic core.commitGraph true &&
|
||||
(
|
||||
cd non-monotonic &&
|
||||
|
||||
git commit-graph write --reachable &&
|
||||
|
||||
echo "main~3 tags/D~2" >expect &&
|
||||
git name-rev --tags main~3 >actual &&
|
||||
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'name-rev --all works with non-monotonic timestamps' '
|
||||
test_config -C non-monotonic core.commitGraph false &&
|
||||
(
|
||||
cd non-monotonic &&
|
||||
|
||||
rm -rf .git/info/commit-graph* &&
|
||||
|
||||
cat >tags <<-\EOF &&
|
||||
tags/E
|
||||
tags/D
|
||||
tags/D~1
|
||||
tags/D~2
|
||||
tags/A
|
||||
EOF
|
||||
|
||||
git log --pretty=%H >revs &&
|
||||
|
||||
paste -d" " revs tags | sort >expect &&
|
||||
|
||||
git name-rev --tags --all | sort >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'name-rev --annotate-stdin works with non-monotonic timestamps' '
|
||||
test_config -C non-monotonic core.commitGraph false &&
|
||||
(
|
||||
cd non-monotonic &&
|
||||
|
||||
rm -rf .git/info/commit-graph* &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
E
|
||||
D
|
||||
D~1
|
||||
D~2
|
||||
A
|
||||
EOF
|
||||
|
||||
git log --pretty=%H >revs &&
|
||||
git name-rev --tags --annotate-stdin --name-only <revs >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'name-rev --all works with commitGraph' '
|
||||
test_config -C non-monotonic core.commitGraph true &&
|
||||
(
|
||||
cd non-monotonic &&
|
||||
|
||||
git commit-graph write --reachable &&
|
||||
|
||||
cat >tags <<-\EOF &&
|
||||
tags/E
|
||||
tags/D
|
||||
tags/D~1
|
||||
tags/D~2
|
||||
tags/A
|
||||
EOF
|
||||
|
||||
git log --pretty=%H >revs &&
|
||||
|
||||
paste -d" " revs tags | sort >expect &&
|
||||
|
||||
git name-rev --tags --all | sort >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'name-rev --annotate-stdin works with commitGraph' '
|
||||
test_config -C non-monotonic core.commitGraph true &&
|
||||
(
|
||||
cd non-monotonic &&
|
||||
|
||||
git commit-graph write --reachable &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
E
|
||||
D
|
||||
D~1
|
||||
D~2
|
||||
A
|
||||
EOF
|
||||
|
||||
git log --pretty=%H >revs &&
|
||||
git name-rev --tags --annotate-stdin --name-only <revs >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
# B
|
||||
# o
|
||||
# \
|
||||
|
Loading…
Reference in New Issue
Block a user