Skip to content

Commit b65c8e1

Browse files
authored
Do re-download corrupt objects with GVFS (#782)
As of 9e59b38, 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. This is even tested for in the functional tests of VFS for Git, which has been identified as a regression in microsoft/VFSForGit#1853.
2 parents 6e437e9 + db6f8f4 commit b65c8e1

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-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: 7 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"
@@ -707,6 +708,9 @@ int read_object_process(const struct object_id *oid)
707708
const char *cmd = find_hook(the_repository, "read-object");
708709
uint64_t start;
709710

711+
if (!cmd)
712+
die(_("could not find the `read-object` hook"));
713+
710714
start = getnanotime();
711715

712716
trace2_region_enter("subprocess", "read_object", the_repository);
@@ -1104,6 +1108,9 @@ void *repo_read_object_file(struct repository *r,
11041108
unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE;
11051109
void *data;
11061110

1111+
if (gvfs_config_is_set(GVFS_MISSING_OK))
1112+
flags &= ~OBJECT_INFO_DIE_IF_CORRUPT;
1113+
11071114
oi.typep = type;
11081115
oi.sizep = size;
11091116
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)