diff --git a/commit.c b/commit.c index 8209d5303d427e..94f8f6e0d600ef 100644 --- a/commit.c +++ b/commit.c @@ -566,9 +566,14 @@ int repo_parse_commit_internal(struct repository *r, int flags = OBJECT_INFO_LOOKUP_REPLACE | OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_DIE_IF_CORRUPT; - /* But the GVFS Protocol _does_ support missing commits! */ + /* + * But the GVFS Protocol _does_ support missing commits! + * And the idea with VFS for Git is to re-download corrupted objects, + * not to fail! + */ if (gvfs_config_is_set(GVFS_MISSING_OK)) - flags ^= OBJECT_INFO_SKIP_FETCH_OBJECT; + flags &= ~(OBJECT_INFO_SKIP_FETCH_OBJECT | + OBJECT_INFO_DIE_IF_CORRUPT); if (!item) return -1; diff --git a/object-store.c b/object-store.c index 188768864c06b4..3cee72452deaf7 100644 --- a/object-store.c +++ b/object-store.c @@ -7,6 +7,7 @@ #include "dir.h" #include "environment.h" #include "gettext.h" +#include "gvfs.h" #include "gvfs-helper-client.h" #include "hex.h" #include "hook.h" @@ -707,6 +708,9 @@ int read_object_process(const struct object_id *oid) const char *cmd = find_hook(the_repository, "read-object"); uint64_t start; + if (!cmd) + die(_("could not find the `read-object` hook")); + start = getnanotime(); trace2_region_enter("subprocess", "read_object", the_repository); @@ -1104,6 +1108,9 @@ void *repo_read_object_file(struct repository *r, unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE; void *data; + if (gvfs_config_is_set(GVFS_MISSING_OK)) + flags &= ~OBJECT_INFO_DIE_IF_CORRUPT; + oi.typep = type; oi.sizep = size; oi.contentp = &data; diff --git a/t/t1060-object-corruption.sh b/t/t1060-object-corruption.sh index 502a5ea1c51e3a..4f1f593c7410bd 100755 --- a/t/t1060-object-corruption.sh +++ b/t/t1060-object-corruption.sh @@ -3,6 +3,7 @@ test_description='see how we handle various forms of corruption' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-diff-data.sh # convert "1234abcd" to ".git/objects/12/34abcd" obj_to_file() { @@ -62,6 +63,35 @@ test_expect_success 'streaming a corrupt blob fails' ' ) ' +test_expect_success PERL 'truncated objects can be re-retrieved via GVFS' ' + git init truncated && + COPYING_test_data >truncated/COPYING && + git -C truncated add COPYING && + test_tick && + git -C truncated commit -m initial COPYING && + + # set up the `read-object` hook so that it overwrites the corrupt object + mkdir -p truncated/.git/hooks && + sed -e "1s|/usr/bin/perl|$PERL_PATH|" \ + -e "s/system/unlink \".git\/objects\/\" . substr(\$sha1, 0, 2) . \"\/\" . substr(\$sha1, 2); &/" \ + <$TEST_DIRECTORY/t0410/read-object \ + >truncated/.git/hooks/read-object && + chmod +x truncated/.git/hooks/read-object && + + # ensure that the parent repository has a copy of the object, from + # where the `read-object` can read it + sha="$(git hash-object -w truncated/COPYING)" && + file=$(obj_to_file $sha) && + size=$(test_file_size $file) && + chmod u+w truncated/$file && + test-tool truncate truncated/$file $(($size-8)) && + + rm truncated/COPYING && + test_must_fail git -C truncated reset --hard && + git -C truncated -c core.gvfs=4 -c core.virtualizeObjects \ + reset --hard +' + test_expect_success 'getting type of a corrupt blob fails' ' ( cd bit-error &&