sha1_file: when writing objects, skip the read_object_hook

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.

Signed-off-by: Johannes Schindelin <johasc@microsoft.com>
This commit is contained in:
Johannes Schindelin 2017-09-08 11:32:43 +02:00 коммит произвёл Johannes Schindelin
Родитель cd90b7f6bc
Коммит 811387f979
3 изменённых файлов: 22 добавлений и 8 удалений

Просмотреть файл

@ -1105,7 +1105,8 @@ static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen)
return 0;
}
static int check_and_freshen(const struct object_id *oid, int freshen)
static int check_and_freshen(const struct object_id *oid, int freshen,
int skip_virtualized_objects)
{
int ret;
int tried_hook = 0;
@ -1113,7 +1114,8 @@ static int check_and_freshen(const struct object_id *oid, int freshen)
retry:
ret = check_and_freshen_local(oid, freshen) ||
check_and_freshen_nonlocal(oid, 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(oid))
goto retry;
@ -1129,7 +1131,7 @@ int has_loose_object_nonlocal(const struct object_id *oid)
int has_loose_object(const struct object_id *oid)
{
return check_and_freshen(oid, 0);
return check_and_freshen(oid, 0, 0);
}
static void mmap_limit_check(size_t length)
@ -2201,9 +2203,10 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
return finalize_object_file(tmp_file.buf, filename.buf);
}
static int freshen_loose_object(const struct object_id *oid)
static int freshen_loose_object(const struct object_id *oid,
int skip_virtualized_objects)
{
return check_and_freshen(oid, 1);
return check_and_freshen(oid, 1, skip_virtualized_objects);
}
static int freshen_packed_object(const struct object_id *oid)
@ -2297,7 +2300,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
die(_("deflateEnd on stream object failed (%d)"), ret);
close_loose_object(fd, tmp_file.buf);
if (freshen_packed_object(oid) || freshen_loose_object(oid)) {
if (freshen_packed_object(oid) || freshen_loose_object(oid, 1)) {
unlink_or_warn(tmp_file.buf);
goto cleanup;
}
@ -2337,7 +2340,7 @@ int write_object_file_flags(const void *buf, size_t len,
*/
write_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr,
&hdrlen);
if (freshen_packed_object(oid) || freshen_loose_object(oid))
if (freshen_packed_object(oid) || freshen_loose_object(oid, 1))
return 0;
return write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags);
}
@ -2358,7 +2361,7 @@ int write_object_file_literally(const void *buf, size_t len,
if (!(flags & HASH_WRITE_OBJECT))
goto cleanup;
if (freshen_packed_object(oid) || freshen_loose_object(oid))
if (freshen_packed_object(oid) || freshen_loose_object(oid, 1))
goto cleanup;
status = write_loose_object(oid, header, hdrlen, buf, len, 0, 0);

Просмотреть файл

@ -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'";
}

Просмотреть файл

@ -26,5 +26,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