Skip to content

Commit 5591ca7

Browse files
committed
cat-file: fall back to OID lookup when a pack disappears mid-stream
"git cat-file --batch-all-objects --unordered" reads each object from the pack and offset the walk handed it, rather than looking it up again. If a concurrent repack removes that pack in between, packed_object_info() calls use_pack(), which cannot reopen the unlinked pack and dies with "packfile ... cannot be accessed" -- even though the object still lives in the pack repack just wrote. Guard the read with is_pack_valid(): if the pack can no longer be opened, clear the pointer so we fall back to a normal object-database lookup, which finds the object in whatever pack now holds it. is_pack_valid() opens and pins the pack's fd, so once it succeeds the pack stays readable even if it is unlinked an instant later. Assisted-by: Claude Opus 4.8 Signed-off-by: Elijah Newren <newren@gmail.com>
1 parent 7d955bb commit 5591ca7

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

‎builtin/cat-file.c‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,15 @@ static void batch_object_write(const char *obj_name,
543543
if (opt->objects_filter.choice == LOFC_BLOB_LIMIT)
544544
data->info.sizep = &data->size;
545545

546+
/*
547+
* With "--batch-all-objects --unordered" we read straight
548+
* from the pack the walk handed us. If a concurrent repack
549+
* removed it, fall back to a normal lookup; is_pack_valid()
550+
* pins the pack's fd, so a passing check stays valid even if
551+
* the pack is unlinked right after.
552+
*/
553+
if (pack && !is_pack_valid(pack))
554+
pack = NULL;
546555
if (pack)
547556
ret = packed_object_info(NULL, pack, offset, &data->info);
548557
else

0 commit comments

Comments
 (0)