pull: Error on depth pull with missing head commit

When pulling with depth, missing parent commits are ignored. However,
the check was applying to any commit, which means that it would succeed
even if the requested commit was missing. This might happen on a
corrupted remote repo or when using ref data from a stale summary.

To achieve this, the semantics of the `commit_to_depth` hash table is
changed slightly to only ever includes parent commits. This makes it
easy to detect when a parent commit is being referenced (although there
is a minor bug there when multiple refs are being pulled) while keeping
references to commits that need their `commitpartial` files cleaned up.
It also means that the table is only populated on depth pulls, which
saves some memory and processing in the common depth=0 case.

Fixes: #2265
This commit is contained in:
Dan Nicholson committed 2021-01-12 14:19:01 -07:00
1 parent b4f06b47a3
commit 20047ff1fe
3 files changed
+57 -35

No files matched your search

+33 -1
View File
@@ -25,7 +25,7 @@ set -euo pipefail
setup_fake_remote_repo1 "archive"
echo '1..1'
echo '1..3'
cd ${test_tmpdir}
mkdir repo
@@ -63,3 +63,35 @@ find repo/state -name '*.commitpartial' | wc -l > commitpartialcount
assert_file_has_content commitpartialcount "^0$"
echo "ok 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=ostree-srv/gnomerepo prune --refs-only --depth=0
rm -rf repo/refs/heads/* repo/refs/remotes/* repo/objects/*/*.commit
${CMD_PREFIX} ostree --repo=repo pull --depth=1 origin main
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 repo/refs/heads/* repo/refs/remotes/* repo/objects/*/*.commit
${CMD_PREFIX} ostree --repo=repo pull --depth=-1 origin main
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 pull depth missing parent"
# Check that it errors if the ref head commit is missing.
cd ${test_tmpdir}
rm -f ostree-srv/gnomerepo/objects/*/*.commit
rm -rf repo/refs/heads/* repo/refs/remotes/* repo/objects/*/*.commit
if ${CMD_PREFIX} ostree --repo=repo pull --depth=-1 origin main; then
fatal "Pull with depth -1 succeeded with missing HEAD commit"
fi
echo "ok pull depth missing HEAD commit"