Skip to content

Commit

Permalink
pull: Fix local pull with depth and truncated source history
Browse files Browse the repository at this point in the history
The local pull path was erroring on any missing commit, but that
prevents a depth pull where the source repo has truncated history. As in
the remote case, this also tries to pull in a tombstone commit if the
source repo supports it.

Fixes: #2266
  • Loading branch information
dbnicholson committed Jan 12, 2021
1 parent 20047ff commit d7f2955
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 5 deletions.
46 changes: 42 additions & 4 deletions src/libostree/ostree-repo-pull.c
Original file line number Diff line number Diff line change
Expand Up @@ -1167,8 +1167,10 @@ meta_fetch_on_complete (GObject *object,
}

/* When traversing parents, do not fail on a missing commit.
* We may be pulling from a partial repository that ends in
* a dangling parent reference. */
* We may be pulling from a partial repository that ends in a
* dangling parent reference. This logic should match the
* local case in scan_one_metadata_object.
*/
else if (objtype == OSTREE_OBJECT_TYPE_COMMIT &&
pull_data->maxdepth != 0 &&
is_parent_commit (pull_data, checksum))
Expand Down Expand Up @@ -1820,10 +1822,46 @@ scan_one_metadata_object (OtPullData *pull_data,
return FALSE;
}

g_autoptr(GError) local_error = NULL;
if (!_ostree_repo_import_object (pull_data->repo, pull_data->remote_repo_local,
objtype, checksum, pull_data->importflags,
cancellable, error))
return FALSE;
cancellable, &local_error))
{
/* When traversing parents, do not fail on a missing commit.
* We may be pulling from a partial repository that ends in a
* dangling parent reference. This logic should match the
* remote case in meta_fetch_on_complete.
*
* Note early return.
*/
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
objtype == OSTREE_OBJECT_TYPE_COMMIT &&
pull_data->maxdepth != 0 &&
is_parent_commit (pull_data, checksum))
{
g_clear_error (&local_error);

/* If the remote repo supports tombstone commits, check if
* the commit was intentionally deleted.
*/
if (pull_data->has_tombstone_commits)
{
if (!_ostree_repo_import_object (pull_data->repo, pull_data->remote_repo_local,
OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT,
checksum, pull_data->importflags,
cancellable, error))
return FALSE;
}

return TRUE;
}
else
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
}

/* The import API will fetch both the commit and detached metadata, so
* add it to the hash to avoid re-fetching it below.
*/
Expand Down
34 changes: 33 additions & 1 deletion tests/test-local-pull-depth.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ set -euo pipefail

setup_test_repository "archive"

echo "1..1"
echo "1..3"

cd ${test_tmpdir}
mkdir repo2
Expand Down Expand Up @@ -62,3 +62,35 @@ find repo2/state -name '*.commitpartial' | wc -l > commitpartialcount
assert_file_has_content commitpartialcount "^0$"

echo "ok local pull depth"

# Check that pulling with depth != 0 succeeds with a missing parent
# commit. Prune the remote to truncate the history.
cd ${test_tmpdir}
${CMD_PREFIX} ostree --repo=repo prune --refs-only --depth=0

rm -rf repo2/refs/heads/* repo2/refs/remotes/* repo2/objects/*/*.commit
${CMD_PREFIX} ostree --repo=repo2 pull-local --depth=1 repo
find repo/objects -name '*.commit' | wc -l > commitcount
assert_file_has_content commitcount "^1$"
find repo/state -name '*.commitpartial' | wc -l > commitpartialcount
assert_file_has_content commitpartialcount "^0$"

rm -rf repo2/refs/heads/* repo2/refs/remotes/* repo2/objects/*/*.commit
${CMD_PREFIX} ostree --repo=repo2 pull-local --depth=-1 repo
find repo/objects -name '*.commit' | wc -l > commitcount
assert_file_has_content commitcount "^1$"
find repo/state -name '*.commitpartial' | wc -l > commitpartialcount
assert_file_has_content commitpartialcount "^0$"

echo "ok local pull depth missing parent"

# Check that it errors if the ref head commit is missing.
cd ${test_tmpdir}
rm -f repo/objects/*/*.commit

rm -rf repo2/refs/heads/* repo2/refs/remotes/* repo2/objects/*/*.commit
if ${CMD_PREFIX} ostree --repo=repo2 pull-local --depth=-1 repo; then
fatal "Local pull with depth -1 succeeded with missing HEAD commit"
fi

echo "ok local pull depth missing HEAD commit"

0 comments on commit d7f2955

Please sign in to comment.