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

[PATCH v2 2/5] packfile: factor out --pack_header argument parsing

From
Jeff King <peff@peff.net>
Date
Jan 19, 2025, 13:23 UTC
Message-ID
<20250119132337.GB1552263@coredump.intra.peff.net>
In-Reply-To
<20250119131224.GA1541095@coredump.intra.peff.net>

Both index-pack and unpack-objects accept a --pack_header argument. This is an undocumented internal argument used by receive-pack and fetch to pass along information about the header of the pack, which they've already read from the incoming stream.

In preparation for a bugfix, let's factor the duplicated code into a common helper.

The callers are still responsible for identifying the option. While this could likewise be factored out, it is more flexible this way (e.g., if they ever started using parse-options and wanted to handle both the stuck and unstuck forms).

Likewise, the callers are responsible for reporting errors, though they both just call die(). I've tweaked unpack-objects to match index-pack in marking the error for translation.

Signed-off-by: Jeff King <peff@peff.net>
---
Same as before.
 builtin/index-pack.c     | 14 +++-----------
 builtin/unpack-objects.c | 16 ++++------------
 packfile.c               | 17 +++++++++++++++++
 packfile.h               |  6 ++++++
 4 files changed, 30 insertions(+), 23 deletions(-)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 0b62b2589f..75b84f78f4 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1955,18 +1955,10 @@ int cmd_index_pack(int argc,
 					nr_threads = 1;
 				}
 			} else if (starts_with(arg, "--pack_header=")) {
-				struct pack_header *hdr;
-				char *c;
-
-				hdr = (struct pack_header *)input_buffer;
-				hdr->hdr_signature = htonl(PACK_SIGNATURE);
-				hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
-				if (*c != ',')
-					die(_("bad %s"), arg);
-				hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
-				if (*c)
+				if (parse_pack_header_option(arg + 14,
+							     input_buffer,
+							     &input_len) < 0)
 					die(_("bad %s"), arg);
-				input_len = sizeof(*hdr);
 			} else if (!strcmp(arg, "-v")) {
 				verbose = 1;
 			} else if (!strcmp(arg, "--progress-title")) {
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 2197d6d933..cf2bc5c531 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -18,6 +18,7 @@
 #include "progress.h"
 #include "decorate.h"
 #include "fsck.h"
+#include "packfile.h"
 
 static int dry_run, quiet, recover, has_errors, strict;
 static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict]";
@@ -645,18 +646,9 @@ int cmd_unpack_objects(int argc,
 				continue;
 			}
 			if (starts_with(arg, "--pack_header=")) {
-				struct pack_header *hdr;
-				char *c;
-
-				hdr = (struct pack_header *)buffer;
-				hdr->hdr_signature = htonl(PACK_SIGNATURE);
-				hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
-				if (*c != ',')
-					die("bad %s", arg);
-				hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
-				if (*c)
-					die("bad %s", arg);
-				len = sizeof(*hdr);
+				if (parse_pack_header_option(arg + 14,
+							     buffer, &len) < 0)
+					die(_("bad %s"), arg);
 				continue;
 			}
 			if (skip_prefix(arg, "--max-input-size=", &arg)) {
diff --git a/packfile.c b/packfile.c
index cc7ab6403a..2bf9e57330 100644
--- a/packfile.c
+++ b/packfile.c
@@ -2315,3 +2315,20 @@ int is_promisor_object(struct repository *r, const struct object_id *oid)
 	}
 	return oidset_contains(&promisor_objects, oid);
 }
+
+int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *len)
+{
+	struct pack_header *hdr;
+	char *c;
+
+	hdr = (struct pack_header *)out;
+	hdr->hdr_signature = htonl(PACK_SIGNATURE);
+	hdr->hdr_version = htonl(strtoul(in, &c, 10));
+	if (*c != ',')
+		return -1;
+	hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
+	if (*c)
+		return -1;
+	*len = sizeof(*hdr);
+	return 0;
+}
diff --git a/packfile.h b/packfile.h
index 58104fa009..00ada7a938 100644
--- a/packfile.h
+++ b/packfile.h
@@ -216,4 +216,10 @@ int is_promisor_object(struct repository *r, const struct object_id *oid);
 int load_idx(const char *path, const unsigned int hashsz, void *idx_map,
 	     size_t idx_size, struct packed_git *p);
 
+/*
+ * Parse a --pack_header option as accepted by index-pack and unpack-objects,
+ * turning it into the matching bytes we'd find in a pack.
+ */
+int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *len);
+
 #endif
-- 
2.48.1.466.g22b8cfd1fa
Previous: Jeff KingNext: Jeff King
Message 17 of 22 in “[BUG] git crashes with a SIGBUS on sparc64 during pull”
  1. KoakumaJan 17, 2025
  2. Jeff KingJan 17, 2025
  3. Jeff KingJan 17, 2025
  4. 1/3 packfile: factor out --pack_header argument parsingJeff King, Jan 17, 2025
  5. Junio C HamanoJan 17, 2025
  6. Jeff KingJan 18, 2025
  7. KoakumaJan 18, 2025
  8. 2/3 parse_pack_header_option(): avoid unaligned memory writesJeff King, Jan 17, 2025
  9. Junio C HamanoJan 18, 2025
  10. Jeff KingJan 18, 2025
  11. 3/3 index-pack, unpack-objects: use skip_prefix to avoid magic numberJeff King, Jan 17, 2025
  12. KoakumaJan 17, 2025
  13. Jeff KingJan 18, 2025
  14. KoakumaJan 18, 2025
  15. 0/5 git crashes with a SIGBUS on sparc64 during pullJeff King, Jan 19, 2025
  16. 1/5 bswap.h: squelch potential sparse -Wcast-truncate warningsJeff King, Jan 19, 2025
  17. 2/5 packfile: factor out --pack_header argument parsingJeff King, Jan 19, 2025
  18. 3/5 parse_pack_header_option(): avoid unaligned memory writesJeff King, Jan 19, 2025
  19. 4/5 index-pack, unpack-objects: use get_be32() for reading pack headerJeff King, Jan 19, 2025
  20. 5/5 index-pack, unpack-objects: use skip_prefix to avoid magic numberJeff King, Jan 19, 2025
  21. KoakumaJan 20, 2025
  22. Junio C HamanoJan 21, 2025

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.