Skip to content

Commit d22b229

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 <[email protected]> Helped-by: Derrick Stolee <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 3745eb0 commit d22b229

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

commit.c

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

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

574579
if (!item)
575580
return -1;

odb.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,9 @@ void *odb_read_object(struct object_database *odb,
11401140
unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE;
11411141
void *data;
11421142

1143+
if (gvfs_config_is_set(odb->repo, GVFS_MISSING_OK))
1144+
flags &= ~OBJECT_INFO_DIE_IF_CORRUPT;
1145+
11431146
oi.typep = type;
11441147
oi.sizep = size;
11451148
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)