]> git.ipfire.org Git - thirdparty/git.git/commitdiff
object-file API: add a format_object_header() function
authorÆvar Arnfjörð Bjarmason <avarab@gmail.com>
Fri, 4 Feb 2022 23:48:25 +0000 (00:48 +0100)
committerJunio C Hamano <gitster@pobox.com>
Sat, 26 Feb 2022 01:16:31 +0000 (17:16 -0800)
Add a convenience function to wrap the xsnprintf() command that
generates loose object headers. This code was copy/pasted in various
parts of the codebase, let's define it in one place and re-use it from
there.

All except one caller of it had a valid "enum object_type" for us,
it's only write_object_file_prepare() which might need to deal with
"git hash-object --literally" and a potential garbage type. Let's have
the primary API use an "enum object_type", and define a *_literally()
function that can take an arbitrary "const char *" for the type.

See [1] for the discussion that prompted this patch, i.e. new code in
object-file.c that wanted to copy/paste the xsnprintf() invocation.

In the case of fast-import.c the callers unfortunately need to cast
back & forth between "unsigned char *" and "char *", since
format_object_header() ad encode_in_pack_object_header() take
different signedness.

1. https://lore.kernel.org/git/211213.86bl1l9bfz.gmgdl@evledraar.gmail.com/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fast-import.c
builtin/index-pack.c
bulk-checkin.c
http-push.c
object-file.c
object-store.h

index 2b2e28bad79cbaef25b4eb8fea4c0f800ba4a89d..123df7d9a537edb952c9d847076d1fcca4c058b8 100644 (file)
@@ -937,8 +937,8 @@ static int store_object(
        git_hash_ctx c;
        git_zstream s;
 
-       hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu",
-                          type_name(type), (unsigned long)dat->len) + 1;
+       hdrlen = format_object_header((char *)hdr, sizeof(hdr), type,
+                                     dat->len);
        the_hash_algo->init_fn(&c);
        the_hash_algo->update_fn(&c, hdr, hdrlen);
        the_hash_algo->update_fn(&c, dat->buf, dat->len);
@@ -1091,7 +1091,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
        hashfile_checkpoint(pack_file, &checkpoint);
        offset = checkpoint.offset;
 
-       hdrlen = xsnprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1;
+       hdrlen = format_object_header((char *)out_buf, out_sz, OBJ_BLOB, len);
 
        the_hash_algo->init_fn(&c);
        the_hash_algo->update_fn(&c, out_buf, hdrlen);
index 3c2e6aee3cc67be5df9bc1b4b62f5cd8a5c26b86..01574378ce2a190a5b0daa76f10b89d4c6b371b2 100644 (file)
@@ -449,8 +449,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size,
        int hdrlen;
 
        if (!is_delta_type(type)) {
-               hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX,
-                                  type_name(type),(uintmax_t)size) + 1;
+               hdrlen = format_object_header(hdr, sizeof(hdr), type, size);
                the_hash_algo->init_fn(&c);
                the_hash_algo->update_fn(&c, hdr, hdrlen);
        } else
index 8785b2ac80699255ae8abd0801922ba025235309..85b3ebaf971087f2863b7d3bc6da5ee7be3317cb 100644 (file)
@@ -220,8 +220,8 @@ static int deflate_to_pack(struct bulk_checkin_state *state,
        if (seekback == (off_t) -1)
                return error("cannot find the current offset");
 
-       header_len = xsnprintf((char *)obuf, sizeof(obuf), "%s %" PRIuMAX,
-                              type_name(type), (uintmax_t)size) + 1;
+       header_len = format_object_header((char *)obuf, sizeof(obuf),
+                                         type, size);
        the_hash_algo->init_fn(&ctx);
        the_hash_algo->update_fn(&ctx, obuf, header_len);
 
index 3309aaf004a4db175bc4c0b94b5c63efebcb30e3..f0c044dcf7661a37b2a03f59e11f9e0bcefba0ea 100644 (file)
@@ -363,7 +363,7 @@ static void start_put(struct transfer_request *request)
        git_zstream stream;
 
        unpacked = read_object_file(&request->obj->oid, &type, &len);
-       hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1;
+       hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
 
        /* Set it up */
        git_deflate_init(&stream, zlib_compression_level);
index eeb6814780ad6a6d51768d99fbd19157b525a53f..3fcd46cf9ed8762859f676d24365b11dd9c078c7 100644 (file)
@@ -1049,6 +1049,23 @@ void *xmmap(void *start, size_t length,
        return ret;
 }
 
+static int format_object_header_literally(char *str, size_t size,
+                                         const char *type, size_t objsize)
+{
+       return xsnprintf(str, size, "%s %"PRIuMAX, type, (uintmax_t)objsize) + 1;
+}
+
+int format_object_header(char *str, size_t size, enum object_type type,
+                        size_t objsize)
+{
+       const char *name = type_name(type);
+
+       if (!name)
+               BUG("could not get a type name for 'enum object_type' value %d", type);
+
+       return format_object_header_literally(str, size, name, objsize);
+}
+
 /*
  * With an in-core object data in "map", rehash it to make sure the
  * object name actually matches "oid" to detect object corruption.
@@ -1077,7 +1094,7 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
                return -1;
 
        /* Generate the header */
-       hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(obj_type), (uintmax_t)size) + 1;
+       hdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size);
 
        /* Sha1.. */
        r->hash_algo->init_fn(&c);
@@ -1777,7 +1794,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo,
        git_hash_ctx c;
 
        /* Generate the header */
-       *hdrlen = xsnprintf(hdr, *hdrlen, "%s %"PRIuMAX , type, (uintmax_t)len)+1;
+       *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);
 
        /* Sha1.. */
        algo->init_fn(&c);
@@ -2051,7 +2068,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
        buf = read_object(the_repository, oid, &type, &len);
        if (!buf)
                return error(_("cannot read object for %s"), oid_to_hex(oid));
-       hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1;
+       hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
        ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);
        free(buf);
 
index 44f6868cc9c46ee1367b237fb66cdb8e0acbedf6..8b4413d0ce70ff35dc71715ffbe1e45d2f3a680f 100644 (file)
@@ -331,6 +331,14 @@ int repo_has_object_file_with_flags(struct repository *r,
  */
 int has_loose_object_nonlocal(const struct object_id *);
 
+/**
+ * format_object_header() is a thin wrapper around s xsnprintf() that
+ * writes the initial "<type> <obj-len>" part of the loose object
+ * header. It returns the size that snprintf() returns + 1.
+ */
+int format_object_header(char *str, size_t size, enum object_type type,
+                        size_t objsize);
+
 void assert_oid_type(const struct object_id *oid, enum object_type expect);
 
 /*