Skip to content

Commit

Permalink
sha1_file: when writing objects, skip the read_object_hook
Browse files Browse the repository at this point in the history
If we are going to write an object there is no use in calling
the read object hook to get an object from a potentially remote
source.  We would rather just write out the object and avoid the
potential round trip for an object that doesn't exist.

This change adds a flag to the check_and_freshen() and
freshen_loose_object() functions' signatures so that the hook
is bypassed when the functions are called before writing loose
objects. The check for a local object is still performed so we
don't overwrite something that has already been written to one
of the objects directories.

Based on a patch by Kevin Willford.
  • Loading branch information
dscho committed Oct 23, 2017
1 parent 208e885 commit 26e4198
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
17 changes: 10 additions & 7 deletions sha1_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -801,15 +801,17 @@ static int check_and_freshen_nonlocal(const unsigned char *sha1, int freshen)
return 0;
}

static int check_and_freshen(const unsigned char *sha1, int freshen)
static int check_and_freshen(const unsigned char *sha1, int freshen,
int skip_virtualized_objects)
{
int ret;
int tried_hook = 0;

retry:
ret = check_and_freshen_local(sha1, freshen) ||
check_and_freshen_nonlocal(sha1, freshen);
if (!ret && core_virtualize_objects && !tried_hook) {
if (!ret && core_virtualize_objects && !skip_virtualized_objects &&
!tried_hook) {
tried_hook = 1;
if (!read_object_process(sha1))
goto retry;
Expand All @@ -825,7 +827,7 @@ int has_loose_object_nonlocal(const unsigned char *sha1)

static int has_loose_object(const unsigned char *sha1)
{
return check_and_freshen(sha1, 0);
return check_and_freshen(sha1, 0, 0);
}

static unsigned int pack_used_ctr;
Expand Down Expand Up @@ -3537,9 +3539,10 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
return finalize_object_file(tmp_file.buf, filename);
}

static int freshen_loose_object(const unsigned char *sha1)
static int freshen_loose_object(const unsigned char *sha1,
int skip_virtualized_objects)
{
return check_and_freshen(sha1, 1);
return check_and_freshen(sha1, 1, skip_virtualized_objects);
}

static int freshen_packed_object(const unsigned char *sha1)
Expand All @@ -3564,7 +3567,7 @@ int write_sha1_file(const void *buf, unsigned long len, const char *type, unsign
* it out into .git/objects/??/?{38} file.
*/
write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen);
if (freshen_packed_object(sha1) || freshen_loose_object(sha1))
if (freshen_packed_object(sha1) || freshen_loose_object(sha1, 1))
return 0;
return write_loose_object(sha1, hdr, hdrlen, buf, len, 0);
}
Expand All @@ -3582,7 +3585,7 @@ int hash_sha1_file_literally(const void *buf, unsigned long len, const char *typ

if (!(flags & HASH_WRITE_OBJECT))
goto cleanup;
if (freshen_packed_object(sha1) || freshen_loose_object(sha1))
if (freshen_packed_object(sha1) || freshen_loose_object(sha1, 1))
goto cleanup;
status = write_loose_object(sha1, header, hdrlen, buf, len, 0);

Expand Down
7 changes: 7 additions & 0 deletions t/t0410-read-object.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,12 @@ test_expect_success 'invalid blobs generate errors' '
test_must_fail git cat-file blob "invalid")
'

test_expect_success 'read-object-hook is bypassed when writing objects' '
(cd guest-repo &&
echo hello >hello.txt &&
git add hello.txt &&
hash="$(git rev-parse --verify :hello.txt)" &&
! grep "$hash" .git/read-object-hook.log)
'

test_done
4 changes: 4 additions & 0 deletions t/t0410/read-object
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ while (1) {
system ('git --git-dir="' . $DIR . '" cat-file blob ' . $sha1 . ' | git -c core.virtualizeobjects=false hash-object -w --stdin >/dev/null 2>&1');
packet_txt_write(($?) ? "status=error" : "status=success");
packet_flush();

open my $log, '>>.git/read-object-hook.log';
print $log "Read object $sha1, exit code $?\n";
close $log;
} else {
die "bad command '$command'";
}
Expand Down

0 comments on commit 26e4198

Please sign in to comment.