Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions commit-reach.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,6 @@ void ahead_behind(struct repository *r,

struct commit_and_index {
struct commit *commit;
unsigned int index;
timestamp_t generation;
};

Expand Down Expand Up @@ -1165,14 +1164,16 @@ void tips_reachable_from_bases(struct repository *r,

for (size_t i = 0; i < tips_nr; i++) {
commits[i].commit = tips[i];
commits[i].index = i;
commits[i].generation = commit_graph_generation(tips[i]);
}

/* Sort with generation number ascending. */
QSORT(commits, tips_nr, compare_commit_and_index_by_generation);
min_generation = commits[0].generation;

for (size_t i = 0; i < tips_nr; i++)
commits[i].commit->object.flags |= RESULT;

while (bases) {
repo_parse_commit(r, bases->item);
commit_list_insert(bases->item, &stack);
Expand All @@ -1183,20 +1184,16 @@ void tips_reachable_from_bases(struct repository *r,
int explored_all_parents = 1;
struct commit_list *p;
struct commit *c = stack->item;
timestamp_t c_gen = commit_graph_generation(c);

/* Does it match any of our tips? */
for (size_t j = min_generation_index; j < tips_nr; j++) {
if (c_gen < commits[j].generation)
break;

if (commits[j].commit == c) {
tips[commits[j].index]->object.flags |= mark;
{
if (c->object.flags & RESULT) {
c->object.flags |= mark;

if (j == min_generation_index) {
unsigned int k = j + 1;
if (commits[min_generation_index].commit->object.flags & mark) {
unsigned int k = min_generation_index + 1;
while (k < tips_nr &&
(tips[commits[k].index]->object.flags & mark))
(commits[k].commit->object.flags & mark))
k++;

/* Terminate early if all found. */
Expand Down Expand Up @@ -1232,6 +1229,8 @@ void tips_reachable_from_bases(struct repository *r,
}

done:
for (size_t i = 0; i < tips_nr; i++)
commits[i].commit->object.flags &= ~RESULT;
free(commits);
repo_clear_commit_marks(r, SEEN);
commit_list_free(stack);
Expand Down
45 changes: 45 additions & 0 deletions t/t6600-test-reach.sh
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,51 @@ test_expect_success 'for-each-ref merged:none' '
--format="%(refname)" --stdin
'

test_expect_success 'for-each-ref merged:duplicate, all reachable' '
git branch dup-a commit-3-3 &&
git branch dup-b commit-3-3 &&
cat >input <<-\EOF &&
refs/heads/commit-1-1
refs/heads/dup-a
refs/heads/dup-b
EOF
cat >expect <<-\EOF &&
refs/heads/commit-1-1
refs/heads/dup-a
refs/heads/dup-b
EOF
run_all_modes git for-each-ref --merged=commit-5-5 \
--format="%(refname)" --stdin
'

test_expect_success 'for-each-ref merged:duplicate, none reachable' '
cat >input <<-\EOF &&
refs/heads/dup-a
refs/heads/dup-b
refs/heads/commit-9-9
EOF
>expect &&
run_all_modes git for-each-ref --merged=commit-2-2 \
--format="%(refname)" --stdin
'

test_expect_success 'for-each-ref merged:duplicate at min generation' '
git branch dup-c commit-1-1 &&
git branch dup-d commit-1-1 &&
cat >input <<-\EOF &&
refs/heads/dup-c
refs/heads/dup-d
refs/heads/commit-5-5
EOF
cat >expect <<-\EOF &&
refs/heads/commit-5-5
refs/heads/dup-c
refs/heads/dup-d
EOF
run_all_modes git for-each-ref --merged=commit-5-5 \
--format="%(refname)" --stdin
'

# For get_branch_base_for_tip, we only care about
# first-parent history. Here is the test graph with
# second parents removed:
Expand Down
Loading