Skip to content

Commit db6f8f4

Browse files
committed
gvfs: allow corrupt objects to be re-downloaded
As of 9e59b38 (object-file: emit corruption errors when detected, 2022-12-14), Git will loudly complain about corrupt objects. That is fine, as long as the idea isn't to re-download locally-corrupted objects. But that's exactly what we want to do in VFS for Git via the `read-object` hook, as per the `GitCorruptObjectTests` code added in microsoft/VFSForGit@2db0c030eb25 (New features: [...] - GVFS can now recover from corrupted git object files [...] , 2018-02-16). So let's support precisely that, and add a regression test that ensures that re-downloading corrupt objects via the `read-object` hook works. While at it, avoid the XOR operator to flip the bits, when we actually want to make sure that they are turned off: Use the AND-NOT operator for that purpose. Helped-by: Matthew John Cheetham <mjcheetham@outlook.com> Helped-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 413202c commit db6f8f4

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

commit.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,9 +566,14 @@ int repo_parse_commit_internal(struct repository *r,
566566
int flags = OBJECT_INFO_LOOKUP_REPLACE | OBJECT_INFO_SKIP_FETCH_OBJECT |
567567
OBJECT_INFO_DIE_IF_CORRUPT;
568568

569-
/* But the GVFS Protocol _does_ support missing commits! */
569+
/*
570+
* But the GVFS Protocol _does_ support missing commits!
571+
* And the idea with VFS for Git is to re-download corrupted objects,
572+
* not to fail!
573+
*/
570574
if (gvfs_config_is_set(GVFS_MISSING_OK))
571-
flags ^= OBJECT_INFO_SKIP_FETCH_OBJECT;
575+
flags &= ~(OBJECT_INFO_SKIP_FETCH_OBJECT |
576+
OBJECT_INFO_DIE_IF_CORRUPT);
572577

573578
if (!item)
574579
return -1;

object-store.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "dir.h"
88
#include "environment.h"
99
#include "gettext.h"
10+
#include "gvfs.h"
1011
#include "gvfs-helper-client.h"
1112
#include "hex.h"
1213
#include "hook.h"
@@ -1107,6 +1108,9 @@ void *repo_read_object_file(struct repository *r,
11071108
unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE;
11081109
void *data;
11091110

1111+
if (gvfs_config_is_set(GVFS_MISSING_OK))
1112+
flags &= ~OBJECT_INFO_DIE_IF_CORRUPT;
1113+
11101114
oi.typep = type;
11111115
oi.sizep = size;
11121116
oi.contentp = &data;

t/t1060-object-corruption.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
test_description='see how we handle various forms of corruption'
44

55
. ./test-lib.sh
6+
. "$TEST_DIRECTORY"/lib-diff-data.sh
67

78
# convert "1234abcd" to ".git/objects/12/34abcd"
89
obj_to_file() {
@@ -62,6 +63,35 @@ test_expect_success 'streaming a corrupt blob fails' '
6263
)
6364
'
6465

66+
test_expect_success PERL 'truncated objects can be re-retrieved via GVFS' '
67+
git init truncated &&
68+
COPYING_test_data >truncated/COPYING &&
69+
git -C truncated add COPYING &&
70+
test_tick &&
71+
git -C truncated commit -m initial COPYING &&
72+
73+
# set up the `read-object` hook so that it overwrites the corrupt object
74+
mkdir -p truncated/.git/hooks &&
75+
sed -e "1s|/usr/bin/perl|$PERL_PATH|" \
76+
-e "s/system/unlink \".git\/objects\/\" . substr(\$sha1, 0, 2) . \"\/\" . substr(\$sha1, 2); &/" \
77+
<$TEST_DIRECTORY/t0410/read-object \
78+
>truncated/.git/hooks/read-object &&
79+
chmod +x truncated/.git/hooks/read-object &&
80+
81+
# ensure that the parent repository has a copy of the object, from
82+
# where the `read-object` can read it
83+
sha="$(git hash-object -w truncated/COPYING)" &&
84+
file=$(obj_to_file $sha) &&
85+
size=$(test_file_size $file) &&
86+
chmod u+w truncated/$file &&
87+
test-tool truncate truncated/$file $(($size-8)) &&
88+
89+
rm truncated/COPYING &&
90+
test_must_fail git -C truncated reset --hard &&
91+
git -C truncated -c core.gvfs=4 -c core.virtualizeObjects \
92+
reset --hard
93+
'
94+
6595
test_expect_success 'getting type of a corrupt blob fails' '
6696
(
6797
cd bit-error &&

0 commit comments

Comments
 (0)