Merge branch 'of/commit-reach-repo-awareness' into jch
The can_all_from_reach() and can_all_from_reach_with_flag() functions have been updated to accept a repository context, preventing bugs where submodule merging incorrectly reads from the superproject's commit-graph. * of/commit-reach-repo-awareness: commit-reach: parse commits in the given repositoryjch
commit
c698d4a539
|
|
@ -658,7 +658,7 @@ int repo_is_descendant_of(struct repository *r,
|
|||
struct commit_list *from_list = NULL;
|
||||
int result;
|
||||
commit_list_insert(commit, &from_list);
|
||||
result = can_all_from_reach(from_list, with_commit, 0);
|
||||
result = can_all_from_reach(r, from_list, with_commit, 0);
|
||||
commit_list_free(from_list);
|
||||
return result;
|
||||
} else {
|
||||
|
|
@ -952,7 +952,8 @@ int commit_contains(struct ref_filter *filter, struct commit *commit,
|
|||
return result;
|
||||
}
|
||||
|
||||
int can_all_from_reach_with_flag(struct object_array *from,
|
||||
int can_all_from_reach_with_flag(struct repository *r,
|
||||
struct object_array *from,
|
||||
unsigned int with_flag,
|
||||
unsigned int assign_flag,
|
||||
timestamp_t min_commit_date,
|
||||
|
|
@ -971,8 +972,7 @@ int can_all_from_reach_with_flag(struct object_array *from,
|
|||
if (!from_one || from_one->flags & assign_flag)
|
||||
continue;
|
||||
|
||||
from_one = deref_tag(the_repository, from_one,
|
||||
"a from object", 0);
|
||||
from_one = deref_tag(r, from_one, "a from object", 0);
|
||||
if (!from_one || from_one->type != OBJ_COMMIT) {
|
||||
/*
|
||||
* no way to tell if this is reachable by
|
||||
|
|
@ -985,7 +985,7 @@ int can_all_from_reach_with_flag(struct object_array *from,
|
|||
}
|
||||
|
||||
list[nr_commits] = (struct commit *)from_one;
|
||||
if (repo_parse_commit(the_repository, list[nr_commits]) ||
|
||||
if (repo_parse_commit(r, list[nr_commits]) ||
|
||||
commit_graph_generation(list[nr_commits]) < min_generation) {
|
||||
result = 0;
|
||||
goto cleanup;
|
||||
|
|
@ -1020,7 +1020,7 @@ int can_all_from_reach_with_flag(struct object_array *from,
|
|||
if (!(parent->item->object.flags & assign_flag)) {
|
||||
parent->item->object.flags |= assign_flag;
|
||||
|
||||
if (repo_parse_commit(the_repository, parent->item) ||
|
||||
if (repo_parse_commit(r, parent->item) ||
|
||||
parent->item->date < min_commit_date ||
|
||||
commit_graph_generation(parent->item) < min_generation)
|
||||
continue;
|
||||
|
|
@ -1054,8 +1054,8 @@ cleanup:
|
|||
return result;
|
||||
}
|
||||
|
||||
int can_all_from_reach(struct commit_list *from, struct commit_list *to,
|
||||
int cutoff_by_min_date)
|
||||
int can_all_from_reach(struct repository *r, struct commit_list *from,
|
||||
struct commit_list *to, int cutoff_by_min_date)
|
||||
{
|
||||
struct object_array from_objs = OBJECT_ARRAY_INIT;
|
||||
struct commit_list *from_iter = from, *to_iter = to;
|
||||
|
|
@ -1066,7 +1066,7 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to,
|
|||
while (from_iter) {
|
||||
add_object_array(&from_iter->item->object, NULL, &from_objs);
|
||||
|
||||
if (!repo_parse_commit(the_repository, from_iter->item)) {
|
||||
if (!repo_parse_commit(r, from_iter->item)) {
|
||||
timestamp_t generation;
|
||||
if (from_iter->item->date < min_commit_date)
|
||||
min_commit_date = from_iter->item->date;
|
||||
|
|
@ -1080,7 +1080,7 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to,
|
|||
}
|
||||
|
||||
while (to_iter) {
|
||||
if (!repo_parse_commit(the_repository, to_iter->item)) {
|
||||
if (!repo_parse_commit(r, to_iter->item)) {
|
||||
timestamp_t generation;
|
||||
if (to_iter->item->date < min_commit_date)
|
||||
min_commit_date = to_iter->item->date;
|
||||
|
|
@ -1095,7 +1095,7 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to,
|
|||
to_iter = to_iter->next;
|
||||
}
|
||||
|
||||
result = can_all_from_reach_with_flag(&from_objs, PARENT2, PARENT1,
|
||||
result = can_all_from_reach_with_flag(r, &from_objs, PARENT2, PARENT1,
|
||||
min_commit_date, min_generation);
|
||||
|
||||
while (from) {
|
||||
|
|
|
|||
|
|
@ -89,13 +89,14 @@ int commit_contains(struct ref_filter *filter, struct commit *commit,
|
|||
* commits with date below 'min_commit_date' or generation below
|
||||
* 'min_generation'.
|
||||
*/
|
||||
int can_all_from_reach_with_flag(struct object_array *from,
|
||||
int can_all_from_reach_with_flag(struct repository *r,
|
||||
struct object_array *from,
|
||||
unsigned int with_flag,
|
||||
unsigned int assign_flag,
|
||||
timestamp_t min_commit_date,
|
||||
timestamp_t min_generation);
|
||||
int can_all_from_reach(struct commit_list *from, struct commit_list *to,
|
||||
int commit_date_cutoff);
|
||||
int can_all_from_reach(struct repository *r, struct commit_list *from,
|
||||
struct commit_list *to, int commit_date_cutoff);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2311,8 +2311,8 @@ void negotiate_using_fetch(const struct oid_array *negotiation_restrict_tips,
|
|||
die(_("unexpected 'ready' from remote"));
|
||||
else
|
||||
do_check_stateless_delimiter(stateless_rpc, &reader);
|
||||
if (can_all_from_reach_with_flag(&nt_object_array, COMMON,
|
||||
REACH_SCRATCH, 0,
|
||||
if (can_all_from_reach_with_flag(the_repository, &nt_object_array,
|
||||
COMMON, REACH_SCRATCH, 0,
|
||||
min_generation))
|
||||
last_iteration = 1;
|
||||
trace2_region_leave_printf("negotiation", "round",
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ int cmd__reach(int ac, const char **av)
|
|||
print_sorted_commit_ids(list);
|
||||
commit_list_free(list);
|
||||
} else if (!strcmp(av[1], "can_all_from_reach")) {
|
||||
printf("%s(X,Y):%d\n", av[1], can_all_from_reach(X, Y, 1));
|
||||
printf("%s(X,Y):%d\n", av[1], can_all_from_reach(r, X, Y, 1));
|
||||
} else if (!strcmp(av[1], "can_all_from_reach_with_flag")) {
|
||||
struct commit_list *iter = Y;
|
||||
|
||||
|
|
@ -136,7 +136,8 @@ int cmd__reach(int ac, const char **av)
|
|||
iter = iter->next;
|
||||
}
|
||||
|
||||
printf("%s(X,_,_,0,0):%d\n", av[1], can_all_from_reach_with_flag(&X_obj, 2, 4, 0, 0));
|
||||
printf("%s(X,_,_,0,0):%d\n", av[1],
|
||||
can_all_from_reach_with_flag(r, &X_obj, 2, 4, 0, 0));
|
||||
} else if (!strcmp(av[1], "commit_contains")) {
|
||||
struct ref_filter filter = REF_FILTER_INIT;
|
||||
struct contains_cache cache;
|
||||
|
|
|
|||
|
|
@ -514,4 +514,43 @@ test_expect_success 'merging should fail with no merge base' '
|
|||
)
|
||||
'
|
||||
|
||||
test_expect_success 'setup for commit-graphs in superproject and submodule' '
|
||||
git init commit-graph &&
|
||||
(cd commit-graph &&
|
||||
git init sub &&
|
||||
for i in 1 2 3 4 5 6 7 8 9 10
|
||||
do
|
||||
test_commit -C sub "sub-$i" || return 1
|
||||
done &&
|
||||
|
||||
git -C sub checkout --detach sub-1 &&
|
||||
git add sub &&
|
||||
git commit -m base &&
|
||||
|
||||
# Write the commit-graph of the superproject while it only
|
||||
# contains a single commit. Any commit-graph position of the
|
||||
# submodule is thus out of bounds for the superproject.
|
||||
git commit-graph write --reachable &&
|
||||
|
||||
git checkout -b side &&
|
||||
git -C sub checkout --detach sub-5 &&
|
||||
git add sub &&
|
||||
git commit -m side &&
|
||||
|
||||
git checkout main &&
|
||||
git -C sub checkout --detach sub-10 &&
|
||||
git add sub &&
|
||||
git commit -m main &&
|
||||
|
||||
git -C sub commit-graph write --reachable)
|
||||
'
|
||||
|
||||
test_expect_success 'merge does not mix up superproject and submodule commit-graphs' '
|
||||
(cd commit-graph &&
|
||||
git merge side &&
|
||||
git rev-parse HEAD:sub >actual &&
|
||||
git -C sub rev-parse sub-10^{commit} >expect &&
|
||||
test_cmp expect actual)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
|||
|
|
@ -530,9 +530,9 @@ static int ok_to_give_up(struct upload_pack_data *data)
|
|||
if (!data->have_obj.nr)
|
||||
return 0;
|
||||
|
||||
return can_all_from_reach_with_flag(&data->want_obj, THEY_HAVE,
|
||||
COMMON_KNOWN, data->oldest_have,
|
||||
min_generation);
|
||||
return can_all_from_reach_with_flag(the_repository, &data->want_obj,
|
||||
THEY_HAVE, COMMON_KNOWN,
|
||||
data->oldest_have, min_generation);
|
||||
}
|
||||
|
||||
static int get_common_commits(struct upload_pack_data *data,
|
||||
|
|
|
|||
Loading…
Reference in New Issue