git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v5 2/7] packfile: always declare object info to be OI_PACKED

From
Patrick Steinhardt <ps@pks.im>
Date
Jan 12, 2026, 09:00 UTC
Message-ID
<20260112-b4-pks-odb-read-object-info-improvements-v5-2-9a6124e95bf2@pks.im>
In-Reply-To
<20260112-b4-pks-odb-read-object-info-improvements-v5-0-9a6124e95bf2@pks.im>
When reading object info via a packfile we yield one of two types:
  - The object can either be OI_PACKED, which is what a caller would
    typically expect.
  - Or it can be OI_DBCACHED if it is stored in the delta base cache.

The latter really is an implementation detail though, and callers typically don't care at all about the difference. Furthermore, the information whether or not it is part of the delta base cache can already be derived via the `is_delta` field, so the fact that we discern between OI_PACKED and OI_DBCACHED only further complicates the interface.

There aren't all that many callers that care about the `whence` field in the first place. In fact, there's only three:

  - `packfile_store_read_object_info()` checks for `whence == OI_PACKED`
    and then populates the packfile information of the object info
    structure. We now start to do this also for deltified objects, which
    gives its callers strictly more information.
  - `repack_local_links()` wants to determine whether the object is part
    of a promisor pack and checks for `whence == OI_PACKED`. If so, it
    verifies that the packfile is a promisor pack. It's arguably wrong
    to declare that an object is not part of a promisor pack only
    because it is stored in the delta base cache.
  - `is_not_in_promisor_pack_obj()` does the same, but checks that a
    specific object is _not_ part of a promisor pack. The same reasoning
    as above applies.

Drop the OI_DBCACHED enum completely. None of the callers seem to care about the distinction.

Note that this also fixes a segfault introduced in 8c1b84bc97 (streaming: move logic to read packed objects streams into backend, 2025-11-23), which refactors how we stream packed objects. The intent is to only read packed objects in case they are stored non-deltified as we'd otherwise have to deflate them first. But the check for whether or not the object is stored as a delta was unconditionally done via `oi.u.packed.is_delta`, which is only valid in case `oi.whence` is `OI_PACKED`. But under some circumstances we got `OI_DBCACHED` here, which means that none of the `oi.u.packed` fields were initialized at all. Consequently, we assumed the object was not stored as a delta, and then try to read the object from `oi.u.packed.pack`, which is a `NULL` pointer and thus causes a segfault.

Add a test case for this issue so that this cannot regress in the future anymore.

Reported-by: Matt Smiley <msmiley@gitlab.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 odb.h                  |  1 -
 packfile.c             |  3 +--
 t/t5003-archive-zip.sh | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/odb.h b/odb.h
index 014cd9585a..73b0b87ad5 100644
--- a/odb.h
+++ b/odb.h
@@ -330,7 +330,6 @@ struct object_info {
 		OI_CACHED,
 		OI_LOOSE,
 		OI_PACKED,
-		OI_DBCACHED
 	} whence;
 	union {
 		/*
diff --git a/packfile.c b/packfile.c
index 08a0863fc3..b0c6665c87 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1656,8 +1656,7 @@ int packed_object_info(struct repository *r, struct packed_git *p,
 			oidclr(oi->delta_base_oid, p->repo->hash_algo);
 	}
 
-	oi->whence = in_delta_base_cache(p, obj_offset) ? OI_DBCACHED :
-							  OI_PACKED;
+	oi->whence = OI_PACKED;
 
 out:
 	unuse_pack(&w_curs);
diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh
index 961c6aac25..c8c1c5c06b 100755
--- a/t/t5003-archive-zip.sh
+++ b/t/t5003-archive-zip.sh
@@ -239,6 +239,40 @@ check_zip with_untracked2
 check_added with_untracked2 untracked one/untracked
 check_added with_untracked2 untracked two/untracked
 
+test_expect_success 'git-archive --format=zip with bigFile delta chains' '
+	test_when_finished rm -rf repo &&
+	git init repo &&
+	(
+		cd repo &&
+		test-tool genrandom foo 100000 >base &&
+		{
+			cat base &&
+			echo "trailing data"
+		} >delta-1 &&
+		{
+			cat delta-1 &&
+			echo "trailing data"
+		} >delta-2 &&
+		git add . &&
+		git commit -m "blobs" &&
+		git repack -Ad &&
+		git verify-pack -v .git/objects/pack/pack-*.idx >stats &&
+		test_grep "chain length = 1: 1 object" stats &&
+		test_grep "chain length = 2: 1 object" stats &&
+
+		git -c core.bigFileThreshold=1k archive --format=zip HEAD >archive.zip &&
+		if test_have_prereq UNZIP
+		then
+			mkdir unpack &&
+			cd unpack &&
+			"$GIT_UNZIP" ../archive.zip &&
+			test_cmp base ../base &&
+			test_cmp delta-1 ../delta-1 &&
+			test_cmp delta-2 ../delta-2
+		fi
+	)
+'
+
 # Test remote archive over HTTP protocol.
 #
 # Note: this should be the last part of this test suite, because
-- 
2.52.0.590.g1f87b77810.dirty
Previous: Patrick SteinhardtNext: Junio C Hamano
Message 52 of 58 in “Improvements for reading object info”
  1. 0/8 Improvements for reading object infoPatrick Steinhardt, Dec 18, 2025
  2. 1/8 object-file: always set OI_LOOSE when reading object infoPatrick Steinhardt, Dec 18, 2025
  3. 2/8 packfile: always declare object info to be OI_PACKEDPatrick Steinhardt, Dec 18, 2025
  4. Junio C HamanoDec 18, 2025
  5. Patrick SteinhardtDec 18, 2025
  6. 3/8 packfile: extend `is_delta` field to allow for "unknown" statePatrick Steinhardt, Dec 18, 2025
  7. 4/8 packfile: always populate pack-specific info when reading object infoPatrick Steinhardt, Dec 18, 2025
  8. Junio C HamanoDec 18, 2025
  9. 5/8 packfile: disentangle return value of `packed_object_info()`Patrick Steinhardt, Dec 18, 2025
  10. 6/8 packfile: skip unpacking object header for disk size requestsPatrick Steinhardt, Dec 18, 2025
  11. 7/8 packfile: fix short-circuiting of empty requestsPatrick Steinhardt, Dec 18, 2025
  12. 8/8 packfile: drop repository parameter from `packed_object_info()`Patrick Steinhardt, Dec 18, 2025
  13. Junio C HamanoDec 18, 2025
  14. Patrick SteinhardtDec 18, 2025
  15. 0/7 Improvements for reading object infoPatrick Steinhardt, Dec 18, 2025
  16. 1/7 object-file: always set OI_LOOSE when reading object infoPatrick Steinhardt, Dec 18, 2025
  17. 2/7 packfile: always declare object info to be OI_PACKEDPatrick Steinhardt, Dec 18, 2025
  18. Toon ClaesJan 5, 2026
  19. 3/7 packfile: extend `is_delta` field to allow for "unknown" statePatrick Steinhardt, Dec 18, 2025
  20. Toon ClaesJan 5, 2026
  21. Patrick SteinhardtJan 6, 2026
  22. 4/7 packfile: always populate pack-specific info when reading object infoPatrick Steinhardt, Dec 18, 2025
  23. Kristoffer HaugsbakkDec 30, 2025
  24. Patrick SteinhardtJan 5, 2026
  25. 5/7 packfile: disentangle return value of `packed_object_info()`Patrick Steinhardt, Dec 18, 2025
  26. 6/7 packfile: skip unpacking object header for disk size requestsPatrick Steinhardt, Dec 18, 2025
  27. 7/7 packfile: drop repository parameter from `packed_object_info()`Patrick Steinhardt, Dec 18, 2025
  28. 0/7 Improvements for reading object infoPatrick Steinhardt, Jan 6, 2026
  29. 1/7 object-file: always set OI_LOOSE when reading object infoPatrick Steinhardt, Jan 6, 2026
  30. Karthik NayakJan 7, 2026
  31. Patrick SteinhardtJan 7, 2026
  32. 2/7 packfile: always declare object info to be OI_PACKEDPatrick Steinhardt, Jan 6, 2026
  33. 3/7 packfile: extend `is_delta` field to allow for "unknown" statePatrick Steinhardt, Jan 6, 2026
  34. Karthik NayakJan 7, 2026
  35. 4/7 packfile: always populate pack-specific info when reading object infoPatrick Steinhardt, Jan 6, 2026
  36. 5/7 packfile: disentangle return value of `packed_object_info()`Patrick Steinhardt, Jan 6, 2026
  37. 6/7 packfile: skip unpacking object header for disk size requestsPatrick Steinhardt, Jan 6, 2026
  38. 7/7 packfile: drop repository parameter from `packed_object_info()`Patrick Steinhardt, Jan 6, 2026
  39. Karthik NayakJan 7, 2026
  40. 0/7 Improvements for reading object infoPatrick Steinhardt, Jan 7, 2026
  41. 1/7 object-file: always set OI_LOOSE when reading object infoPatrick Steinhardt, Jan 7, 2026
  42. Karthik NayakJan 8, 2026
  43. 2/7 packfile: always declare object info to be OI_PACKEDPatrick Steinhardt, Jan 7, 2026
  44. 3/7 packfile: extend `is_delta` field to allow for "unknown" statePatrick Steinhardt, Jan 7, 2026
  45. 4/7 packfile: always populate pack-specific info when reading object infoPatrick Steinhardt, Jan 7, 2026
  46. 5/7 packfile: disentangle return value of `packed_object_info()`Patrick Steinhardt, Jan 7, 2026
  47. 6/7 packfile: skip unpacking object header for disk size requestsPatrick Steinhardt, Jan 7, 2026
  48. 7/7 packfile: drop repository parameter from `packed_object_info()`Patrick Steinhardt, Jan 7, 2026
  49. Karthik NayakJan 8, 2026
  50. 0/7 Improvements for reading object infoPatrick Steinhardt, Jan 12, 2026
  51. 1/7 object-file: always set OI_LOOSE when reading object infoPatrick Steinhardt, Jan 12, 2026
  52. 2/7 packfile: always declare object info to be OI_PACKEDPatrick Steinhardt, Jan 12, 2026
  53. Junio C HamanoJan 12, 2026
  54. 3/7 packfile: extend `is_delta` field to allow for "unknown" statePatrick Steinhardt, Jan 12, 2026
  55. 4/7 packfile: always populate pack-specific info when reading object infoPatrick Steinhardt, Jan 12, 2026
  56. 5/7 packfile: disentangle return value of `packed_object_info()`Patrick Steinhardt, Jan 12, 2026
  57. 6/7 packfile: skip unpacking object header for disk size requestsPatrick Steinhardt, Jan 12, 2026
  58. 7/7 packfile: drop repository parameter from `packed_object_info()`Patrick Steinhardt, Jan 12, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.