mirror of
https://github.com/git/git.git
synced 2026-02-26 01:43:43 +00:00
Merge branch 'sp/shallow-deepen-relative-fix' into jch
"git fetch --deepen" that tries to go beyond merged branch used to get confused where the updated shallow points are, which has been corrected. * sp/shallow-deepen-relative-fix: shallow: handling fetch relative-deepen shallow: free local object_array allocations
This commit is contained in:
73
shallow.c
73
shallow.c
@@ -130,11 +130,24 @@ static void free_depth_in_slab(int **ptr)
|
||||
{
|
||||
FREE_AND_NULL(*ptr);
|
||||
}
|
||||
struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
|
||||
int shallow_flag, int not_shallow_flag)
|
||||
/*
|
||||
* This is a common internal function that can either return a list of
|
||||
* shallow commits or calculate the current maximum depth of a shallow
|
||||
* repository, depending on the input parameters.
|
||||
*
|
||||
* Depth calculation is triggered by passing the `shallows` parameter.
|
||||
* In this case, the computed depth is stored in `max_cur_depth` (if it is
|
||||
* provided), and the function returns NULL.
|
||||
*
|
||||
* Otherwise, `max_cur_depth` remains unchanged and the function returns
|
||||
* a list of shallow commits.
|
||||
*/
|
||||
static struct commit_list *get_shallows_or_depth(struct object_array *heads,
|
||||
struct object_array *shallows, int *max_cur_depth,
|
||||
int depth, int shallow_flag, int not_shallow_flag)
|
||||
{
|
||||
size_t i = 0;
|
||||
int cur_depth = 0;
|
||||
int cur_depth = 0, cur_depth_shallow = 0;
|
||||
struct commit_list *result = NULL;
|
||||
struct object_array stack = OBJECT_ARRAY_INIT;
|
||||
struct commit *commit = NULL;
|
||||
@@ -168,16 +181,30 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
|
||||
}
|
||||
parse_commit_or_die(commit);
|
||||
cur_depth++;
|
||||
if ((depth != INFINITE_DEPTH && cur_depth >= depth) ||
|
||||
(is_repository_shallow(the_repository) && !commit->parents &&
|
||||
(graft = lookup_commit_graft(the_repository, &commit->object.oid)) != NULL &&
|
||||
graft->nr_parent < 0)) {
|
||||
commit_list_insert(commit, &result);
|
||||
commit->object.flags |= shallow_flag;
|
||||
commit = NULL;
|
||||
continue;
|
||||
if (shallows) {
|
||||
for (size_t j = 0; j < shallows->nr; j++)
|
||||
if (oideq(&commit->object.oid, &shallows->objects[j].item->oid))
|
||||
if (!cur_depth_shallow || cur_depth < cur_depth_shallow)
|
||||
cur_depth_shallow = cur_depth;
|
||||
|
||||
if ((is_repository_shallow(the_repository) && !commit->parents &&
|
||||
(graft = lookup_commit_graft(the_repository, &commit->object.oid)) != NULL &&
|
||||
graft->nr_parent < 0)) {
|
||||
commit = NULL;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if ((depth != INFINITE_DEPTH && cur_depth >= depth) ||
|
||||
(is_repository_shallow(the_repository) && !commit->parents &&
|
||||
(graft = lookup_commit_graft(the_repository, &commit->object.oid)) != NULL &&
|
||||
graft->nr_parent < 0)) {
|
||||
commit_list_insert(commit, &result);
|
||||
commit->object.flags |= shallow_flag;
|
||||
commit = NULL;
|
||||
continue;
|
||||
}
|
||||
commit->object.flags |= not_shallow_flag;
|
||||
}
|
||||
commit->object.flags |= not_shallow_flag;
|
||||
for (p = commit->parents, commit = NULL; p; p = p->next) {
|
||||
int **depth_slot = commit_depth_at(&depths, p->item);
|
||||
if (!*depth_slot) {
|
||||
@@ -198,10 +225,32 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
|
||||
}
|
||||
}
|
||||
deep_clear_commit_depth(&depths, free_depth_in_slab);
|
||||
object_array_clear(&stack);
|
||||
|
||||
if (shallows && max_cur_depth)
|
||||
*max_cur_depth = cur_depth_shallow;
|
||||
return result;
|
||||
}
|
||||
|
||||
int get_shallows_depth(struct object_array *heads, struct object_array *shallows)
|
||||
{
|
||||
int max_cur_depth = 0;
|
||||
get_shallows_or_depth(heads, shallows, &max_cur_depth, 0, 0, 0);
|
||||
return max_cur_depth;
|
||||
|
||||
}
|
||||
|
||||
struct commit_list *get_shallow_commits(struct object_array *heads,
|
||||
struct object_array *shallows, int deepen_relative,
|
||||
int depth, int shallow_flag, int not_shallow_flag)
|
||||
{
|
||||
if (shallows && deepen_relative) {
|
||||
depth += get_shallows_depth(heads, shallows);
|
||||
}
|
||||
return get_shallows_or_depth(heads, NULL, NULL,
|
||||
depth, shallow_flag, not_shallow_flag);
|
||||
}
|
||||
|
||||
static void show_commit(struct commit *commit, void *data)
|
||||
{
|
||||
commit_list_insert(commit, data);
|
||||
|
||||
@@ -36,7 +36,9 @@ int commit_shallow_file(struct repository *r, struct shallow_lock *lk);
|
||||
/* rollback $GIT_DIR/shallow and reset stat-validity checks */
|
||||
void rollback_shallow_file(struct repository *r, struct shallow_lock *lk);
|
||||
|
||||
int get_shallows_depth(struct object_array *heads, struct object_array *shallows);
|
||||
struct commit_list *get_shallow_commits(struct object_array *heads,
|
||||
struct object_array *shallows, int deepen_relative,
|
||||
int depth, int shallow_flag, int not_shallow_flag);
|
||||
struct commit_list *get_shallow_commits_by_rev_list(struct strvec *argv,
|
||||
int shallow_flag, int not_shallow_flag);
|
||||
|
||||
@@ -960,6 +960,29 @@ test_expect_success 'fetching deepen' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'fetching deepen beyond merged branch' '
|
||||
test_create_repo shallow-deepen-merged &&
|
||||
(
|
||||
cd shallow-deepen-merged &&
|
||||
git commit --allow-empty -m one &&
|
||||
git commit --allow-empty -m two &&
|
||||
git commit --allow-empty -m three &&
|
||||
git switch -c branch &&
|
||||
git commit --allow-empty -m four &&
|
||||
git commit --allow-empty -m five &&
|
||||
git switch main &&
|
||||
git merge --no-ff branch &&
|
||||
cd - &&
|
||||
git clone --bare --depth 3 "file://$(pwd)/shallow-deepen-merged" deepen.git &&
|
||||
git -C deepen.git fetch origin --deepen=1 &&
|
||||
git -C deepen.git rev-list --all >actual &&
|
||||
for commit in $(sed "/^$/d" deepen.git/shallow)
|
||||
do
|
||||
test_grep "$commit" actual || exit 1
|
||||
done
|
||||
)
|
||||
'
|
||||
|
||||
test_negotiation_algorithm_default () {
|
||||
test_when_finished rm -rf clientv0 clientv2 &&
|
||||
rm -rf server client &&
|
||||
|
||||
@@ -704,56 +704,6 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int get_reachable_list(struct upload_pack_data *data,
|
||||
struct object_array *reachable)
|
||||
{
|
||||
struct child_process cmd = CHILD_PROCESS_INIT;
|
||||
int i;
|
||||
struct object *o;
|
||||
char namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + hash + LF */
|
||||
const unsigned hexsz = the_hash_algo->hexsz;
|
||||
int ret;
|
||||
|
||||
if (do_reachable_revlist(&cmd, &data->shallows, reachable,
|
||||
data->allow_uor) < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) {
|
||||
struct object_id oid;
|
||||
const char *p;
|
||||
|
||||
if (parse_oid_hex(namebuf, &oid, &p) || *p != '\n')
|
||||
break;
|
||||
|
||||
o = lookup_object(the_repository, &oid);
|
||||
if (o && o->type == OBJ_COMMIT) {
|
||||
o->flags &= ~TMP_MARK;
|
||||
}
|
||||
}
|
||||
for (i = get_max_object_index(the_repository); 0 < i; i--) {
|
||||
o = get_indexed_object(the_repository, i - 1);
|
||||
if (o && o->type == OBJ_COMMIT &&
|
||||
(o->flags & TMP_MARK)) {
|
||||
add_object_array(o, NULL, reachable);
|
||||
o->flags &= ~TMP_MARK;
|
||||
}
|
||||
}
|
||||
close(cmd.out);
|
||||
|
||||
if (finish_command(&cmd)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
child_process_clear(&cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int has_unreachable(struct object_array *src, enum allow_uor allow_uor)
|
||||
{
|
||||
struct child_process cmd = CHILD_PROCESS_INIT;
|
||||
@@ -881,29 +831,11 @@ static void deepen(struct upload_pack_data *data, int depth)
|
||||
struct object *object = data->shallows.objects[i].item;
|
||||
object->flags |= NOT_SHALLOW;
|
||||
}
|
||||
} else if (data->deepen_relative) {
|
||||
struct object_array reachable_shallows = OBJECT_ARRAY_INIT;
|
||||
struct commit_list *result;
|
||||
|
||||
/*
|
||||
* Checking for reachable shallows requires that our refs be
|
||||
* marked with OUR_REF.
|
||||
*/
|
||||
refs_head_ref_namespaced(get_main_ref_store(the_repository),
|
||||
check_ref, data);
|
||||
for_each_namespaced_ref_1(check_ref, data);
|
||||
|
||||
get_reachable_list(data, &reachable_shallows);
|
||||
result = get_shallow_commits(&reachable_shallows,
|
||||
depth + 1,
|
||||
SHALLOW, NOT_SHALLOW);
|
||||
send_shallow(data, result);
|
||||
free_commit_list(result);
|
||||
object_array_clear(&reachable_shallows);
|
||||
} else {
|
||||
struct commit_list *result;
|
||||
|
||||
result = get_shallow_commits(&data->want_obj, depth,
|
||||
result = get_shallow_commits(&data->want_obj, &data->shallows,
|
||||
data->deepen_relative, depth,
|
||||
SHALLOW, NOT_SHALLOW);
|
||||
send_shallow(data, result);
|
||||
free_commit_list(result);
|
||||
|
||||
Reference in New Issue
Block a user