Merge branch 'jt/object-file-batch-fsync-fix'

When 'core.fsyncMethod' is set to 'batch', the ODB transaction
failed to properly flush large blob packfiles residing in the
temporary directory before migrating the directory's contents to the
main object store.  The execution sequence has been corrected by
performing the packfile flush before the temporary directory
migration, averting failure.

* jt/object-file-batch-fsync-fix:
  object-file: flush transaction packfile before migrating objects
  object-file: lift ODB reprepare out of packfile flush
main
Junio C Hamano 2026-10-05 13:52:28 -07:00
commit d2bda356b7
2 changed files with 25 additions and 4 deletions

View File

@ -857,8 +857,6 @@ clear_exit:
memset(state, 0, sizeof(*state));

strbuf_release(&packname);
/* Make objects we just wrote available to ourselves */
odb_reprepare(repo->objects);
}

/*
@ -909,8 +907,10 @@ static int odb_transaction_files_write_object_stream(struct odb_transaction *bas
* to zlib compression and is sufficient for this check.
*/
if (state->nr_written && pack_size_limit_cfg &&
pack_size_limit_cfg < state->offset + stream->size)
pack_size_limit_cfg < state->offset + stream->size) {
flush_packfile_transaction(transaction);
odb_reprepare(transaction->base.source->odb);
}

CALLOC_ARRAY(idx, 1);
prepare_packfile_transaction(transaction);
@ -1260,6 +1260,9 @@ static int odb_transaction_files_commit(struct odb_transaction *base)
{
struct odb_transaction_files *transaction =
container_of(base, struct odb_transaction_files, base);
int have_packfile = !!transaction->packfile.f;

flush_packfile_transaction(transaction);

if (transaction->objdir) {
struct strbuf temp_path = STRBUF_INIT;
@ -1291,7 +1294,8 @@ static int odb_transaction_files_commit(struct odb_transaction *base)
transaction->objdir = NULL;
}

flush_packfile_transaction(transaction);
if (have_packfile)
odb_reprepare(transaction->base.source->odb);

return 0;
}

View File

@ -87,6 +87,23 @@ test_expect_success 'add a large file or two' '
test $count = 1
'

test_expect_success 'add large file with loose object in batch fsync' '
test_when_finished "rm -rf batch" &&
git init batch &&
(
cd batch &&
git config core.bigFileThreshold 5 &&
echo foo >1-small &&
echo foobar >2-large &&

git -c core.fsync=loose-object -c core.fsyncMethod=batch \
add 1-small 2-large &&

git cat-file -e :1-small &&
git cat-file -e :2-large
)
'

test_expect_success 'checkout a large file' '
large1=$(git rev-parse :large1) &&
git update-index --add --cacheinfo 100644 $large1 another &&