{"thread":{"id":"57347","subject":"[PATCH 00/10] object-file API: pass object enums, tidy up streaming interface","startedAt":"2022-02-01T14:53:19Z","lastAt":"2022-03-01T03:09:36Z","messageCount":46,"participants":["Ævar Arnfjörð Bjarmason","Junio C Hamano","Jiang Xin"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"447407","messageId":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":null,"subject":"[PATCH 00/10] object-file API: pass object enums, tidy up streaming interface","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:02Z","receivedAt":"2022-02-01T14:53:19Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"This is intended to help along the \"unpack large blobs in stream\"\nseries that Han Xin has been submitting. The v9 of it is available\nat[1], but not currently picked up by Junio.\n\nThis changes those parts of the object-file.c API that took a \"const\nchar *\" type to take an \"enum object_type\" instead. We had a lot of\nplaces that would convert back & forth between the two for no good\nreason. We're still left with the \"literally\" interface for \"git\nhash-object --literally\", but it's now a tiny part of the API that's\nsidelined.\n\nThis also has various small API cleanups, such as returning \"void\" in\na case where no caller did (or should) use a return value in the case\nof hash_object_file().\n\nWe then introduce the format_object_header() helper, part of that was\nin Han Xin's version, but we had various other in-tree users that\ncould use it (which I found later, after my initial RFC patch).\n\nWe can then split up the two classes of API users of\ncheck_object_signature() to use two different functions, which suits\ntheir uses much better. Half of them were making use of a very early\nreturn.\n\n1. https://lore.kernel.org/git/20220120112114.47618-1-chiyutianyi@gmail.com/\n\nÆvar Arnfjörð Bjarmason (10):\n  object-file.c: split up declaration of unrelated variables\n  object-file API: return \"void\", not \"int\" from hash_object_file()\n  object-file API: add a format_object_header() function\n  object-file API: have write_object_file() take \"enum object_type\"\n  object-file API: provide a hash_object_file_oideq()\n  object-file API: replace some use of check_object_signature()\n  object-file API: have hash_object_file() take \"enum object_type\"\n  object-file API: replace check_object_signature() with stream_*\n  object-file.c: add a literal version of write_object_file_prepare()\n  object-file API: pass an enum to read_object_with_reference()\n\n apply.c                  |  12 ++--\n builtin/cat-file.c       |  11 +--\n builtin/checkout.c       |   2 +-\n builtin/fast-export.c    |   4 +-\n builtin/fast-import.c    |  12 ++--\n builtin/grep.c           |   4 +-\n builtin/hash-object.c    |   4 +-\n builtin/index-pack.c     |  10 ++-\n builtin/mktag.c          |   7 +-\n builtin/mktree.c         |   2 +-\n builtin/notes.c          |   3 +-\n builtin/pack-objects.c   |   2 +-\n builtin/receive-pack.c   |   2 +-\n builtin/replace.c        |   4 +-\n builtin/tag.c            |   2 +-\n builtin/unpack-objects.c |   8 +--\n bulk-checkin.c           |   4 +-\n cache-tree.c             |   8 +--\n cache.h                  |  13 ++--\n commit.c                 |   2 +-\n convert.c                |   2 +-\n diffcore-rename.c        |   2 +-\n dir.c                    |   2 +-\n http-push.c              |   2 +-\n log-tree.c               |   2 +-\n match-trees.c            |   2 +-\n merge-ort.c              |   4 +-\n merge-recursive.c        |   2 +-\n notes-cache.c            |   2 +-\n notes.c                  |   8 +--\n object-file.c            | 142 ++++++++++++++++++++++++++-------------\n object-store.h           |  39 ++++++++---\n object.c                 |   6 +-\n pack-check.c             |   8 ++-\n read-cache.c             |   2 +-\n tree-walk.c              |   6 +-\n 36 files changed, 213 insertions(+), 134 deletions(-)\n\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447408","messageId":"patch-01.10-53334bc970a-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 01/10] object-file.c: split up declaration of unrelated variables","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:03Z","receivedAt":"2022-02-01T14:53:21Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split up the declaration of the \"ret\" and \"re_allocated\"\nvariables. It's not our usual style to group variable declarations\nsimply because they share a type, we'd only prefer to do so when the\ntwo are closely related (e.g. \"int i, j\"). This change makes a\nsubsequent and meaningful change's diff smaller.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex 8be57f48de7..ecc77973292 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2118,7 +2118,8 @@ static int index_mem(struct index_state *istate,\n \t\t     enum object_type type,\n \t\t     const char *path, unsigned flags)\n {\n-\tint ret, re_allocated = 0;\n+\tint ret;\n+\tint re_allocated = 0;\n \tint write_object = flags & HASH_WRITE_OBJECT;\n \n \tif (!type)\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447409","messageId":"patch-02.10-ab1d204f49b-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 02/10] object-file API: return \"void\", not \"int\" from hash_object_file()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:04Z","receivedAt":"2022-02-01T14:53:22Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"The hash_object_file() function added in abdc3fc8421 (Add\nhash_sha1_file(), 2006-10-14) did not have a meaningful return value,\nand it never has.\n\nOne was seemingly added to avoid adding braces to the \"ret = \"\nassignments being modified here. Let's instead assign \"0\" to the \"ret\"\nvariables at the beginning of the relevant functions, and have them\nreturn \"void\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c  | 16 ++++++++--------\n object-store.h |  6 +++---\n 2 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex ecc77973292..eeb6814780a 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1836,14 +1836,13 @@ static int write_buffer(int fd, const void *buf, size_t len)\n \treturn 0;\n }\n \n-int hash_object_file(const struct git_hash_algo *algo, const void *buf,\n+void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \t\t     unsigned long len, const char *type,\n \t\t     struct object_id *oid)\n {\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n-\treturn 0;\n }\n \n /* Finalize a file on disk, and close it. */\n@@ -2118,7 +2117,7 @@ static int index_mem(struct index_state *istate,\n \t\t     enum object_type type,\n \t\t     const char *path, unsigned flags)\n {\n-\tint ret;\n+\tint ret = 0;\n \tint re_allocated = 0;\n \tint write_object = flags & HASH_WRITE_OBJECT;\n \n@@ -2148,8 +2147,9 @@ static int index_mem(struct index_state *istate,\n \tif (write_object)\n \t\tret = write_object_file(buf, size, type_name(type), oid);\n \telse\n-\t\tret = hash_object_file(the_hash_algo, buf, size,\n-\t\t\t\t       type_name(type), oid);\n+\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n+\t\t\t\t oid);\n+\n \tif (re_allocated)\n \t\tfree(buf);\n \treturn ret;\n@@ -2161,7 +2161,7 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\t\t\t     const char *path,\n \t\t\t\t     unsigned flags)\n {\n-\tint ret;\n+\tint ret = 0;\n \tconst int write_object = flags & HASH_WRITE_OBJECT;\n \tstruct strbuf sbuf = STRBUF_INIT;\n \n@@ -2175,8 +2175,8 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\tret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB),\n \t\t\t\t\toid);\n \telse\n-\t\tret = hash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n-\t\t\t\t       type_name(OBJ_BLOB), oid);\n+\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n+\t\t\t\t type_name(OBJ_BLOB), oid);\n \tstrbuf_release(&sbuf);\n \treturn ret;\n }\ndiff --git a/object-store.h b/object-store.h\nindex 6f89482df03..44f6868cc9c 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -245,9 +245,9 @@ static inline void *repo_read_object_file(struct repository *r,\n /* Read and unpack an object file into memory, write memory to an object file */\n int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);\n \n-int hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t     unsigned long len, const char *type,\n-\t\t     struct object_id *oid);\n+void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n+\t\t      unsigned long len, const char *type,\n+\t\t      struct object_id *oid);\n \n int write_object_file_flags(const void *buf, unsigned long len,\n \t\t\t    const char *type, struct object_id *oid,\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447410","messageId":"patch-03.10-64484e046ea-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 03/10] object-file API: add a format_object_header() function","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:05Z","receivedAt":"2022-02-01T14:53:24Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a convenience function to wrap the xsnprintf() command that\ngenerates loose object headers. This code was copy/pasted in various\nparts of the codebase, let's define it in one place and re-use it from\nthere.\n\nAll except one caller of it had a valid \"enum object_type\" for us,\nit's only write_object_file_prepare() which might need to deal with\n\"git hash-object --literally\" and a potential garbage type. Let's have\nthe primary API use an \"enum object_type\", and define a *_literally()\nfunction that can take an arbitrary \"const char *\" for the type.\n\nSee [1] for the discussion that prompted this patch, i.e. new code in\nobject-file.c that wanted to copy/paste the xsnprintf() invocation.\n\nIn the case of fast-import.c the callers unfortunately need to cast\nback & forth between \"unsigned char *\" and \"char *\", since\nformat_object_header() ad encode_in_pack_object_header() take\ndifferent signedness.\n\n1. https://lore.kernel.org/git/211213.86bl1l9bfz.gmgdl@evledraar.gmail.com/\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/fast-import.c |  6 +++---\n builtin/index-pack.c  |  3 +--\n bulk-checkin.c        |  4 ++--\n http-push.c           |  2 +-\n object-file.c         | 23 ++++++++++++++++++++---\n object-store.h        |  8 ++++++++\n 6 files changed, 35 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 2b2e28bad79..123df7d9a53 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -937,8 +937,8 @@ static int store_object(\n \tgit_hash_ctx c;\n \tgit_zstream s;\n \n-\thdrlen = xsnprintf((char *)hdr, sizeof(hdr), \"%s %lu\",\n-\t\t\t   type_name(type), (unsigned long)dat->len) + 1;\n+\thdrlen = format_object_header((char *)hdr, sizeof(hdr), type,\n+\t\t\t\t      dat->len);\n \tthe_hash_algo->init_fn(&c);\n \tthe_hash_algo->update_fn(&c, hdr, hdrlen);\n \tthe_hash_algo->update_fn(&c, dat->buf, dat->len);\n@@ -1091,7 +1091,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)\n \thashfile_checkpoint(pack_file, &checkpoint);\n \toffset = checkpoint.offset;\n \n-\thdrlen = xsnprintf((char *)out_buf, out_sz, \"blob %\" PRIuMAX, len) + 1;\n+\thdrlen = format_object_header((char *)out_buf, out_sz, OBJ_BLOB, len);\n \n \tthe_hash_algo->init_fn(&c);\n \tthe_hash_algo->update_fn(&c, out_buf, hdrlen);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 3c2e6aee3cc..01574378ce2 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -449,8 +449,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size,\n \tint hdrlen;\n \n \tif (!is_delta_type(type)) {\n-\t\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX,\n-\t\t\t\t   type_name(type),(uintmax_t)size) + 1;\n+\t\thdrlen = format_object_header(hdr, sizeof(hdr), type, size);\n \t\tthe_hash_algo->init_fn(&c);\n \t\tthe_hash_algo->update_fn(&c, hdr, hdrlen);\n \t} else\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 8785b2ac806..85b3ebaf971 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -220,8 +220,8 @@ static int deflate_to_pack(struct bulk_checkin_state *state,\n \tif (seekback == (off_t) -1)\n \t\treturn error(\"cannot find the current offset\");\n \n-\theader_len = xsnprintf((char *)obuf, sizeof(obuf), \"%s %\" PRIuMAX,\n-\t\t\t       type_name(type), (uintmax_t)size) + 1;\n+\theader_len = format_object_header((char *)obuf, sizeof(obuf),\n+\t\t\t\t\t  type, size);\n \tthe_hash_algo->init_fn(&ctx);\n \tthe_hash_algo->update_fn(&ctx, obuf, header_len);\n \ndiff --git a/http-push.c b/http-push.c\nindex 3309aaf004a..f0c044dcf76 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -363,7 +363,7 @@ static void start_put(struct transfer_request *request)\n \tgit_zstream stream;\n \n \tunpacked = read_object_file(&request->obj->oid, &type, &len);\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(type), (uintmax_t)len) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type, len);\n \n \t/* Set it up */\n \tgit_deflate_init(&stream, zlib_compression_level);\ndiff --git a/object-file.c b/object-file.c\nindex eeb6814780a..3fcd46cf9ed 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1049,6 +1049,23 @@ void *xmmap(void *start, size_t length,\n \treturn ret;\n }\n \n+static int format_object_header_literally(char *str, size_t size,\n+\t\t\t\t\t  const char *type, size_t objsize)\n+{\n+\treturn xsnprintf(str, size, \"%s %\"PRIuMAX, type, (uintmax_t)objsize) + 1;\n+}\n+\n+int format_object_header(char *str, size_t size, enum object_type type,\n+\t\t\t size_t objsize)\n+{\n+\tconst char *name = type_name(type);\n+\n+\tif (!name)\n+\t\tBUG(\"could not get a type name for 'enum object_type' value %d\", type);\n+\n+\treturn format_object_header_literally(str, size, name, objsize);\n+}\n+\n /*\n  * With an in-core object data in \"map\", rehash it to make sure the\n  * object name actually matches \"oid\" to detect object corruption.\n@@ -1077,7 +1094,7 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\treturn -1;\n \n \t/* Generate the header */\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(obj_type), (uintmax_t)size) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size);\n \n \t/* Sha1.. */\n \tr->hash_algo->init_fn(&c);\n@@ -1777,7 +1794,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo,\n \tgit_hash_ctx c;\n \n \t/* Generate the header */\n-\t*hdrlen = xsnprintf(hdr, *hdrlen, \"%s %\"PRIuMAX , type, (uintmax_t)len)+1;\n+\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n \n \t/* Sha1.. */\n \talgo->init_fn(&c);\n@@ -2051,7 +2068,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)\n \tbuf = read_object(the_repository, oid, &type, &len);\n \tif (!buf)\n \t\treturn error(_(\"cannot read object for %s\"), oid_to_hex(oid));\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(type), (uintmax_t)len) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type, len);\n \tret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);\n \tfree(buf);\n \ndiff --git a/object-store.h b/object-store.h\nindex 44f6868cc9c..8b4413d0ce7 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -331,6 +331,14 @@ int repo_has_object_file_with_flags(struct repository *r,\n  */\n int has_loose_object_nonlocal(const struct object_id *);\n \n+/**\n+ * format_object_header() is a thin wrapper around s xsnprintf() that\n+ * writes the initial \"<type> <obj-len>\" part of the loose object\n+ * header. It returns the size that snprintf() returns + 1.\n+ */\n+int format_object_header(char *str, size_t size, enum object_type type,\n+\t\t\t size_t objsize);\n+\n void assert_oid_type(const struct object_id *oid, enum object_type expect);\n \n /*\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447411","messageId":"patch-04.10-d6231ac68fe-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 04/10] object-file API: have write_object_file() take \"enum object_type\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:06Z","receivedAt":"2022-02-01T14:53:26Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the write_object_file() function to take an \"enum object_type\"\ninstead of a \"const char *type\". Its callers either passed\n{commit,tree,blob,tag}_type and can pass the corresponding OBJ_* type\ninstead, or were hardcoding strings like \"blob\".\n\nThis avoids the back & forth fragility where the callers of\nwrite_object_file() would have the enum type, and convert it\nthemselves via type_name(). We do have to now do that conversion\nourselves before calling write_object_file_prepare(), but those\ncodepaths will be similarly adjusted in subsequent commits.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n apply.c                  |  8 ++++----\n builtin/checkout.c       |  2 +-\n builtin/mktag.c          |  2 +-\n builtin/mktree.c         |  2 +-\n builtin/notes.c          |  3 +--\n builtin/receive-pack.c   |  2 +-\n builtin/replace.c        |  2 +-\n builtin/tag.c            |  2 +-\n builtin/unpack-objects.c |  6 +++---\n cache-tree.c             |  2 +-\n commit.c                 |  2 +-\n match-trees.c            |  2 +-\n merge-ort.c              |  4 ++--\n merge-recursive.c        |  2 +-\n notes-cache.c            |  2 +-\n notes.c                  |  8 ++++----\n object-file.c            | 10 +++++-----\n object-store.h           |  4 ++--\n read-cache.c             |  2 +-\n 19 files changed, 33 insertions(+), 34 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex 7ffadc3b17a..e82a7c30f01 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -3589,7 +3589,7 @@ static int try_threeway(struct apply_state *state,\n \n \t/* Preimage the patch was prepared for */\n \tif (patch->is_new)\n-\t\twrite_object_file(\"\", 0, blob_type, &pre_oid);\n+\t\twrite_object_file(\"\", 0, OBJ_BLOB, &pre_oid);\n \telse if (get_oid(patch->old_oid_prefix, &pre_oid) ||\n \t\t read_blob_object(&buf, &pre_oid, patch->old_mode))\n \t\treturn error(_(\"repository lacks the necessary blob to perform 3-way merge.\"));\n@@ -3605,7 +3605,7 @@ static int try_threeway(struct apply_state *state,\n \t\treturn -1;\n \t}\n \t/* post_oid is theirs */\n-\twrite_object_file(tmp_image.buf, tmp_image.len, blob_type, &post_oid);\n+\twrite_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &post_oid);\n \tclear_image(&tmp_image);\n \n \t/* our_oid is ours */\n@@ -3618,7 +3618,7 @@ static int try_threeway(struct apply_state *state,\n \t\t\treturn error(_(\"cannot read the current contents of '%s'\"),\n \t\t\t\t     patch->old_name);\n \t}\n-\twrite_object_file(tmp_image.buf, tmp_image.len, blob_type, &our_oid);\n+\twrite_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &our_oid);\n \tclear_image(&tmp_image);\n \n \t/* in-core three-way merge between post and our using pre as base */\n@@ -4346,7 +4346,7 @@ static int add_index_file(struct apply_state *state,\n \t\t\t}\n \t\t\tfill_stat_cache_info(state->repo->index, ce, &st);\n \t\t}\n-\t\tif (write_object_file(buf, size, blob_type, &ce->oid) < 0) {\n+\t\tif (write_object_file(buf, size, OBJ_BLOB, &ce->oid) < 0) {\n \t\t\tdiscard_cache_entry(ce);\n \t\t\treturn error(_(\"unable to create backing store \"\n \t\t\t\t       \"for newly created file %s\"), path);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex cc804ba8e1e..24cc235939f 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -298,7 +298,7 @@ static int checkout_merged(int pos, const struct checkout *state,\n \t * (it also writes the merge result to the object database even\n \t * when it may contain conflicts).\n \t */\n-\tif (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid))\n+\tif (write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &oid))\n \t\tdie(_(\"Unable to add merge result for '%s'\"), path);\n \tfree(result_buf.ptr);\n \tce = make_transient_cache_entry(mode, &oid, path, 2, ce_mem_pool);\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 3b2dbbb37e6..96a3686af53 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -100,7 +100,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)\n \tif (verify_object_in_tag(&tagged_oid, &tagged_type))\n \t\tdie(_(\"tag on stdin did not refer to a valid object\"));\n \n-\tif (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)\n+\tif (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0)\n \t\tdie(_(\"unable to write tag file\"));\n \n \tstrbuf_release(&buf);\ndiff --git a/builtin/mktree.c b/builtin/mktree.c\nindex ae78ca1c029..a1213aaa961 100644\n--- a/builtin/mktree.c\n+++ b/builtin/mktree.c\n@@ -58,7 +58,7 @@ static void write_tree(struct object_id *oid)\n \t\tstrbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz);\n \t}\n \n-\twrite_object_file(buf.buf, buf.len, tree_type, oid);\n+\twrite_object_file(buf.buf, buf.len, OBJ_TREE, oid);\n \tstrbuf_release(&buf);\n }\n \ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 05d60483e82..d81acaeaf78 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -199,9 +199,8 @@ static void prepare_note_data(const struct object_id *object, struct note_data *\n \n static void write_note_data(struct note_data *d, struct object_id *oid)\n {\n-\tif (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) {\n+\tif (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) {\n \t\tint status = die_message(_(\"unable to write note object\"));\n-\n \t\tif (d->edit_path)\n \t\t\tdie_message(_(\"the note contents have been left in %s\"),\n \t\t\t\t    d->edit_path);\ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 9f4a0b816cf..231d576927b 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -762,7 +762,7 @@ static void prepare_push_cert_sha1(struct child_process *proc)\n \t\tint bogs /* beginning_of_gpg_sig */;\n \n \t\talready_done = 1;\n-\t\tif (write_object_file(push_cert.buf, push_cert.len, \"blob\",\n+\t\tif (write_object_file(push_cert.buf, push_cert.len, OBJ_BLOB,\n \t\t\t\t      &push_cert_oid))\n \t\t\toidclr(&push_cert_oid);\n \ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 6ff1734d587..995ca683302 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -474,7 +474,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle)\n \t\treturn -1;\n \t}\n \n-\tif (write_object_file(buf.buf, buf.len, commit_type, &new_oid)) {\n+\tif (write_object_file(buf.buf, buf.len, OBJ_COMMIT, &new_oid)) {\n \t\tstrbuf_release(&buf);\n \t\treturn error(_(\"could not write replacement commit for: '%s'\"),\n \t\t\t     old_ref);\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 134b3f1edf0..31e6b155c04 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -238,7 +238,7 @@ static int build_tag_object(struct strbuf *buf, int sign, struct object_id *resu\n {\n \tif (sign && do_sign(buf) < 0)\n \t\treturn error(_(\"unable to sign the tag\"));\n-\tif (write_object_file(buf->buf, buf->len, tag_type, result) < 0)\n+\tif (write_object_file(buf->buf, buf->len, OBJ_TAG, result) < 0)\n \t\treturn error(_(\"unable to write tag file\"));\n \treturn 0;\n }\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 4a9466295ba..808041551fd 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -177,7 +177,7 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf)\n \tstruct object_id oid;\n \n \tif (write_object_file(obj_buf->buffer, obj_buf->size,\n-\t\t\t      type_name(obj->type), &oid) < 0)\n+\t\t\t      obj->type, &oid) < 0)\n \t\tdie(\"failed to write object %s\", oid_to_hex(&obj->oid));\n \tobj->flags |= FLAG_WRITTEN;\n }\n@@ -243,7 +243,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t\t\t void *buf, unsigned long size)\n {\n \tif (!strict) {\n-\t\tif (write_object_file(buf, size, type_name(type),\n+\t\tif (write_object_file(buf, size, type,\n \t\t\t\t      &obj_list[nr].oid) < 0)\n \t\t\tdie(\"failed to write object\");\n \t\tadded_object(nr, type, buf, size);\n@@ -251,7 +251,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t\tobj_list[nr].obj = NULL;\n \t} else if (type == OBJ_BLOB) {\n \t\tstruct blob *blob;\n-\t\tif (write_object_file(buf, size, type_name(type),\n+\t\tif (write_object_file(buf, size, type,\n \t\t\t\t      &obj_list[nr].oid) < 0)\n \t\t\tdie(\"failed to write object\");\n \t\tadded_object(nr, type, buf, size);\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 65ca9933613..fdbbd191d22 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -440,7 +440,7 @@ static int update_one(struct cache_tree *it,\n \t} else if (dryrun) {\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n \t\t\t\t tree_type, &it->oid);\n-\t} else if (write_object_file_flags(buffer.buf, buffer.len, tree_type,\n+\t} else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE,\n \t\t\t\t\t   &it->oid, flags & WRITE_TREE_SILENT\n \t\t\t\t\t   ? HASH_SILENT : 0)) {\n \t\tstrbuf_release(&buffer);\ndiff --git a/commit.c b/commit.c\nindex a348f085b2b..6cc0ba9c11b 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1567,7 +1567,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \t\tgoto out;\n \t}\n \n-\tresult = write_object_file(buffer.buf, buffer.len, commit_type, ret);\n+\tresult = write_object_file(buffer.buf, buffer.len, OBJ_COMMIT, ret);\n out:\n \tstrbuf_release(&buffer);\n \treturn result;\ndiff --git a/match-trees.c b/match-trees.c\nindex df413989fa8..49398e599fe 100644\n--- a/match-trees.c\n+++ b/match-trees.c\n@@ -235,7 +235,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,\n \t\trewrite_with = oid2;\n \t}\n \thashcpy(rewrite_here, rewrite_with->hash);\n-\tstatus = write_object_file(buf, sz, tree_type, result);\n+\tstatus = write_object_file(buf, sz, OBJ_TREE, result);\n \tfree(buf);\n \treturn status;\n }\ndiff --git a/merge-ort.c b/merge-ort.c\nindex c3197970219..d4ba2955f11 100644\n--- a/merge-ort.c\n+++ b/merge-ort.c\n@@ -1888,7 +1888,7 @@ static int handle_content_merge(struct merge_options *opt,\n \n \t\tif (!ret &&\n \t\t    write_object_file(result_buf.ptr, result_buf.size,\n-\t\t\t\t      blob_type, &result->oid))\n+\t\t\t\t      OBJ_BLOB, &result->oid))\n \t\t\tret = err(opt, _(\"Unable to add %s to database\"),\n \t\t\t\t  path);\n \n@@ -3343,7 +3343,7 @@ static void write_tree(struct object_id *result_oid,\n \t}\n \n \t/* Write this object file out, and record in result_oid */\n-\twrite_object_file(buf.buf, buf.len, tree_type, result_oid);\n+\twrite_object_file(buf.buf, buf.len, OBJ_TREE, result_oid);\n \tstrbuf_release(&buf);\n }\n \ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex d9457797dbb..e0cbbf2d022 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1373,7 +1373,7 @@ static int merge_mode_and_contents(struct merge_options *opt,\n \n \t\t\tif (!ret &&\n \t\t\t    write_object_file(result_buf.ptr, result_buf.size,\n-\t\t\t\t\t      blob_type, &result->blob.oid))\n+\t\t\t\t\t      OBJ_BLOB, &result->blob.oid))\n \t\t\t\tret = err(opt, _(\"Unable to add %s to database\"),\n \t\t\t\t\t  a->path);\n \ndiff --git a/notes-cache.c b/notes-cache.c\nindex 2473314d686..9dfd251a815 100644\n--- a/notes-cache.c\n+++ b/notes-cache.c\n@@ -92,7 +92,7 @@ int notes_cache_put(struct notes_cache *c, struct object_id *key_oid,\n {\n \tstruct object_id value_oid;\n \n-\tif (write_object_file(data, size, \"blob\", &value_oid) < 0)\n+\tif (write_object_file(data, size, OBJ_BLOB, &value_oid) < 0)\n \t\treturn -1;\n \treturn add_note(&c->tree, key_oid, &value_oid, NULL);\n }\ndiff --git a/notes.c b/notes.c\nindex f87dac40684..7452e71cc8d 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -675,7 +675,7 @@ static int tree_write_stack_finish_subtree(struct tree_write_stack *tws)\n \t\tret = tree_write_stack_finish_subtree(n);\n \t\tif (ret)\n \t\t\treturn ret;\n-\t\tret = write_object_file(n->buf.buf, n->buf.len, tree_type, &s);\n+\t\tret = write_object_file(n->buf.buf, n->buf.len, OBJ_TREE, &s);\n \t\tif (ret)\n \t\t\treturn ret;\n \t\tstrbuf_release(&n->buf);\n@@ -836,7 +836,7 @@ int combine_notes_concatenate(struct object_id *cur_oid,\n \tfree(new_msg);\n \n \t/* create a new blob object from buf */\n-\tret = write_object_file(buf, buf_len, blob_type, cur_oid);\n+\tret = write_object_file(buf, buf_len, OBJ_BLOB, cur_oid);\n \tfree(buf);\n \treturn ret;\n }\n@@ -916,7 +916,7 @@ int combine_notes_cat_sort_uniq(struct object_id *cur_oid,\n \t\t\t\t string_list_join_lines_helper, &buf))\n \t\tgoto out;\n \n-\tret = write_object_file(buf.buf, buf.len, blob_type, cur_oid);\n+\tret = write_object_file(buf.buf, buf.len, OBJ_BLOB, cur_oid);\n \n out:\n \tstrbuf_release(&buf);\n@@ -1192,7 +1192,7 @@ int write_notes_tree(struct notes_tree *t, struct object_id *result)\n \tret = for_each_note(t, flags, write_each_note, &cb_data) ||\n \t      write_each_non_note_until(NULL, &cb_data) ||\n \t      tree_write_stack_finish_subtree(&root) ||\n-\t      write_object_file(root.buf.buf, root.buf.len, tree_type, result);\n+\t      write_object_file(root.buf.buf, root.buf.len, OBJ_TREE, result);\n \tstrbuf_release(&root.buf);\n \treturn ret;\n }\ndiff --git a/object-file.c b/object-file.c\nindex 3fcd46cf9ed..59eb793e0ac 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2014,7 +2014,7 @@ static int freshen_packed_object(const struct object_id *oid)\n }\n \n int write_object_file_flags(const void *buf, unsigned long len,\n-\t\t\t    const char *type, struct object_id *oid,\n+\t\t\t    enum object_type type, struct object_id *oid,\n \t\t\t    unsigned flags)\n {\n \tchar hdr[MAX_HEADER_LEN];\n@@ -2023,7 +2023,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t/* Normally if we have it in the pack then we do not bother writing\n \t * it out into .git/objects/??/?{38} file.\n \t */\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr,\n+\twrite_object_file_prepare(the_hash_algo, buf, len, type_name(type), oid, hdr,\n \t\t\t\t  &hdrlen);\n \tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n \t\treturn 0;\n@@ -2162,7 +2162,7 @@ static int index_mem(struct index_state *istate,\n \t}\n \n \tif (write_object)\n-\t\tret = write_object_file(buf, size, type_name(type), oid);\n+\t\tret = write_object_file(buf, size, type, oid);\n \telse\n \t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n \t\t\t\t oid);\n@@ -2189,7 +2189,7 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\t\t\t get_conv_flags(flags));\n \n \tif (write_object)\n-\t\tret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB),\n+\t\tret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB,\n \t\t\t\t\toid);\n \telse\n \t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n@@ -2313,7 +2313,7 @@ int index_path(struct index_state *istate, struct object_id *oid,\n \t\tif (!(flags & HASH_WRITE_OBJECT))\n \t\t\thash_object_file(the_hash_algo, sb.buf, sb.len,\n \t\t\t\t\t blob_type, oid);\n-\t\telse if (write_object_file(sb.buf, sb.len, blob_type, oid))\n+\t\telse if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))\n \t\t\trc = error(_(\"%s: failed to insert into database\"), path);\n \t\tstrbuf_release(&sb);\n \t\tbreak;\ndiff --git a/object-store.h b/object-store.h\nindex 8b4413d0ce7..eab1e2a967e 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -250,10 +250,10 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \t\t      struct object_id *oid);\n \n int write_object_file_flags(const void *buf, unsigned long len,\n-\t\t\t    const char *type, struct object_id *oid,\n+\t\t\t    enum object_type type, struct object_id *oid,\n \t\t\t    unsigned flags);\n static inline int write_object_file(const void *buf, unsigned long len,\n-\t\t\t\t    const char *type, struct object_id *oid)\n+\t\t\t\t    enum object_type type, struct object_id *oid)\n {\n \treturn write_object_file_flags(buf, len, type, oid, 0);\n }\ndiff --git a/read-cache.c b/read-cache.c\nindex cbe73f14e5e..b8ae30a0e71 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -735,7 +735,7 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,\n void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)\n {\n \tstruct object_id oid;\n-\tif (write_object_file(\"\", 0, blob_type, &oid))\n+\tif (write_object_file(\"\", 0, OBJ_BLOB, &oid))\n \t\tdie(_(\"cannot create an empty blob in the object database\"));\n \toidcpy(&ce->oid, &oid);\n }\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447412","messageId":"patch-05.10-719fcfbe13c-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 05/10] object-file API: provide a hash_object_file_oideq()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:07Z","receivedAt":"2022-02-01T14:53:28Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Provide a new hash_object_file_oideq() for those callers of\ncheck_object_signature() that don't care about its streaming\ninterface. I.e. at the start of that function we do:\n\n\tif (map) {\n\t\thash_object_file(r->hash_algo, map, size, type, real_oid);\n\t\treturn !oideq(oid, real_oid) ? -1 : 0;\n\t}\n\nThese callers always provide a \"map\" (or \"buf[fer]\"). Let's have them\ncall this simpler hash_object_file_oideq() function instead.\n\nNone of them use a non-NULL \"real_oid\" argument, but let's provide it\nlike check_object_signature() did. This'll make it easy to have these\nemit better error messages in the future as was done in\n96e41f58fe1 (fsck: report invalid object type-path combinations,\n2021-10-01), i.e. the die() calls here can emit not only the OID we\nexpected, but also what we got.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/fast-export.c |  4 ++--\n builtin/index-pack.c  |  5 ++---\n builtin/mktag.c       |  5 ++---\n object-file.c         | 13 +++++++++++++\n object-store.h        | 14 ++++++++++++++\n object.c              |  4 ++--\n 6 files changed, 35 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex 9f1c730e587..f084da198c7 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -299,8 +299,8 @@ static void export_blob(const struct object_id *oid)\n \t\tbuf = read_object_file(oid, &type, &size);\n \t\tif (!buf)\n \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n-\t\tif (check_object_signature(the_repository, oid, buf, size,\n-\t\t\t\t\t   type_name(type), NULL) < 0)\n+\t\tif (!hash_object_file_oideq(the_repository->hash_algo, buf,\n+\t\t\t\t\t    size, type, oid, NULL))\n \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n \t\tobject = parse_object_buffer(the_repository, oid, type,\n \t\t\t\t\t     size, buf, &eaten);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 01574378ce2..5531a6d8bae 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1412,9 +1412,8 @@ static void fix_unresolved_deltas(struct hashfile *f)\n \t\tif (!data)\n \t\t\tcontinue;\n \n-\t\tif (check_object_signature(the_repository, &d->oid,\n-\t\t\t\t\t   data, size,\n-\t\t\t\t\t   type_name(type), NULL))\n+\t\tif (!hash_object_file_oideq(the_repository->hash_algo, data,\n+\t\t\t\t\t    size, type, &d->oid, NULL))\n \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n \n \t\t/*\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 96a3686af53..d8c7cf836b7 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -61,9 +61,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n \t\t    type_name(*tagged_type), type_name(type));\n \n \trepl = lookup_replace_object(the_repository, tagged_oid);\n-\tret = check_object_signature(the_repository, repl,\n-\t\t\t\t     buffer, size, type_name(*tagged_type),\n-\t\t\t\t     NULL);\n+\tret = !hash_object_file_oideq(the_repository->hash_algo, buffer, size,\n+\t\t\t\t      *tagged_type, repl, NULL);\n \tfree(buffer);\n \n \treturn ret;\ndiff --git a/object-file.c b/object-file.c\nindex 59eb793e0ac..27d10112960 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1862,6 +1862,19 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n+int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n+\t\t\t   unsigned long len, enum object_type type,\n+\t\t\t   const struct object_id *oid,\n+\t\t\t   struct object_id *real_oidp)\n+{\n+\tstruct object_id tmp;\n+\tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n+\n+\thash_object_file(algo, buf, len, type_name(type), real_oid);\n+\n+\treturn oideq(oid, real_oid);\n+}\n+\n /* Finalize a file on disk, and close it. */\n static void close_loose_object(int fd)\n {\ndiff --git a/object-store.h b/object-store.h\nindex eab1e2a967e..95907062682 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -249,6 +249,20 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \t\t      unsigned long len, const char *type,\n \t\t      struct object_id *oid);\n \n+/**\n+ * hash_object_file_oideq() is like hash_object_file() except that\n+ * asserts that \"real_oid\" is equivalent to an input \"oid\", and the\n+ * return value is that of oideq(oid, real_oid).\n+ *\n+ * The \"real_oid\" can be NULL, when non-NULL the caller provides a\n+ * \"struct object_id *\" that can be used to print what the real OID\n+ * was.\n+ */\n+int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n+\t\t\t   unsigned long len, enum object_type type,\n+\t\t\t   const struct object_id *oid,\n+\t\t\t   struct object_id *real_oidp);\n+\n int write_object_file_flags(const void *buf, unsigned long len,\n \t\t\t    enum object_type type, struct object_id *oid,\n \t\t\t    unsigned flags);\ndiff --git a/object.c b/object.c\nindex c37501fc120..d7673332582 100644\n--- a/object.c\n+++ b/object.c\n@@ -289,8 +289,8 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \n \tbuffer = repo_read_object_file(r, oid, &type, &size);\n \tif (buffer) {\n-\t\tif (check_object_signature(r, repl, buffer, size,\n-\t\t\t\t\t   type_name(type), NULL) < 0) {\n+\t\tif (!hash_object_file_oideq(r->hash_algo, buffer, size,\n+\t\t\t\t\t    type, repl, NULL)) {\n \t\t\tfree(buffer);\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n \t\t\treturn NULL;\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447413","messageId":"patch-06.10-2a065bf23da-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 06/10] object-file API: replace some use of check_object_signature()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:08Z","receivedAt":"2022-02-01T14:53:30Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a \"hash_object_file_literally()\" function to go with the existing\n\"hash_object_file()\" function. This is currently a wrapper for its\nsibling, but this change will allow us to change it to take an \"enum\nobject_type\" in a subsequent commit.\n\nThe only caller that wanted to pass a custom type to\n\"check_object_signature()\" was the \"git fsck\" via its\n\"read_loose_object()\", which is being changed here.\n\nThere was an existing hash_object_file_literally() which I'm renaming\nto \"hash_write_object_file_literally()\", that function is only used\nfor \"hash-object --literally\". That renaming is being done because it\nwould be confusing to have a \"hash_object_file_literally()\" and a\n\"hash_object_file()\" that do very different things.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/hash-object.c |  4 ++--\n object-file.c         | 18 +++++++++++++-----\n object-store.h        |  6 +++---\n 3 files changed, 18 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex c7b3ad74c60..624e9e677fb 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -25,8 +25,8 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig\n \tif (strbuf_read(&buf, fd, 4096) < 0)\n \t\tret = -1;\n \telse\n-\t\tret = hash_object_file_literally(buf.buf, buf.len, type, oid,\n-\t\t\t\t\t\t flags);\n+\t\tret = hash_write_object_file_literally(buf.buf, buf.len, type, oid,\n+\t\t\t\t\t\t       flags);\n \tstrbuf_release(&buf);\n \treturn ret;\n }\ndiff --git a/object-file.c b/object-file.c\nindex 27d10112960..9fc959fa05d 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1862,6 +1862,13 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n+static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf,\n+\t\t\t\t       unsigned long len, const char *type,\n+\t\t\t\t       struct object_id *oid)\n+{\n+\thash_object_file(algo, buf, len, type, oid);\n+}\n+\n int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n \t\t\t   unsigned long len, enum object_type type,\n \t\t\t   const struct object_id *oid,\n@@ -2043,9 +2050,9 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \treturn write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags);\n }\n \n-int hash_object_file_literally(const void *buf, unsigned long len,\n-\t\t\t       const char *type, struct object_id *oid,\n-\t\t\t       unsigned flags)\n+int hash_write_object_file_literally(const void *buf, unsigned long len,\n+\t\t\t\t     const char *type, struct object_id *oid,\n+\t\t\t\t     unsigned flags)\n {\n \tchar *header;\n \tint hdrlen, status = 0;\n@@ -2630,9 +2637,10 @@ int read_loose_object(const char *path,\n \t\t\tgit_inflate_end(&stream);\n \t\t\tgoto out;\n \t\t}\n-\t\tif (check_object_signature(the_repository, expected_oid,\n+\t\thash_object_file_literally(the_repository->hash_algo,\n \t\t\t\t\t   *contents, *size,\n-\t\t\t\t\t   oi->type_name->buf, real_oid))\n+\t\t\t\t\t   oi->type_name->buf, real_oid);\n+\t\tif (!oideq(expected_oid, real_oid))\n \t\t\tgoto out;\n \t}\n \ndiff --git a/object-store.h b/object-store.h\nindex 95907062682..2ddc20b3304 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -272,9 +272,9 @@ static inline int write_object_file(const void *buf, unsigned long len,\n \treturn write_object_file_flags(buf, len, type, oid, 0);\n }\n \n-int hash_object_file_literally(const void *buf, unsigned long len,\n-\t\t\t       const char *type, struct object_id *oid,\n-\t\t\t       unsigned flags);\n+int hash_write_object_file_literally(const void *buf, unsigned long len,\n+\t\t\t\t     const char *type, struct object_id *oid,\n+\t\t\t\t     unsigned flags);\n \n /*\n  * Add an object file to the in-memory object store, without writing it\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447414","messageId":"patch-08.10-70c3e84dd0d-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 08/10] object-file API: replace check_object_signature() with stream_*","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:10Z","receivedAt":"2022-02-01T14:53:35Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the task of the the check_object_signature() function so that\nit no longer confusingly does two unrelated things.\n\nNow the \"!map\" branch of it is exposed as a renamed\nstream_object_signature(). In preceding commits we migrated all of the\n\"if (map)\" callers over to \"hash_object_file_oideq()\" or\n\"hash_object_file_literally()\" followed by \"!oideq(...)\".\n\nThis makes the caller in parse_object() less confusing, as we'll now\nno longer need to pass NULL for \"map\" and \"OBJ_BAD\" for the unused\n\"type\" argument. The \"verify_packfile()\" caller is arguably a bit\nworse off than before, but as we're only using this function in a\ncouple of places now a bit more verbosity there is acceptable.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n cache.h       | 11 ++++++++---\n object-file.c | 17 +++--------------\n object.c      |  2 +-\n pack-check.c  |  8 ++++++--\n 4 files changed, 18 insertions(+), 20 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex d9c68c66d53..881ae36fd47 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1319,9 +1319,14 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,\n struct object_info;\n int parse_loose_header(const char *hdr, struct object_info *oi);\n \n-int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, enum object_type type,\n-\t\t\t   struct object_id *real_oidp);\n+\n+/**\n+ * stream_object_signature() tries to read the object named with \"oid\"\n+ * using the streaming interface and rehash it to make sure the object\n+ * name actually matches \"oid\" to detect object corruption.\n+ */\n+int stream_object_signature(struct repository *r, const struct object_id *oid,\n+\t\t\t    struct object_id *real_oidp);\n \n int finalize_object_file(const char *tmpfile, const char *filename);\n \ndiff --git a/object-file.c b/object-file.c\nindex 4a23a7aa79f..27f587d1dcd 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1066,29 +1066,18 @@ int format_object_header(char *str, size_t size, enum object_type type,\n \treturn format_object_header_literally(str, size, name, objsize);\n }\n \n-/*\n- * With an in-core object data in \"map\", rehash it to make sure the\n- * object name actually matches \"oid\" to detect object corruption.\n- * With \"map\" == NULL, try reading the object named with \"oid\" using\n- * the streaming interface and rehash it to do the same.\n- */\n-int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *map, unsigned long size, enum object_type type,\n-\t\t\t   struct object_id *real_oidp)\n+int stream_object_signature(struct repository *r, const struct object_id *oid,\n+\t\t\t    struct object_id *real_oidp)\n {\n \tstruct object_id tmp;\n \tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n+\tunsigned long size;\n \tenum object_type obj_type;\n \tstruct git_istream *st;\n \tgit_hash_ctx c;\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen;\n \n-\tif (map) {\n-\t\thash_object_file(r->hash_algo, map, size, type, real_oid);\n-\t\treturn !oideq(oid, real_oid) ? -1 : 0;\n-\t}\n-\n \tst = open_istream(r, oid, &obj_type, &size, NULL);\n \tif (!st)\n \t\treturn -1;\ndiff --git a/object.c b/object.c\nindex 795b1356a1b..bf51b2056e9 100644\n--- a/object.c\n+++ b/object.c\n@@ -279,7 +279,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n \t    (!obj && repo_has_object_file(r, oid) &&\n \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n-\t\tif (check_object_signature(r, repl, NULL, 0, OBJ_BAD, NULL) < 0) {\n+\t\tif (stream_object_signature(r, repl, NULL) < 0) {\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n \t\t\treturn NULL;\n \t\t}\ndiff --git a/pack-check.c b/pack-check.c\nindex faceae610d3..5d5169507ec 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -142,8 +142,12 @@ static int verify_packfile(struct repository *r,\n \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n \t\t\t\t    (uintmax_t)entries[i].offset);\n-\t\telse if (check_object_signature(r, &oid, data, size,\n-\t\t\t\t\t\ttype, NULL))\n+\t\telse if (data && !hash_object_file_oideq(r->hash_algo, data,\n+\t\t\t\t\t\t\t size, type, &oid,\n+\t\t\t\t\t\t\t NULL))\n+\t\t\terr = error(\"packed %s from %s is corrupt\",\n+\t\t\t\t    oid_to_hex(&oid), p->pack_name);\n+\t\telse if (!data && stream_object_signature(r, &oid, NULL))\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n \t\telse if (fn) {\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447415","messageId":"patch-07.10-ad5d94714cc-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 07/10] object-file API: have hash_object_file() take \"enum object_type\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:09Z","receivedAt":"2022-02-01T14:53:38Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the hash_object_file() function to take an \"enum\nobject_type\".\n\nAlmost all of its callers were passing either\n\"{commit,tree,blob,tag}_type\", or the result of a call to\ntype_name(). Let's instead benefit from type checking and use the enum\ndirectly.\n\n\"Almost\" because one caller here will now pass OBJ_BAD. The previous\n\"NULL\" value was not used, as \"check_object_signature()\" will never\nuse its \"type\" argument when given a NULL \"map\" argument, which that\ncaller in \"parse_object()\" also does. We'll deal with it in a\nsubsequent commit, but for now it'll pass an \"OBJ_BAD\" placeholder.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n apply.c                  |  4 ++--\n builtin/index-pack.c     |  2 +-\n builtin/replace.c        |  2 +-\n builtin/unpack-objects.c |  2 +-\n cache-tree.c             |  6 +++---\n cache.h                  |  2 +-\n convert.c                |  2 +-\n diffcore-rename.c        |  2 +-\n dir.c                    |  2 +-\n log-tree.c               |  2 +-\n object-file.c            | 26 ++++++++++++++------------\n object-store.h           |  3 ++-\n object.c                 |  2 +-\n pack-check.c             |  2 +-\n 14 files changed, 31 insertions(+), 28 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex e82a7c30f01..8513755e254 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -3157,7 +3157,7 @@ static int apply_binary(struct apply_state *state,\n \t\t * See if the old one matches what the patch\n \t\t * applies to.\n \t\t */\n-\t\thash_object_file(the_hash_algo, img->buf, img->len, blob_type,\n+\t\thash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,\n \t\t\t\t &oid);\n \t\tif (strcmp(oid_to_hex(&oid), patch->old_oid_prefix))\n \t\t\treturn error(_(\"the patch applies to '%s' (%s), \"\n@@ -3203,7 +3203,7 @@ static int apply_binary(struct apply_state *state,\n \t\t\t\t     name);\n \n \t\t/* verify that the result matches */\n-\t\thash_object_file(the_hash_algo, img->buf, img->len, blob_type,\n+\t\thash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,\n \t\t\t\t &oid);\n \t\tif (strcmp(oid_to_hex(&oid), patch->new_oid_prefix))\n \t\t\treturn error(_(\"binary patch to '%s' creates incorrect result (expecting %s, got %s)\"),\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 5531a6d8bae..4f2f4550e2e 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -970,7 +970,7 @@ static struct base_data *resolve_delta(struct object_entry *delta_obj,\n \tif (!result_data)\n \t\tbad_object(delta_obj->idx.offset, _(\"failed to apply delta\"));\n \thash_object_file(the_hash_algo, result_data, result_size,\n-\t\t\t type_name(delta_obj->real_type), &delta_obj->idx.oid);\n+\t\t\t delta_obj->real_type, &delta_obj->idx.oid);\n \tsha1_object(result_data, NULL, result_size, delta_obj->real_type,\n \t\t    &delta_obj->idx.oid);\n \ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 995ca683302..53a3b246570 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -409,7 +409,7 @@ static int check_one_mergetag(struct commit *commit,\n \tint i;\n \n \thash_object_file(the_hash_algo, extra->value, extra->len,\n-\t\t\t type_name(OBJ_TAG), &tag_oid);\n+\t\t\t OBJ_TAG, &tag_oid);\n \ttag = lookup_tag(the_repository, &tag_oid);\n \tif (!tag)\n \t\treturn error(_(\"bad mergetag in commit '%s'\"), ref);\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 808041551fd..dbeb0680a58 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -266,7 +266,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t} else {\n \t\tstruct object *obj;\n \t\tint eaten;\n-\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n+\t\thash_object_file(the_hash_algo, buf, size, type,\n \t\t\t\t &obj_list[nr].oid);\n \t\tadded_object(nr, type, buf, size);\n \t\tobj = parse_object_buffer(the_repository, &obj_list[nr].oid,\ndiff --git a/cache-tree.c b/cache-tree.c\nindex fdbbd191d22..6752f69d515 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -432,14 +432,14 @@ static int update_one(struct cache_tree *it,\n \tif (repair) {\n \t\tstruct object_id oid;\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n-\t\t\t\t tree_type, &oid);\n+\t\t\t\t OBJ_TREE, &oid);\n \t\tif (has_object_file_with_flags(&oid, OBJECT_INFO_SKIP_FETCH_OBJECT))\n \t\t\toidcpy(&it->oid, &oid);\n \t\telse\n \t\t\tto_invalidate = 1;\n \t} else if (dryrun) {\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n-\t\t\t\t tree_type, &it->oid);\n+\t\t\t\t OBJ_TREE, &it->oid);\n \t} else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE,\n \t\t\t\t\t   &it->oid, flags & WRITE_TREE_SILENT\n \t\t\t\t\t   ? HASH_SILENT : 0)) {\n@@ -948,7 +948,7 @@ static int verify_one(struct repository *r,\n \t\tstrbuf_addf(&tree_buf, \"%o %.*s%c\", mode, entlen, name, '\\0');\n \t\tstrbuf_add(&tree_buf, oid->hash, r->hash_algo->rawsz);\n \t}\n-\thash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, tree_type,\n+\thash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, OBJ_TREE,\n \t\t\t &new_oid);\n \tif (!oideq(&new_oid, &it->oid))\n \t\tBUG(\"cache-tree for path %.*s does not match. \"\ndiff --git a/cache.h b/cache.h\nindex 281f00ab1b1..d9c68c66d53 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1320,7 +1320,7 @@ struct object_info;\n int parse_loose_header(const char *hdr, struct object_info *oi);\n \n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type,\n+\t\t\t   void *buf, unsigned long size, enum object_type type,\n \t\t\t   struct object_id *real_oidp);\n \n int finalize_object_file(const char *tmpfile, const char *filename);\ndiff --git a/convert.c b/convert.c\nindex df7186bd813..d88072fe320 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -1159,7 +1159,7 @@ static int ident_to_worktree(const char *src, size_t len,\n \t/* are we \"faking\" in place editing ? */\n \tif (src == buf->buf)\n \t\tto_free = strbuf_detach(buf, NULL);\n-\thash_object_file(the_hash_algo, src, len, \"blob\", &oid);\n+\thash_object_file(the_hash_algo, src, len, OBJ_BLOB, &oid);\n \n \tstrbuf_grow(buf, len + cnt * (the_hash_algo->hexsz + 3));\n \tfor (;;) {\ndiff --git a/diffcore-rename.c b/diffcore-rename.c\nindex bebd4ed6a42..c0422d9e709 100644\n--- a/diffcore-rename.c\n+++ b/diffcore-rename.c\n@@ -261,7 +261,7 @@ static unsigned int hash_filespec(struct repository *r,\n \t\tif (diff_populate_filespec(r, filespec, NULL))\n \t\t\treturn 0;\n \t\thash_object_file(r->hash_algo, filespec->data, filespec->size,\n-\t\t\t\t \"blob\", &filespec->oid);\n+\t\t\t\t OBJ_BLOB, &filespec->oid);\n \t}\n \treturn oidhash(&filespec->oid);\n }\ndiff --git a/dir.c b/dir.c\nindex d91295f2bcd..5674e8a6256 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1113,7 +1113,7 @@ static int add_patterns(const char *fname, const char *base, int baselen,\n \t\t\t\t       &istate->cache[pos]->oid);\n \t\t\telse\n \t\t\t\thash_object_file(the_hash_algo, buf, size,\n-\t\t\t\t\t\t \"blob\", &oid_stat->oid);\n+\t\t\t\t\t\t OBJ_BLOB, &oid_stat->oid);\n \t\t\tfill_stat_data(&oid_stat->stat, &st);\n \t\t\toid_stat->valid = 1;\n \t\t}\ndiff --git a/log-tree.c b/log-tree.c\nindex d3e7a40b648..27a5b0bd61a 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -561,7 +561,7 @@ static int show_one_mergetag(struct commit *commit,\n \tstruct strbuf signature = STRBUF_INIT;\n \n \thash_object_file(the_hash_algo, extra->value, extra->len,\n-\t\t\t type_name(OBJ_TAG), &oid);\n+\t\t\t OBJ_TAG, &oid);\n \ttag = lookup_tag(the_repository, &oid);\n \tif (!tag)\n \t\treturn -1; /* error message already given */\ndiff --git a/object-file.c b/object-file.c\nindex 9fc959fa05d..4a23a7aa79f 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1073,7 +1073,7 @@ int format_object_header(char *str, size_t size, enum object_type type,\n  * the streaming interface and rehash it to do the same.\n  */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *map, unsigned long size, const char *type,\n+\t\t\t   void *map, unsigned long size, enum object_type type,\n \t\t\t   struct object_id *real_oidp)\n {\n \tstruct object_id tmp;\n@@ -1679,7 +1679,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,\n {\n \tstruct cached_object *co;\n \n-\thash_object_file(the_hash_algo, buf, len, type_name(type), oid);\n+\thash_object_file(the_hash_algo, buf, len, type, oid);\n \tif (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) ||\n \t    find_cached_object(oid))\n \t\treturn 0;\n@@ -1854,19 +1854,23 @@ static int write_buffer(int fd, const void *buf, size_t len)\n }\n \n void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t     unsigned long len, const char *type,\n+\t\t     unsigned long len, enum object_type type,\n \t\t     struct object_id *oid)\n {\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n-\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n+\n+\twrite_object_file_prepare(algo, buf, len, type_name(type), oid, hdr, &hdrlen);\n }\n \n static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf,\n \t\t\t\t       unsigned long len, const char *type,\n \t\t\t\t       struct object_id *oid)\n {\n-\thash_object_file(algo, buf, len, type, oid);\n+\tchar hdr[MAX_HEADER_LEN];\n+\tint hdrlen = sizeof(hdr);\n+\n+\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n@@ -1877,7 +1881,7 @@ int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n \tstruct object_id tmp;\n \tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n \n-\thash_object_file(algo, buf, len, type_name(type), real_oid);\n+\thash_object_file(algo, buf, len, type, real_oid);\n \n \treturn oideq(oid, real_oid);\n }\n@@ -2184,9 +2188,7 @@ static int index_mem(struct index_state *istate,\n \tif (write_object)\n \t\tret = write_object_file(buf, size, type, oid);\n \telse\n-\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n-\t\t\t\t oid);\n-\n+\t\thash_object_file(the_hash_algo, buf, size, type, oid);\n \tif (re_allocated)\n \t\tfree(buf);\n \treturn ret;\n@@ -2212,8 +2214,8 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\tret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB,\n \t\t\t\t\toid);\n \telse\n-\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n-\t\t\t\t type_name(OBJ_BLOB), oid);\n+\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len, OBJ_BLOB,\n+\t\t\t\t oid);\n \tstrbuf_release(&sbuf);\n \treturn ret;\n }\n@@ -2332,7 +2334,7 @@ int index_path(struct index_state *istate, struct object_id *oid,\n \t\t\treturn error_errno(\"readlink(\\\"%s\\\")\", path);\n \t\tif (!(flags & HASH_WRITE_OBJECT))\n \t\t\thash_object_file(the_hash_algo, sb.buf, sb.len,\n-\t\t\t\t\t blob_type, oid);\n+\t\t\t\t\t OBJ_BLOB, oid);\n \t\telse if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))\n \t\t\trc = error(_(\"%s: failed to insert into database\"), path);\n \t\tstrbuf_release(&sb);\ndiff --git a/object-store.h b/object-store.h\nindex 2ddc20b3304..719122f047f 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -245,8 +245,9 @@ static inline void *repo_read_object_file(struct repository *r,\n /* Read and unpack an object file into memory, write memory to an object file */\n int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);\n \n+\n void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t      unsigned long len, const char *type,\n+\t\t      unsigned long len, enum object_type type,\n \t\t      struct object_id *oid);\n \n /**\ndiff --git a/object.c b/object.c\nindex d7673332582..795b1356a1b 100644\n--- a/object.c\n+++ b/object.c\n@@ -279,7 +279,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n \t    (!obj && repo_has_object_file(r, oid) &&\n \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n-\t\tif (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) {\n+\t\tif (check_object_signature(r, repl, NULL, 0, OBJ_BAD, NULL) < 0) {\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n \t\t\treturn NULL;\n \t\t}\ndiff --git a/pack-check.c b/pack-check.c\nindex 3f418e3a6af..faceae610d3 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -143,7 +143,7 @@ static int verify_packfile(struct repository *r,\n \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n \t\t\t\t    (uintmax_t)entries[i].offset);\n \t\telse if (check_object_signature(r, &oid, data, size,\n-\t\t\t\t\t\ttype_name(type), NULL))\n+\t\t\t\t\t\ttype, NULL))\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n \t\telse if (fn) {\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447416","messageId":"patch-09.10-009b6604d6f-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 09/10] object-file.c: add a literal version of write_object_file_prepare()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:11Z","receivedAt":"2022-02-01T14:53:39Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split off a *_literally() variant of the write_object_file_prepare()\nfunction. To do this create a new \"hash_object_body()\" static helper.\n\nWe now defer the type_name() call until the very last moment in\nformat_object_header() for those callers that aren't \"hash-object\n--literally\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c | 41 ++++++++++++++++++++++++++++++-----------\n 1 file changed, 30 insertions(+), 11 deletions(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex 27f587d1dcd..0a6d56db39f 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1775,21 +1775,40 @@ void *read_object_with_reference(struct repository *r,\n \t}\n }\n \n+static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c,\n+\t\t\t     const void *buf, unsigned long len,\n+\t\t\t     struct object_id *oid,\n+\t\t\t     char *hdr, int *hdrlen)\n+{\n+\talgo->init_fn(c);\n+\talgo->update_fn(c, hdr, *hdrlen);\n+\talgo->update_fn(c, buf, len);\n+\talgo->final_oid_fn(oid, c);\n+}\n+\n static void write_object_file_prepare(const struct git_hash_algo *algo,\n \t\t\t\t      const void *buf, unsigned long len,\n-\t\t\t\t      const char *type, struct object_id *oid,\n+\t\t\t\t      enum object_type type, struct object_id *oid,\n \t\t\t\t      char *hdr, int *hdrlen)\n {\n \tgit_hash_ctx c;\n \n \t/* Generate the header */\n-\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n+\t*hdrlen = format_object_header(hdr, *hdrlen, type, len);\n \n \t/* Sha1.. */\n-\talgo->init_fn(&c);\n-\talgo->update_fn(&c, hdr, *hdrlen);\n-\talgo->update_fn(&c, buf, len);\n-\talgo->final_oid_fn(oid, &c);\n+\thash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);\n+}\n+\n+static void write_object_file_prepare_literally(const struct git_hash_algo *algo,\n+\t\t\t\t      const void *buf, unsigned long len,\n+\t\t\t\t      const char *type, struct object_id *oid,\n+\t\t\t\t      char *hdr, int *hdrlen)\n+{\n+\tgit_hash_ctx c;\n+\n+\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n+\thash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);\n }\n \n /*\n@@ -1849,7 +1868,7 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n \n-\twrite_object_file_prepare(algo, buf, len, type_name(type), oid, hdr, &hdrlen);\n+\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf,\n@@ -1859,7 +1878,7 @@ static void hash_object_file_literally(const struct git_hash_algo *algo, const v\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n \n-\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n+\twrite_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n@@ -2036,7 +2055,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t/* Normally if we have it in the pack then we do not bother writing\n \t * it out into .git/objects/??/?{38} file.\n \t */\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type_name(type), oid, hdr,\n+\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr,\n \t\t\t\t  &hdrlen);\n \tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n \t\treturn 0;\n@@ -2053,8 +2072,8 @@ int hash_write_object_file_literally(const void *buf, unsigned long len,\n \t/* type string, SP, %lu of the length plus NUL must fit this */\n \thdrlen = strlen(type) + MAX_HEADER_LEN;\n \theader = xmalloc(hdrlen);\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, header,\n-\t\t\t\t  &hdrlen);\n+\twrite_object_file_prepare_literally(the_hash_algo, buf, len, type,\n+\t\t\t\t\t    oid, header, &hdrlen);\n \n \tif (!(flags & HASH_WRITE_OBJECT))\n \t\tgoto cleanup;\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447417","messageId":"patch-10.10-d89fe344c70-20220201T144803Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH 10/10] object-file API: pass an enum to read_object_with_reference()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T14:53:12Z","receivedAt":"2022-02-01T14:53:41Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the read_object_with_reference() function to take an \"enum\nobject_type\". It was not prepared to handle an arbitrary \"const\nchar *type\", as it was itself calling type_from_string().\n\nLet's change the only caller that passes in user data to use\ntype_from_string(), and convert the rest to use e.g. \"OBJ_TREE\"\ninstead of \"tree_type\".\n\nThe \"cat-file\" caller is not on the codepath that\nhandles\"--allow-unknown\", so the type_from_string() there is safe. Its\nuse of type_from_string() doesn't functionally differ from that of the\npre-image.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/cat-file.c     | 11 +++++++----\n builtin/fast-import.c  |  6 +++---\n builtin/grep.c         |  4 ++--\n builtin/pack-objects.c |  2 +-\n cache.h                |  2 +-\n object-file.c          |  5 ++---\n tree-walk.c            |  6 +++---\n 7 files changed, 19 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex d94050e6c18..3c5bc505e0a 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -154,7 +154,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\tbreak;\n \n \tcase 0:\n-\t\tif (type_from_string(exp_type) == OBJ_BLOB) {\n+\t{\n+\t\tenum object_type exp_type_id = type_from_string(exp_type);\n+\n+\t\tif (exp_type_id == OBJ_BLOB) {\n \t\t\tstruct object_id blob_oid;\n \t\t\tif (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) {\n \t\t\t\tchar *buffer = read_object_file(&oid, &type,\n@@ -176,10 +179,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\t\t * fall-back to the usual case.\n \t\t\t */\n \t\t}\n-\t\tbuf = read_object_with_reference(the_repository,\n-\t\t\t\t\t\t &oid, exp_type, &size, NULL);\n+\t\tbuf = read_object_with_reference(the_repository, &oid,\n+\t\t\t\t\t\t exp_type_id, &size, NULL);\n \t\tbreak;\n-\n+\t}\n \tdefault:\n \t\tdie(\"git cat-file: unknown option: %s\", exp_type);\n \t}\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 123df7d9a53..c52e807f56e 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -2483,7 +2483,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa\n \t\tunsigned long size;\n \t\tchar *buf = read_object_with_reference(the_repository,\n \t\t\t\t\t\t       &commit_oid,\n-\t\t\t\t\t\t       commit_type, &size,\n+\t\t\t\t\t\t       OBJ_COMMIT, &size,\n \t\t\t\t\t\t       &commit_oid);\n \t\tif (!buf || size < the_hash_algo->hexsz + 6)\n \t\t\tdie(\"Not a valid commit: %s\", p);\n@@ -2555,7 +2555,7 @@ static void parse_from_existing(struct branch *b)\n \t\tchar *buf;\n \n \t\tbuf = read_object_with_reference(the_repository,\n-\t\t\t\t\t\t &b->oid, commit_type, &size,\n+\t\t\t\t\t\t &b->oid, OBJ_COMMIT, &size,\n \t\t\t\t\t\t &b->oid);\n \t\tparse_from_commit(b, buf, size);\n \t\tfree(buf);\n@@ -2651,7 +2651,7 @@ static struct hash_list *parse_merge(unsigned int *count)\n \t\t\tunsigned long size;\n \t\t\tchar *buf = read_object_with_reference(the_repository,\n \t\t\t\t\t\t\t       &n->oid,\n-\t\t\t\t\t\t\t       commit_type,\n+\t\t\t\t\t\t\t       OBJ_COMMIT,\n \t\t\t\t\t\t\t       &size, &n->oid);\n \t\t\tif (!buf || size < the_hash_algo->hexsz + 6)\n \t\t\t\tdie(\"Not a valid commit: %s\", from);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 9e34a820ad4..75e07b5623a 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t\tobject_type = oid_object_info(subrepo, oid, NULL);\n \t\tobj_read_unlock();\n \t\tdata = read_object_with_reference(subrepo,\n-\t\t\t\t\t\t  oid, tree_type,\n+\t\t\t\t\t\t  oid, OBJ_TREE,\n \t\t\t\t\t\t  &size, NULL);\n \t\tif (!data)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(oid));\n@@ -651,7 +651,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,\n \t\tint hit, len;\n \n \t\tdata = read_object_with_reference(opt->repo,\n-\t\t\t\t\t\t  &obj->oid, tree_type,\n+\t\t\t\t\t\t  &obj->oid, OBJ_TREE,\n \t\t\t\t\t\t  &size, NULL);\n \t\tif (!data)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(&obj->oid));\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex ba2006f2212..c4df3df3141 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1802,7 +1802,7 @@ static void add_preferred_base(struct object_id *oid)\n \t\treturn;\n \n \tdata = read_object_with_reference(the_repository, oid,\n-\t\t\t\t\t  tree_type, &size, &tree_oid);\n+\t\t\t\t\t  OBJ_TREE, &size, &tree_oid);\n \tif (!data)\n \t\treturn;\n \ndiff --git a/cache.h b/cache.h\nindex 881ae36fd47..92da61ef47a 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1552,7 +1552,7 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char\n \n void *read_object_with_reference(struct repository *r,\n \t\t\t\t const struct object_id *oid,\n-\t\t\t\t const char *required_type,\n+\t\t\t\t enum object_type required_type,\n \t\t\t\t unsigned long *size,\n \t\t\t\t struct object_id *oid_ret);\n \ndiff --git a/object-file.c b/object-file.c\nindex 0a6d56db39f..6c6e21ccc92 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1728,16 +1728,15 @@ void *read_object_file_extended(struct repository *r,\n \n void *read_object_with_reference(struct repository *r,\n \t\t\t\t const struct object_id *oid,\n-\t\t\t\t const char *required_type_name,\n+\t\t\t\t enum object_type required_type,\n \t\t\t\t unsigned long *size,\n \t\t\t\t struct object_id *actual_oid_return)\n {\n-\tenum object_type type, required_type;\n+\tenum object_type type;\n \tvoid *buffer;\n \tunsigned long isize;\n \tstruct object_id actual_oid;\n \n-\trequired_type = type_from_string(required_type_name);\n \toidcpy(&actual_oid, oid);\n \twhile (1) {\n \t\tint ref_length = -1;\ndiff --git a/tree-walk.c b/tree-walk.c\nindex 3a94959d64a..506234b4b81 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -89,7 +89,7 @@ void *fill_tree_descriptor(struct repository *r,\n \tvoid *buf = NULL;\n \n \tif (oid) {\n-\t\tbuf = read_object_with_reference(r, oid, tree_type, &size, NULL);\n+\t\tbuf = read_object_with_reference(r, oid, OBJ_TREE, &size, NULL);\n \t\tif (!buf)\n \t\t\tdie(\"unable to read tree %s\", oid_to_hex(oid));\n \t}\n@@ -605,7 +605,7 @@ int get_tree_entry(struct repository *r,\n \tunsigned long size;\n \tstruct object_id root;\n \n-\ttree = read_object_with_reference(r, tree_oid, tree_type, &size, &root);\n+\ttree = read_object_with_reference(r, tree_oid, OBJ_TREE, &size, &root);\n \tif (!tree)\n \t\treturn -1;\n \n@@ -677,7 +677,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r,\n \t\t\tunsigned long size;\n \t\t\ttree = read_object_with_reference(r,\n \t\t\t\t\t\t\t  &current_tree_oid,\n-\t\t\t\t\t\t\t  tree_type, &size,\n+\t\t\t\t\t\t\t  OBJ_TREE, &size,\n \t\t\t\t\t\t\t  &root);\n \t\t\tif (!tree)\n \t\t\t\tgoto done;\n-- \n2.35.0.913.g12b4baa2536\n\n"},{"id":"447444","messageId":"xmqqczk6e7m7.fsf@gitster.g","threadId":"57347","inReplyTo":"patch-04.10-d6231ac68fe-20220201T144803Z-avarab@gmail.com","subject":"Re: [PATCH 04/10] object-file API: have write_object_file() take \"enum object_type\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-02-01T18:58:56Z","receivedAt":"2022-02-01T18:59:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Change the write_object_file() function to take an \"enum object_type\"\n> instead of a \"const char *type\". Its callers either passed\n> {commit,tree,blob,tag}_type and can pass the corresponding OBJ_* type\n> instead, or were hardcoding strings like \"blob\".\n>\n> This avoids the back & forth fragility where the callers of\n> write_object_file() would have the enum type, and convert it\n> themselves via type_name(). We do have to now do that conversion\n> ourselves before calling write_object_file_prepare(), but those\n> codepaths will be similarly adjusted in subsequent commits.\n\nUp to this point, the series makes sense to me (I didn't check for\ncalls that were left uncoverted by mistake, or new callers that were\nadded on other topics---the compiler should flag them all).\n\n\n"},{"id":"447445","messageId":"xmqq5ypye767.fsf@gitster.g","threadId":"57347","inReplyTo":"patch-05.10-719fcfbe13c-20220201T144803Z-avarab@gmail.com","subject":"Re: [PATCH 05/10] object-file API: provide a hash_object_file_oideq()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-02-01T19:08:32Z","receivedAt":"2022-02-01T19:08:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Provide a new hash_object_file_oideq() for those callers of\n> check_object_signature() that don't care about its streaming\n> interface. I.e. at the start of that function we do:\n>\n> \tif (map) {\n> \t\thash_object_file(r->hash_algo, map, size, type, real_oid);\n> \t\treturn !oideq(oid, real_oid) ? -1 : 0;\n> \t}\n>\n> These callers always provide a \"map\" (or \"buf[fer]\"). Let's have them\n> call this simpler hash_object_file_oideq() function instead.\n>\n> None of them use a non-NULL \"real_oid\" argument, but let's provide it\n> like check_object_signature() did. This'll make it easy to have these\n> emit better error messages in the future as was done in\n> 96e41f58fe1 (fsck: report invalid object type-path combinations,\n> 2021-10-01), i.e. the die() calls here can emit not only the OID we\n> expected, but also what we got.\n\nThis has a potential to moving us in the wrong direction when made\nto code paths that currently fully slurp an object in-core but may\nwant to shrink the memory footprint by using streaming API more.\n\nHaving said that, I think all of these want to also use the in-core\nversion of hte object data (mostly to write them out), and they need\nmore work to move them in the other direction, so I'd say it is OK\nto introduce the new helper to simplify these callsites.\n"},{"id":"447446","messageId":"xmqqy22ucs7q.fsf@gitster.g","threadId":"57347","inReplyTo":"patch-06.10-2a065bf23da-20220201T144803Z-avarab@gmail.com","subject":"Re: [PATCH 06/10] object-file API: replace some use of check_object_signature()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-02-01T19:16:57Z","receivedAt":"2022-02-01T19:17:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Add a \"hash_object_file_literally()\" function to go with the existing\n> \"hash_object_file()\" function. This is currently a wrapper for its\n> sibling, but this change will allow us to change it to take an \"enum\n> object_type\" in a subsequent commit.\n\nThis is a confusing renaming, because there is already a public\nfunction that exists under that name.  And with this implementation,\n...\n\n> +static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf,\n> +\t\t\t\t       unsigned long len, const char *type,\n> +\t\t\t\t       struct object_id *oid)\n> +{\n> +\thash_object_file(algo, buf, len, type, oid);\n> +}\n\n... it is dubious why we need it.\n\n> -int hash_object_file_literally(const void *buf, unsigned long len,\n> -\t\t\t       const char *type, struct object_id *oid,\n> -\t\t\t       unsigned flags)\n> +int hash_write_object_file_literally(const void *buf, unsigned long len,\n> +\t\t\t\t     const char *type, struct object_id *oid,\n> +\t\t\t\t     unsigned flags)\n\nThis renaming is actually OK, if hash_object_file() which is also\npublic is renamed to hash_write_object_file() at the same time.\n\nBut I would say we should try to avoid such name churn to the public\nnamespace.\n"},{"id":"447460","messageId":"220201.86ee4m9ue5.gmgdl@evledraar.gmail.com","threadId":"57347","inReplyTo":"xmqq5ypye767.fsf@gitster.g","subject":"Re: [PATCH 05/10] object-file API: provide a hash_object_file_oideq()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-01T20:56:51Z","receivedAt":"2022-02-01T20:58:15Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Feb 01 2022, Junio C Hamano wrote:\n\n> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n>\n>> Provide a new hash_object_file_oideq() for those callers of\n>> check_object_signature() that don't care about its streaming\n>> interface. I.e. at the start of that function we do:\n>>\n>> \tif (map) {\n>> \t\thash_object_file(r->hash_algo, map, size, type, real_oid);\n>> \t\treturn !oideq(oid, real_oid) ? -1 : 0;\n>> \t}\n>>\n>> These callers always provide a \"map\" (or \"buf[fer]\"). Let's have them\n>> call this simpler hash_object_file_oideq() function instead.\n>>\n>> None of them use a non-NULL \"real_oid\" argument, but let's provide it\n>> like check_object_signature() did. This'll make it easy to have these\n>> emit better error messages in the future as was done in\n>> 96e41f58fe1 (fsck: report invalid object type-path combinations,\n>> 2021-10-01), i.e. the die() calls here can emit not only the OID we\n>> expected, but also what we got.\n>\n> This has a potential to moving us in the wrong direction when made\n> to code paths that currently fully slurp an object in-core but may\n> want to shrink the memory footprint by using streaming API more.\n>\n> Having said that, I think all of these want to also use the in-core\n> version of hte object data (mostly to write them out), and they need\n> more work to move them in the other direction, so I'd say it is OK\n> to introduce the new helper to simplify these callsites.\n\nYes, I'm avoiding any value-judgement on whether the callers that use\nthese APIs should or shouldn't be using something else.\n\nBut I think as the end-state shows splitting apart the two very\ndifferent API users that do and don't provide the \"map\" parameter makes\nsense. We're effectively calling two different functions in all but name\nbefore this change.\n"},{"id":"447727","messageId":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com","subject":"[PATCH v2 00/11] object-file API: pass object enums, tidy up streaming interface","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:14Z","receivedAt":"2022-02-04T13:51:36Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"This is a topic to prepare APIs for Han Xin's streaming \"git\nunpack-objects\" topic, which I'll be re-rolling on top of this with\nhis approval[1].\n\nSince v1 of this topic[2] I've thoroughly addressed the feedback Junio\nhad on it. I was introducing some new object-name.c APIs for reasons\nthat turned out to be that I was making things too complex, by doing\nthe \"enum\" step in-between several incremental updates to\ncheck_object_signature() and its callers.\n\nThat's now a much simpler 05-07/11, with the changing of the API users\nbeing one atomic change.\n\nI also made some other amendmends to reduce the diff size, e.g. not\nmoving the check_object_signature() prototype from cache.h to\nobject-store.h (a sensible change, but can be done in some other\ncleanup).\n\n1. https://lore.kernel.org/git/CAO0brD2Pe0aKSiBphZS861gC=nZk+q2GtXDN4pPjAQnPdns3TA@mail.gmail.com/\n2. https://lore.kernel.org/git/cover-00.10-00000000000-20220201T144803Z-avarab@gmail.com/\n\nÆvar Arnfjörð Bjarmason (11):\n  object-file.c: split up declaration of unrelated variables\n  object-file API: return \"void\", not \"int\" from hash_object_file()\n  object-file API: add a format_object_header() function\n  object-file API: have write_object_file() take \"enum object_type\"\n  object API: correct \"buf\" v.s. \"map\" mismatch in *.c and *.h\n  object API: make check_object_signature() oideq()-like, move docs\n  object-file API: split up and simplify check_object_signature()\n  object API: rename hash_object_file_literally() to write_*()\n  object-file API: have hash_object_file() take \"enum object_type\"\n  object-file.c: add a literal version of write_object_file_prepare()\n  object-file API: pass an enum to read_object_with_reference()\n\n apply.c                  |  12 ++--\n builtin/cat-file.c       |  11 +--\n builtin/checkout.c       |   2 +-\n builtin/fast-export.c    |   4 +-\n builtin/fast-import.c    |  12 ++--\n builtin/grep.c           |   4 +-\n builtin/hash-object.c    |   2 +-\n builtin/index-pack.c     |  10 ++-\n builtin/mktag.c          |   7 +-\n builtin/mktree.c         |   2 +-\n builtin/notes.c          |   3 +-\n builtin/pack-objects.c   |   2 +-\n builtin/receive-pack.c   |   2 +-\n builtin/replace.c        |   4 +-\n builtin/tag.c            |   2 +-\n builtin/unpack-objects.c |   8 +--\n bulk-checkin.c           |   4 +-\n cache-tree.c             |   8 +--\n cache.h                  |  20 +++++-\n commit.c                 |   2 +-\n convert.c                |   2 +-\n diffcore-rename.c        |   2 +-\n dir.c                    |   2 +-\n http-push.c              |   2 +-\n log-tree.c               |   2 +-\n match-trees.c            |   2 +-\n merge-ort.c              |   4 +-\n merge-recursive.c        |   2 +-\n notes-cache.c            |   2 +-\n notes.c                  |   8 +--\n object-file.c            | 146 +++++++++++++++++++++++++--------------\n object-store.h           |  24 ++++---\n object.c                 |   5 +-\n pack-check.c             |   9 ++-\n read-cache.c             |   2 +-\n tree-walk.c              |   6 +-\n 36 files changed, 203 insertions(+), 138 deletions(-)\n\nRange-diff against v1:\n 1:  53334bc970a =  1:  53334bc970a object-file.c: split up declaration of unrelated variables\n 2:  ab1d204f49b =  2:  5ba49778ac1 object-file API: return \"void\", not \"int\" from hash_object_file()\n 3:  64484e046ea =  3:  92fd020d199 object-file API: add a format_object_header() function\n 4:  d6231ac68fe =  4:  d259f901114 object-file API: have write_object_file() take \"enum object_type\"\n -:  ----------- >  5:  207aec4eb64 object API: correct \"buf\" v.s. \"map\" mismatch in *.c and *.h\n 5:  719fcfbe13c !  6:  636a647ac51 object-file API: provide a hash_object_file_oideq()\n    @@ Metadata\n     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n      ## Commit message ##\n    -    object-file API: provide a hash_object_file_oideq()\n    +    object API: make check_object_signature() oideq()-like, move docs\n     \n    -    Provide a new hash_object_file_oideq() for those callers of\n    -    check_object_signature() that don't care about its streaming\n    -    interface. I.e. at the start of that function we do:\n    +    Make the return value of check_object_signature() behave like oideq()\n    +    and memcmp() instead of returning negative values on failure.\n     \n    -            if (map) {\n    -                    hash_object_file(r->hash_algo, map, size, type, real_oid);\n    -                    return !oideq(oid, real_oid) ? -1 : 0;\n    -            }\n    +    This reduces the boilerplate required when calling the function, and\n    +    makes the calling code behave the same is if though we'd called\n    +    oideq(), which is basically what we're doing here. We already had some\n    +    callers using \"f() < 0\", with others using \"!f()\". Instead of\n    +    declaring the latter a bug let's convert all callers to it.\n     \n    -    These callers always provide a \"map\" (or \"buf[fer]\"). Let's have them\n    -    call this simpler hash_object_file_oideq() function instead.\n    +    It is unfortunate that there's also cases where we \"return -1\" on\n    +    various errors, and we can't tell those apart from the expected OID\n    +    being less than the real OID, but this was the case already.\n     \n    -    None of them use a non-NULL \"real_oid\" argument, but let's provide it\n    -    like check_object_signature() did. This'll make it easy to have these\n    -    emit better error messages in the future as was done in\n    -    96e41f58fe1 (fsck: report invalid object type-path combinations,\n    -    2021-10-01), i.e. the die() calls here can emit not only the OID we\n    -    expected, but also what we got.\n    +    This change is rather dangerous stand-alone as we're changing the\n    +    return semantics, but not changing the prototype. Therefore any\n    +    out-of-tree code rebased on this change would start doing the opposite\n    +    of what it was meant to do. In a subsequent commit we'll make that a\n    +    non-issue by changing the signature of the function, ensuring that the\n    +    compiler will catch any such misuse.\n    +\n    +    While we're at it let's re-flow some of the callers to wrap at 79\n    +    characters, and move the API documentation to cache.h, where the\n    +    prototype of this function lives.\n     \n         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n    @@ builtin/fast-export.c: static void export_blob(const struct object_id *oid)\n      \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n     -\t\tif (check_object_signature(the_repository, oid, buf, size,\n     -\t\t\t\t\t   type_name(type), NULL) < 0)\n    -+\t\tif (!hash_object_file_oideq(the_repository->hash_algo, buf,\n    -+\t\t\t\t\t    size, type, oid, NULL))\n    ++\t\tif (!check_object_signature(the_repository, oid, buf, size,\n    ++\t\t\t\t\t    type_name(type), NULL))\n      \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n      \t\tobject = parse_object_buffer(the_repository, oid, type,\n      \t\t\t\t\t     size, buf, &eaten);\n    @@ builtin/index-pack.c: static void fix_unresolved_deltas(struct hashfile *f)\n     -\t\tif (check_object_signature(the_repository, &d->oid,\n     -\t\t\t\t\t   data, size,\n     -\t\t\t\t\t   type_name(type), NULL))\n    -+\t\tif (!hash_object_file_oideq(the_repository->hash_algo, data,\n    -+\t\t\t\t\t    size, type, &d->oid, NULL))\n    ++\t\tif (!check_object_signature(the_repository, &d->oid, data,\n    ++\t\t\t\t\t    size, type_name(type), NULL))\n      \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n      \n      \t\t/*\n    @@ builtin/mktag.c: static int verify_object_in_tag(struct object_id *tagged_oid, i\n     -\tret = check_object_signature(the_repository, repl,\n     -\t\t\t\t     buffer, size, type_name(*tagged_type),\n     -\t\t\t\t     NULL);\n    -+\tret = !hash_object_file_oideq(the_repository->hash_algo, buffer, size,\n    -+\t\t\t\t      *tagged_type, repl, NULL);\n    ++\tret = !check_object_signature(the_repository, repl, buffer, size,\n    ++\t\t\t\t      type_name(*tagged_type), NULL);\n      \tfree(buffer);\n      \n      \treturn ret;\n     \n    + ## cache.h ##\n    +@@ cache.h: enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,\n    + struct object_info;\n    + int parse_loose_header(const char *hdr, struct object_info *oi);\n    + \n    ++/**\n    ++ * With in-core object data in \"buf\", rehash it to make sure the\n    ++ * object name actually matches \"oid\" to detect object corruption.\n    ++ * With \"buf\" == NULL, try reading the object named with \"oid\" using\n    ++ * the streaming interface and rehash it to do the same.\n    ++ *\n    ++ * Treat the return value like oideq() (which is like memcmp()),\n    ++ * except that negative values might also indicate a generic error.\n    ++ */\n    + int check_object_signature(struct repository *r, const struct object_id *oid,\n    + \t\t\t   void *buf, unsigned long size, const char *type,\n    + \t\t\t   struct object_id *real_oidp);\n    +\n      ## object-file.c ##\n    -@@ object-file.c: void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n    - \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n    +@@ object-file.c: int format_object_header(char *str, size_t size, enum object_type type,\n    + \treturn format_object_header_literally(str, size, name, objsize);\n      }\n      \n    -+int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n    -+\t\t\t   unsigned long len, enum object_type type,\n    -+\t\t\t   const struct object_id *oid,\n    -+\t\t\t   struct object_id *real_oidp)\n    -+{\n    -+\tstruct object_id tmp;\n    -+\tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n    -+\n    -+\thash_object_file(algo, buf, len, type_name(type), real_oid);\n    -+\n    +-/*\n    +- * With in-core object data in \"buf\", rehash it to make sure the\n    +- * object name actually matches \"oid\" to detect object corruption.\n    +- * With \"buf\" == NULL, try reading the object named with \"oid\" using\n    +- * the streaming interface and rehash it to do the same.\n    +- */\n    + int check_object_signature(struct repository *r, const struct object_id *oid,\n    + \t\t\t   void *buf, unsigned long size, const char *type,\n    + \t\t\t   struct object_id *real_oidp)\n    +@@ object-file.c: int check_object_signature(struct repository *r, const struct object_id *oid,\n    + \n    + \tif (buf) {\n    + \t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n    +-\t\treturn !oideq(oid, real_oid) ? -1 : 0;\n    ++\t\treturn oideq(oid, real_oid);\n    + \t}\n    + \n    + \tst = open_istream(r, oid, &obj_type, &size, NULL);\n    +@@ object-file.c: int check_object_signature(struct repository *r, const struct object_id *oid,\n    + \t}\n    + \tr->hash_algo->final_oid_fn(real_oid, &c);\n    + \tclose_istream(st);\n    +-\treturn !oideq(oid, real_oid) ? -1 : 0;\n     +\treturn oideq(oid, real_oid);\n    -+}\n    -+\n    - /* Finalize a file on disk, and close it. */\n    - static void close_loose_object(int fd)\n    - {\n    -\n    - ## object-store.h ##\n    -@@ object-store.h: void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n    - \t\t      unsigned long len, const char *type,\n    - \t\t      struct object_id *oid);\n    + }\n    + \n    + int git_open_cloexec(const char *name, int flags)\n    +@@ object-file.c: int read_loose_object(const char *path,\n    + \t\t\tgit_inflate_end(&stream);\n    + \t\t\tgoto out;\n    + \t\t}\n    +-\t\tif (check_object_signature(the_repository, expected_oid,\n    +-\t\t\t\t\t   *contents, *size,\n    +-\t\t\t\t\t   oi->type_name->buf, real_oid))\n    ++\t\tif (!check_object_signature(the_repository, expected_oid,\n    ++\t\t\t\t\t    *contents, *size,\n    ++\t\t\t\t\t    oi->type_name->buf, real_oid))\n    + \t\t\tgoto out;\n    + \t}\n      \n    -+/**\n    -+ * hash_object_file_oideq() is like hash_object_file() except that\n    -+ * asserts that \"real_oid\" is equivalent to an input \"oid\", and the\n    -+ * return value is that of oideq(oid, real_oid).\n    -+ *\n    -+ * The \"real_oid\" can be NULL, when non-NULL the caller provides a\n    -+ * \"struct object_id *\" that can be used to print what the real OID\n    -+ * was.\n    -+ */\n    -+int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n    -+\t\t\t   unsigned long len, enum object_type type,\n    -+\t\t\t   const struct object_id *oid,\n    -+\t\t\t   struct object_id *real_oidp);\n    -+\n    - int write_object_file_flags(const void *buf, unsigned long len,\n    - \t\t\t    enum object_type type, struct object_id *oid,\n    - \t\t\t    unsigned flags);\n     \n      ## object.c ##\n     @@ object.c: struct object *parse_object(struct repository *r, const struct object_id *oid)\n    + \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n    + \t    (!obj && repo_has_object_file(r, oid) &&\n    + \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n    +-\t\tif (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) {\n    ++\t\tif (!check_object_signature(r, repl, NULL, 0, NULL, NULL)) {\n    + \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n    + \t\t\treturn NULL;\n    + \t\t}\n    +@@ object.c: struct object *parse_object(struct repository *r, const struct object_id *oid)\n      \n      \tbuffer = repo_read_object_file(r, oid, &type, &size);\n      \tif (buffer) {\n     -\t\tif (check_object_signature(r, repl, buffer, size,\n     -\t\t\t\t\t   type_name(type), NULL) < 0) {\n    -+\t\tif (!hash_object_file_oideq(r->hash_algo, buffer, size,\n    -+\t\t\t\t\t    type, repl, NULL)) {\n    ++\t\tif (!check_object_signature(r, repl, buffer, size,\n    ++\t\t\t\t\t    type_name(type), NULL)) {\n      \t\t\tfree(buffer);\n      \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n      \t\t\treturn NULL;\n    +\n    + ## pack-check.c ##\n    +@@ pack-check.c: static int verify_packfile(struct repository *r,\n    + \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\n    + \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n    + \t\t\t\t    (uintmax_t)entries[i].offset);\n    +-\t\telse if (check_object_signature(r, &oid, data, size,\n    +-\t\t\t\t\t\ttype_name(type), NULL))\n    ++\t\telse if (!check_object_signature(r, &oid, data, size,\n    ++\t\t\t\t\t\t type_name(type), NULL))\n    + \t\t\terr = error(\"packed %s from %s is corrupt\",\n    + \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n    + \t\telse if (fn) {\n 8:  70c3e84dd0d !  7:  c38af53e889 object-file API: replace check_object_signature() with stream_*\n    @@ Metadata\n     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n      ## Commit message ##\n    -    object-file API: replace check_object_signature() with stream_*\n    +    object-file API: split up and simplify check_object_signature()\n     \n    -    Change the task of the the check_object_signature() function so that\n    -    it no longer confusingly does two unrelated things.\n    +    Split up the check_object_signature() function into that non-streaming\n    +    version (it accepts an already filled \"buf\"), and a new\n    +    stream_object_signature() which will retrieve the object from storage,\n    +    and hash it on-the-fly.\n     \n    -    Now the \"!map\" branch of it is exposed as a renamed\n    -    stream_object_signature(). In preceding commits we migrated all of the\n    -    \"if (map)\" callers over to \"hash_object_file_oideq()\" or\n    -    \"hash_object_file_literally()\" followed by \"!oideq(...)\".\n    +    All of the callers of check_object_signature() were effectively\n    +    calling two different functions, if we go by cyclomatic\n    +    complexity. I.e. they'd either take the early \"if (map)\" branch and\n    +    return early, or not. This has been the case since the \"if (map)\"\n    +    condition was added in 090ea12671b (parse_object: avoid putting whole\n    +    blob in core, 2012-03-07).\n     \n    -    This makes the caller in parse_object() less confusing, as we'll now\n    -    no longer need to pass NULL for \"map\" and \"OBJ_BAD\" for the unused\n    -    \"type\" argument. The \"verify_packfile()\" caller is arguably a bit\n    -    worse off than before, but as we're only using this function in a\n    -    couple of places now a bit more verbosity there is acceptable.\n    +    We can then further simplify the resulting check_object_signature()\n    +    function since only one caller wanted to pass a non-NULL \"buf\" and a\n    +    non-NULL \"real_oidp\". That \"read_loose_object()\" codepath used by \"git\n    +    fsck\" can instead use hash_object_file() followed by oideq().\n     \n         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n    - ## cache.h ##\n    -@@ cache.h: enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,\n    - struct object_info;\n    - int parse_loose_header(const char *hdr, struct object_info *oi);\n    + ## builtin/fast-export.c ##\n    +@@ builtin/fast-export.c: static void export_blob(const struct object_id *oid)\n    + \t\tif (!buf)\n    + \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n    + \t\tif (!check_object_signature(the_repository, oid, buf, size,\n    +-\t\t\t\t\t    type_name(type), NULL))\n    ++\t\t\t\t\t    type_name(type)))\n    + \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n    + \t\tobject = parse_object_buffer(the_repository, oid, type,\n    + \t\t\t\t\t     size, buf, &eaten);\n    +\n    + ## builtin/index-pack.c ##\n    +@@ builtin/index-pack.c: static void fix_unresolved_deltas(struct hashfile *f)\n    + \t\t\tcontinue;\n    + \n    + \t\tif (!check_object_signature(the_repository, &d->oid, data,\n    +-\t\t\t\t\t    size, type_name(type), NULL))\n    ++\t\t\t\t\t    size, type_name(type)))\n    + \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n    + \n    + \t\t/*\n    +\n    + ## builtin/mktag.c ##\n    +@@ builtin/mktag.c: static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n    + \n    + \trepl = lookup_replace_object(the_repository, tagged_oid);\n    + \tret = !check_object_signature(the_repository, repl, buffer, size,\n    +-\t\t\t\t      type_name(*tagged_type), NULL);\n    ++\t\t\t\t      type_name(*tagged_type));\n    + \tfree(buffer);\n      \n    --int check_object_signature(struct repository *r, const struct object_id *oid,\n    --\t\t\t   void *buf, unsigned long size, enum object_type type,\n    + \treturn ret;\n    +\n    + ## cache.h ##\n    +@@ cache.h: int parse_loose_header(const char *hdr, struct object_info *oi);\n    + /**\n    +  * With in-core object data in \"buf\", rehash it to make sure the\n    +  * object name actually matches \"oid\" to detect object corruption.\n    +- * With \"buf\" == NULL, try reading the object named with \"oid\" using\n    +- * the streaming interface and rehash it to do the same.\n    +  *\n    +  * Treat the return value like oideq() (which is like memcmp()),\n    +  * except that negative values might also indicate a generic error.\n    +  */\n    + int check_object_signature(struct repository *r, const struct object_id *oid,\n    +-\t\t\t   void *buf, unsigned long size, const char *type,\n     -\t\t\t   struct object_id *real_oidp);\n    ++\t\t\t   void *buf, unsigned long size, const char *type);\n     +\n     +/**\n    -+ * stream_object_signature() tries to read the object named with \"oid\"\n    -+ * using the streaming interface and rehash it to make sure the object\n    -+ * name actually matches \"oid\" to detect object corruption.\n    ++ * A streaming version of check_object_signature().\n    ++ * Try reading the object named with \"oid\" using\n    ++ * the streaming interface and rehash it to do the same.\n     + */\n    -+int stream_object_signature(struct repository *r, const struct object_id *oid,\n    -+\t\t\t    struct object_id *real_oidp);\n    ++int stream_object_signature(struct repository *r, const struct object_id *oid);\n      \n      int finalize_object_file(const char *tmpfile, const char *filename);\n      \n     \n      ## object-file.c ##\n     @@ object-file.c: int format_object_header(char *str, size_t size, enum object_type type,\n    - \treturn format_object_header_literally(str, size, name, objsize);\n      }\n      \n    --/*\n    -- * With an in-core object data in \"map\", rehash it to make sure the\n    -- * object name actually matches \"oid\" to detect object corruption.\n    -- * With \"map\" == NULL, try reading the object named with \"oid\" using\n    -- * the streaming interface and rehash it to do the same.\n    -- */\n    --int check_object_signature(struct repository *r, const struct object_id *oid,\n    --\t\t\t   void *map, unsigned long size, enum object_type type,\n    + int check_object_signature(struct repository *r, const struct object_id *oid,\n    +-\t\t\t   void *buf, unsigned long size, const char *type,\n     -\t\t\t   struct object_id *real_oidp)\n    -+int stream_object_signature(struct repository *r, const struct object_id *oid,\n    -+\t\t\t    struct object_id *real_oidp)\n    ++\t\t\t   void *buf, unsigned long size, const char *type)\n      {\n    - \tstruct object_id tmp;\n    - \tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n    +-\tstruct object_id tmp;\n    +-\tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n    ++\tstruct object_id real_oid;\n    ++\n    ++\thash_object_file(r->hash_algo, buf, size, type, &real_oid);\n    ++\n    ++\treturn oideq(oid, &real_oid);\n    ++}\n    ++\n    ++int stream_object_signature(struct repository *r, const struct object_id *oid)\n    ++{\n    ++\tstruct object_id real_oid;\n     +\tunsigned long size;\n      \tenum object_type obj_type;\n      \tstruct git_istream *st;\n    @@ object-file.c: int format_object_header(char *str, size_t size, enum object_type\n      \tchar hdr[MAX_HEADER_LEN];\n      \tint hdrlen;\n      \n    --\tif (map) {\n    --\t\thash_object_file(r->hash_algo, map, size, type, real_oid);\n    --\t\treturn !oideq(oid, real_oid) ? -1 : 0;\n    +-\tif (buf) {\n    +-\t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n    +-\t\treturn oideq(oid, real_oid);\n     -\t}\n     -\n      \tst = open_istream(r, oid, &obj_type, &size, NULL);\n      \tif (!st)\n      \t\treturn -1;\n    +@@ object-file.c: int check_object_signature(struct repository *r, const struct object_id *oid,\n    + \t\t\tbreak;\n    + \t\tr->hash_algo->update_fn(&c, buf, readlen);\n    + \t}\n    +-\tr->hash_algo->final_oid_fn(real_oid, &c);\n    ++\tr->hash_algo->final_oid_fn(&real_oid, &c);\n    + \tclose_istream(st);\n    +-\treturn oideq(oid, real_oid);\n    ++\treturn oideq(oid, &real_oid);\n    + }\n    + \n    + int git_open_cloexec(const char *name, int flags)\n    +@@ object-file.c: int read_loose_object(const char *path,\n    + \t\t\tgit_inflate_end(&stream);\n    + \t\t\tgoto out;\n    + \t\t}\n    +-\t\tif (!check_object_signature(the_repository, expected_oid,\n    +-\t\t\t\t\t    *contents, *size,\n    +-\t\t\t\t\t    oi->type_name->buf, real_oid))\n    ++\n    ++\t\thash_object_file(the_repository->hash_algo,\n    ++\t\t\t\t *contents, *size, oi->type_name->buf,\n    ++\t\t\t\t real_oid);\n    ++\t\tif (!oideq(expected_oid, real_oid))\n    + \t\t\tgoto out;\n    + \t}\n    + \n     \n      ## object.c ##\n     @@ object.c: struct object *parse_object(struct repository *r, const struct object_id *oid)\n      \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n      \t    (!obj && repo_has_object_file(r, oid) &&\n      \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n    --\t\tif (check_object_signature(r, repl, NULL, 0, OBJ_BAD, NULL) < 0) {\n    -+\t\tif (stream_object_signature(r, repl, NULL) < 0) {\n    +-\t\tif (!check_object_signature(r, repl, NULL, 0, NULL, NULL)) {\n    ++\t\tif (!stream_object_signature(r, repl)) {\n      \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n      \t\t\treturn NULL;\n      \t\t}\n    +@@ object.c: struct object *parse_object(struct repository *r, const struct object_id *oid)\n    + \tbuffer = repo_read_object_file(r, oid, &type, &size);\n    + \tif (buffer) {\n    + \t\tif (!check_object_signature(r, repl, buffer, size,\n    +-\t\t\t\t\t    type_name(type), NULL)) {\n    ++\t\t\t\t\t    type_name(type))) {\n    + \t\t\tfree(buffer);\n    + \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n    + \t\t\treturn NULL;\n     \n      ## pack-check.c ##\n     @@ pack-check.c: static int verify_packfile(struct repository *r,\n    + \n    + \t\tif (type == OBJ_BLOB && big_file_threshold <= size) {\n    + \t\t\t/*\n    +-\t\t\t * Let check_object_signature() check it with\n    ++\t\t\t * Let stream_object_signature() check it with\n    + \t\t\t * the streaming interface; no point slurping\n    + \t\t\t * the data in-core only to discard.\n    + \t\t\t */\n    +@@ pack-check.c: static int verify_packfile(struct repository *r,\n      \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\n      \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n      \t\t\t\t    (uintmax_t)entries[i].offset);\n    --\t\telse if (check_object_signature(r, &oid, data, size,\n    --\t\t\t\t\t\ttype, NULL))\n    -+\t\telse if (data && !hash_object_file_oideq(r->hash_algo, data,\n    -+\t\t\t\t\t\t\t size, type, &oid,\n    -+\t\t\t\t\t\t\t NULL))\n    +-\t\telse if (!check_object_signature(r, &oid, data, size,\n    +-\t\t\t\t\t\t type_name(type), NULL))\n    ++\t\telse if (data && !check_object_signature(r, &oid, data, size,\n    ++\t\t\t\t\t\t\t type_name(type)))\n     +\t\t\terr = error(\"packed %s from %s is corrupt\",\n     +\t\t\t\t    oid_to_hex(&oid), p->pack_name);\n    -+\t\telse if (!data && stream_object_signature(r, &oid, NULL))\n    ++\t\telse if (!data && !stream_object_signature(r, &oid))\n      \t\t\terr = error(\"packed %s from %s is corrupt\",\n      \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n      \t\telse if (fn) {\n 6:  2a065bf23da !  8:  a5ebd04d462 object-file API: replace some use of check_object_signature()\n    @@ Metadata\n     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n      ## Commit message ##\n    -    object-file API: replace some use of check_object_signature()\n    +    object API: rename hash_object_file_literally() to write_*()\n     \n    -    Add a \"hash_object_file_literally()\" function to go with the existing\n    -    \"hash_object_file()\" function. This is currently a wrapper for its\n    -    sibling, but this change will allow us to change it to take an \"enum\n    -    object_type\" in a subsequent commit.\n    +    Before 0c3db67cc81 (hash-object --literally: fix buffer overrun with\n    +    extra-long object type, 2015-05-04) the hash-object code being changed\n    +    here called write_sha1_file() to both hash and write a loose\n    +    object. Before that we'd use hash_sha1_file() to if \"-w\" wasn't\n    +    provided, and otherwise call write_sha1_file().\n     \n    -    The only caller that wanted to pass a custom type to\n    -    \"check_object_signature()\" was the \"git fsck\" via its\n    -    \"read_loose_object()\", which is being changed here.\n    -\n    -    There was an existing hash_object_file_literally() which I'm renaming\n    -    to \"hash_write_object_file_literally()\", that function is only used\n    -    for \"hash-object --literally\". That renaming is being done because it\n    -    would be confusing to have a \"hash_object_file_literally()\" and a\n    -    \"hash_object_file()\" that do very different things.\n    +    Now we'll always call the same function for both writing. Let's rename\n    +    it from hash_*_literally() to write_*_literally(). Even though the\n    +    write_*() might not actually write if HASH_WRITE_OBJECT isn't in\n    +    \"flags\", having it be more similar to write_object_file_flags() than\n    +    hash_object_file(), but carrying a name that would suggest that it's a\n    +    variant of the latter is confusing.\n     \n         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n    @@ builtin/hash-object.c: static int hash_literally(struct object_id *oid, int fd,\n      \t\tret = -1;\n      \telse\n     -\t\tret = hash_object_file_literally(buf.buf, buf.len, type, oid,\n    --\t\t\t\t\t\t flags);\n    -+\t\tret = hash_write_object_file_literally(buf.buf, buf.len, type, oid,\n    -+\t\t\t\t\t\t       flags);\n    ++\t\tret = write_object_file_literally(buf.buf, buf.len, type, oid,\n    + \t\t\t\t\t\t flags);\n      \tstrbuf_release(&buf);\n      \treturn ret;\n    - }\n     \n      ## object-file.c ##\n    -@@ object-file.c: void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n    - \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n    - }\n    - \n    -+static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf,\n    -+\t\t\t\t       unsigned long len, const char *type,\n    -+\t\t\t\t       struct object_id *oid)\n    -+{\n    -+\thash_object_file(algo, buf, len, type, oid);\n    -+}\n    -+\n    - int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n    - \t\t\t   unsigned long len, enum object_type type,\n    - \t\t\t   const struct object_id *oid,\n     @@ object-file.c: int write_object_file_flags(const void *buf, unsigned long len,\n      \treturn write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags);\n      }\n    @@ object-file.c: int write_object_file_flags(const void *buf, unsigned long len,\n     -int hash_object_file_literally(const void *buf, unsigned long len,\n     -\t\t\t       const char *type, struct object_id *oid,\n     -\t\t\t       unsigned flags)\n    -+int hash_write_object_file_literally(const void *buf, unsigned long len,\n    -+\t\t\t\t     const char *type, struct object_id *oid,\n    -+\t\t\t\t     unsigned flags)\n    ++int write_object_file_literally(const void *buf, unsigned long len,\n    ++\t\t\t\tconst char *type, struct object_id *oid,\n    ++\t\t\t\tunsigned flags)\n      {\n      \tchar *header;\n      \tint hdrlen, status = 0;\n    -@@ object-file.c: int read_loose_object(const char *path,\n    - \t\t\tgit_inflate_end(&stream);\n    - \t\t\tgoto out;\n    - \t\t}\n    --\t\tif (check_object_signature(the_repository, expected_oid,\n    -+\t\thash_object_file_literally(the_repository->hash_algo,\n    - \t\t\t\t\t   *contents, *size,\n    --\t\t\t\t\t   oi->type_name->buf, real_oid))\n    -+\t\t\t\t\t   oi->type_name->buf, real_oid);\n    -+\t\tif (!oideq(expected_oid, real_oid))\n    - \t\t\tgoto out;\n    - \t}\n    - \n     \n      ## object-store.h ##\n     @@ object-store.h: static inline int write_object_file(const void *buf, unsigned long len,\n    @@ object-store.h: static inline int write_object_file(const void *buf, unsigned lo\n     -int hash_object_file_literally(const void *buf, unsigned long len,\n     -\t\t\t       const char *type, struct object_id *oid,\n     -\t\t\t       unsigned flags);\n    -+int hash_write_object_file_literally(const void *buf, unsigned long len,\n    -+\t\t\t\t     const char *type, struct object_id *oid,\n    -+\t\t\t\t     unsigned flags);\n    ++int write_object_file_literally(const void *buf, unsigned long len,\n    ++\t\t\t\tconst char *type, struct object_id *oid,\n    ++\t\t\t\tunsigned flags);\n      \n      /*\n       * Add an object file to the in-memory object store, without writing it\n 7:  ad5d94714cc !  9:  40647be525b object-file API: have hash_object_file() take \"enum object_type\"\n    @@ Commit message\n         Change the hash_object_file() function to take an \"enum\n         object_type\".\n     \n    -    Almost all of its callers were passing either\n    -    \"{commit,tree,blob,tag}_type\", or the result of a call to\n    -    type_name(). Let's instead benefit from type checking and use the enum\n    -    directly.\n    -\n    -    \"Almost\" because one caller here will now pass OBJ_BAD. The previous\n    -    \"NULL\" value was not used, as \"check_object_signature()\" will never\n    -    use its \"type\" argument when given a NULL \"map\" argument, which that\n    -    caller in \"parse_object()\" also does. We'll deal with it in a\n    -    subsequent commit, but for now it'll pass an \"OBJ_BAD\" placeholder.\n    +    Since a preceding commit all of its callers are passing either\n    +    \"{commit,tree,blob,tag}_type\", or the result of a call to type_name(),\n    +    the parse_object() caller that would pass NULL is now using\n    +    stream_object_signature().\n     \n         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n    @@ apply.c: static int apply_binary(struct apply_state *state,\n      \t\tif (strcmp(oid_to_hex(&oid), patch->new_oid_prefix))\n      \t\t\treturn error(_(\"binary patch to '%s' creates incorrect result (expecting %s, got %s)\"),\n     \n    + ## builtin/fast-export.c ##\n    +@@ builtin/fast-export.c: static void export_blob(const struct object_id *oid)\n    + \t\tif (!buf)\n    + \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n    + \t\tif (!check_object_signature(the_repository, oid, buf, size,\n    +-\t\t\t\t\t    type_name(type)))\n    ++\t\t\t\t\t    type))\n    + \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n    + \t\tobject = parse_object_buffer(the_repository, oid, type,\n    + \t\t\t\t\t     size, buf, &eaten);\n    +\n      ## builtin/index-pack.c ##\n     @@ builtin/index-pack.c: static struct base_data *resolve_delta(struct object_entry *delta_obj,\n      \tif (!result_data)\n    @@ builtin/index-pack.c: static struct base_data *resolve_delta(struct object_entry\n      \tsha1_object(result_data, NULL, result_size, delta_obj->real_type,\n      \t\t    &delta_obj->idx.oid);\n      \n    +@@ builtin/index-pack.c: static void fix_unresolved_deltas(struct hashfile *f)\n    + \t\t\tcontinue;\n    + \n    + \t\tif (!check_object_signature(the_repository, &d->oid, data,\n    +-\t\t\t\t\t    size, type_name(type)))\n    ++\t\t\t\t\t    size, type))\n    + \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n    + \n    + \t\t/*\n    +\n    + ## builtin/mktag.c ##\n    +@@ builtin/mktag.c: static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n    + \n    + \trepl = lookup_replace_object(the_repository, tagged_oid);\n    + \tret = !check_object_signature(the_repository, repl, buffer, size,\n    +-\t\t\t\t      type_name(*tagged_type));\n    ++\t\t\t\t     *tagged_type);\n    + \tfree(buffer);\n    + \n    + \treturn ret;\n     \n      ## builtin/replace.c ##\n     @@ builtin/replace.c: static int check_one_mergetag(struct commit *commit,\n    @@ cache-tree.c: static int verify_one(struct repository *r,\n      \t\tBUG(\"cache-tree for path %.*s does not match. \"\n     \n      ## cache.h ##\n    -@@ cache.h: struct object_info;\n    - int parse_loose_header(const char *hdr, struct object_info *oi);\n    - \n    +@@ cache.h: int parse_loose_header(const char *hdr, struct object_info *oi);\n    +  * except that negative values might also indicate a generic error.\n    +  */\n      int check_object_signature(struct repository *r, const struct object_id *oid,\n    --\t\t\t   void *buf, unsigned long size, const char *type,\n    -+\t\t\t   void *buf, unsigned long size, enum object_type type,\n    - \t\t\t   struct object_id *real_oidp);\n    +-\t\t\t   void *buf, unsigned long size, const char *type);\n    ++\t\t\t   void *map, unsigned long size,\n    ++\t\t\t   enum object_type type);\n      \n    - int finalize_object_file(const char *tmpfile, const char *filename);\n    + /**\n    +  * A streaming version of check_object_signature().\n     \n      ## convert.c ##\n     @@ convert.c: static int ident_to_worktree(const char *src, size_t len,\n    @@ log-tree.c: static int show_one_mergetag(struct commit *commit,\n     \n      ## object-file.c ##\n     @@ object-file.c: int format_object_header(char *str, size_t size, enum object_type type,\n    -  * the streaming interface and rehash it to do the same.\n    -  */\n    + }\n    + \n      int check_object_signature(struct repository *r, const struct object_id *oid,\n    --\t\t\t   void *map, unsigned long size, const char *type,\n    -+\t\t\t   void *map, unsigned long size, enum object_type type,\n    - \t\t\t   struct object_id *real_oidp)\n    +-\t\t\t   void *buf, unsigned long size, const char *type)\n    ++\t\t\t   void *buf, unsigned long size,\n    ++\t\t\t   enum object_type type)\n      {\n    - \tstruct object_id tmp;\n    + \tstruct object_id real_oid;\n    + \n     @@ object-file.c: int pretend_object_file(void *buf, unsigned long len, enum object_type type,\n      {\n      \tstruct cached_object *co;\n    @@ object-file.c: int pretend_object_file(void *buf, unsigned long len, enum object\n      \t    find_cached_object(oid))\n      \t\treturn 0;\n     @@ object-file.c: static int write_buffer(int fd, const void *buf, size_t len)\n    + \treturn 0;\n      }\n      \n    - void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n    +-void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n     -\t\t     unsigned long len, const char *type,\n    -+\t\t     unsigned long len, enum object_type type,\n    - \t\t     struct object_id *oid)\n    +-\t\t     struct object_id *oid)\n    ++static void hash_object_file_literally(const struct git_hash_algo *algo,\n    ++\t\t\t\t       const void *buf, unsigned long len,\n    ++\t\t\t\t       const char *type, struct object_id *oid)\n      {\n      \tchar hdr[MAX_HEADER_LEN];\n      \tint hdrlen = sizeof(hdr);\n    --\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n     +\n    -+\twrite_object_file_prepare(algo, buf, len, type_name(type), oid, hdr, &hdrlen);\n    + \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n      }\n      \n    - static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf,\n    - \t\t\t\t       unsigned long len, const char *type,\n    - \t\t\t\t       struct object_id *oid)\n    - {\n    --\thash_object_file(algo, buf, len, type, oid);\n    -+\tchar hdr[MAX_HEADER_LEN];\n    -+\tint hdrlen = sizeof(hdr);\n    ++void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n    ++\t\t      unsigned long len, enum object_type type,\n    ++\t\t      struct object_id *oid)\n    ++{\n    ++\thash_object_file_literally(algo, buf, len, type_name(type), oid);\n    ++}\n     +\n    -+\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n    - }\n    - \n    - int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n    -@@ object-file.c: int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n    - \tstruct object_id tmp;\n    - \tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n    - \n    --\thash_object_file(algo, buf, len, type_name(type), real_oid);\n    -+\thash_object_file(algo, buf, len, type, real_oid);\n    - \n    - \treturn oideq(oid, real_oid);\n    - }\n    + /* Finalize a file on disk, and close it. */\n    + static void close_loose_object(int fd)\n    + {\n     @@ object-file.c: static int index_mem(struct index_state *istate,\n      \tif (write_object)\n      \t\tret = write_object_file(buf, size, type, oid);\n    @@ object-file.c: int index_path(struct index_state *istate, struct object_id *oid,\n      \t\telse if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))\n      \t\t\trc = error(_(\"%s: failed to insert into database\"), path);\n      \t\tstrbuf_release(&sb);\n    +@@ object-file.c: int read_loose_object(const char *path,\n    + \t\t\tgoto out;\n    + \t\t}\n    + \n    +-\t\thash_object_file(the_repository->hash_algo,\n    +-\t\t\t\t *contents, *size, oi->type_name->buf,\n    +-\t\t\t\t real_oid);\n    ++\t\thash_object_file_literally(the_repository->hash_algo,\n    ++\t\t\t\t\t   *contents, *size,\n    ++\t\t\t\t\t   oi->type_name->buf, real_oid);\n    + \t\tif (!oideq(expected_oid, real_oid))\n    + \t\t\tgoto out;\n    + \t}\n     \n      ## object-store.h ##\n     @@ object-store.h: static inline void *repo_read_object_file(struct repository *r,\n    - /* Read and unpack an object file into memory, write memory to an object file */\n      int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);\n      \n    -+\n      void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n     -\t\t      unsigned long len, const char *type,\n     +\t\t      unsigned long len, enum object_type type,\n      \t\t      struct object_id *oid);\n      \n    - /**\n    + int write_object_file_flags(const void *buf, unsigned long len,\n     \n      ## object.c ##\n     @@ object.c: struct object *parse_object(struct repository *r, const struct object_id *oid)\n    - \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n    - \t    (!obj && repo_has_object_file(r, oid) &&\n    - \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n    --\t\tif (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) {\n    -+\t\tif (check_object_signature(r, repl, NULL, 0, OBJ_BAD, NULL) < 0) {\n    - \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n    + \n    + \tbuffer = repo_read_object_file(r, oid, &type, &size);\n    + \tif (buffer) {\n    +-\t\tif (!check_object_signature(r, repl, buffer, size,\n    +-\t\t\t\t\t    type_name(type))) {\n    ++\t\tif (!check_object_signature(r, repl, buffer, size, type)) {\n    + \t\t\tfree(buffer);\n    + \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n      \t\t\treturn NULL;\n    - \t\t}\n     \n      ## pack-check.c ##\n     @@ pack-check.c: static int verify_packfile(struct repository *r,\n      \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n      \t\t\t\t    (uintmax_t)entries[i].offset);\n    - \t\telse if (check_object_signature(r, &oid, data, size,\n    --\t\t\t\t\t\ttype_name(type), NULL))\n    -+\t\t\t\t\t\ttype, NULL))\n    + \t\telse if (data && !check_object_signature(r, &oid, data, size,\n    +-\t\t\t\t\t\t\t type_name(type)))\n    ++\t\t\t\t\t\t\t type))\n      \t\t\terr = error(\"packed %s from %s is corrupt\",\n      \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n    - \t\telse if (fn) {\n    + \t\telse if (!data && !stream_object_signature(r, &oid))\n 9:  009b6604d6f ! 10:  e39edfbce05 object-file.c: add a literal version of write_object_file_prepare()\n    @@ object-file.c: void *read_object_with_reference(struct repository *r,\n      }\n      \n      /*\n    -@@ object-file.c: void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n    - \tchar hdr[MAX_HEADER_LEN];\n    - \tint hdrlen = sizeof(hdr);\n    - \n    --\twrite_object_file_prepare(algo, buf, len, type_name(type), oid, hdr, &hdrlen);\n    -+\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n    - }\n    - \n    - static void hash_object_file_literally(const struct git_hash_algo *algo, const void *buf,\n    -@@ object-file.c: static void hash_object_file_literally(const struct git_hash_algo *algo, const v\n    +@@ object-file.c: static void hash_object_file_literally(const struct git_hash_algo *algo,\n      \tchar hdr[MAX_HEADER_LEN];\n      \tint hdrlen = sizeof(hdr);\n      \n    @@ object-file.c: static void hash_object_file_literally(const struct git_hash_algo\n     +\twrite_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen);\n      }\n      \n    - int hash_object_file_oideq(const struct git_hash_algo *algo, const void *buf,\n    + void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n     @@ object-file.c: int write_object_file_flags(const void *buf, unsigned long len,\n      \t/* Normally if we have it in the pack then we do not bother writing\n      \t * it out into .git/objects/??/?{38} file.\n    @@ object-file.c: int write_object_file_flags(const void *buf, unsigned long len,\n      \t\t\t\t  &hdrlen);\n      \tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n      \t\treturn 0;\n    -@@ object-file.c: int hash_write_object_file_literally(const void *buf, unsigned long len,\n    +@@ object-file.c: int write_object_file_literally(const void *buf, unsigned long len,\n      \t/* type string, SP, %lu of the length plus NUL must fit this */\n      \thdrlen = strlen(type) + MAX_HEADER_LEN;\n      \theader = xmalloc(hdrlen);\n10:  d89fe344c70 = 11:  f2b1cb861a0 object-file API: pass an enum to read_object_with_reference()\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447728","messageId":"patch-v2-02.11-5ba49778ac1-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 02/11] object-file API: return \"void\", not \"int\" from hash_object_file()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:16Z","receivedAt":"2022-02-04T13:51:38Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"The hash_object_file() function added in abdc3fc8421 (Add\nhash_sha1_file(), 2006-10-14) did not have a meaningful return value,\nand it never has.\n\nOne was seemingly added to avoid adding braces to the \"ret = \"\nassignments being modified here. Let's instead assign \"0\" to the \"ret\"\nvariables at the beginning of the relevant functions, and have them\nreturn \"void\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c  | 16 ++++++++--------\n object-store.h |  6 +++---\n 2 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex ecc77973292..eeb6814780a 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1836,14 +1836,13 @@ static int write_buffer(int fd, const void *buf, size_t len)\n \treturn 0;\n }\n \n-int hash_object_file(const struct git_hash_algo *algo, const void *buf,\n+void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \t\t     unsigned long len, const char *type,\n \t\t     struct object_id *oid)\n {\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n-\treturn 0;\n }\n \n /* Finalize a file on disk, and close it. */\n@@ -2118,7 +2117,7 @@ static int index_mem(struct index_state *istate,\n \t\t     enum object_type type,\n \t\t     const char *path, unsigned flags)\n {\n-\tint ret;\n+\tint ret = 0;\n \tint re_allocated = 0;\n \tint write_object = flags & HASH_WRITE_OBJECT;\n \n@@ -2148,8 +2147,9 @@ static int index_mem(struct index_state *istate,\n \tif (write_object)\n \t\tret = write_object_file(buf, size, type_name(type), oid);\n \telse\n-\t\tret = hash_object_file(the_hash_algo, buf, size,\n-\t\t\t\t       type_name(type), oid);\n+\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n+\t\t\t\t oid);\n+\n \tif (re_allocated)\n \t\tfree(buf);\n \treturn ret;\n@@ -2161,7 +2161,7 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\t\t\t     const char *path,\n \t\t\t\t     unsigned flags)\n {\n-\tint ret;\n+\tint ret = 0;\n \tconst int write_object = flags & HASH_WRITE_OBJECT;\n \tstruct strbuf sbuf = STRBUF_INIT;\n \n@@ -2175,8 +2175,8 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\tret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB),\n \t\t\t\t\toid);\n \telse\n-\t\tret = hash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n-\t\t\t\t       type_name(OBJ_BLOB), oid);\n+\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n+\t\t\t\t type_name(OBJ_BLOB), oid);\n \tstrbuf_release(&sbuf);\n \treturn ret;\n }\ndiff --git a/object-store.h b/object-store.h\nindex 6f89482df03..44f6868cc9c 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -245,9 +245,9 @@ static inline void *repo_read_object_file(struct repository *r,\n /* Read and unpack an object file into memory, write memory to an object file */\n int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);\n \n-int hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t     unsigned long len, const char *type,\n-\t\t     struct object_id *oid);\n+void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n+\t\t      unsigned long len, const char *type,\n+\t\t      struct object_id *oid);\n \n int write_object_file_flags(const void *buf, unsigned long len,\n \t\t\t    const char *type, struct object_id *oid,\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447729","messageId":"patch-v2-03.11-92fd020d199-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 03/11] object-file API: add a format_object_header() function","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:17Z","receivedAt":"2022-02-04T13:51:40Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a convenience function to wrap the xsnprintf() command that\ngenerates loose object headers. This code was copy/pasted in various\nparts of the codebase, let's define it in one place and re-use it from\nthere.\n\nAll except one caller of it had a valid \"enum object_type\" for us,\nit's only write_object_file_prepare() which might need to deal with\n\"git hash-object --literally\" and a potential garbage type. Let's have\nthe primary API use an \"enum object_type\", and define a *_literally()\nfunction that can take an arbitrary \"const char *\" for the type.\n\nSee [1] for the discussion that prompted this patch, i.e. new code in\nobject-file.c that wanted to copy/paste the xsnprintf() invocation.\n\nIn the case of fast-import.c the callers unfortunately need to cast\nback & forth between \"unsigned char *\" and \"char *\", since\nformat_object_header() ad encode_in_pack_object_header() take\ndifferent signedness.\n\n1. https://lore.kernel.org/git/211213.86bl1l9bfz.gmgdl@evledraar.gmail.com/\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/fast-import.c |  6 +++---\n builtin/index-pack.c  |  3 +--\n bulk-checkin.c        |  4 ++--\n http-push.c           |  2 +-\n object-file.c         | 23 ++++++++++++++++++++---\n object-store.h        |  8 ++++++++\n 6 files changed, 35 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 2b2e28bad79..123df7d9a53 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -937,8 +937,8 @@ static int store_object(\n \tgit_hash_ctx c;\n \tgit_zstream s;\n \n-\thdrlen = xsnprintf((char *)hdr, sizeof(hdr), \"%s %lu\",\n-\t\t\t   type_name(type), (unsigned long)dat->len) + 1;\n+\thdrlen = format_object_header((char *)hdr, sizeof(hdr), type,\n+\t\t\t\t      dat->len);\n \tthe_hash_algo->init_fn(&c);\n \tthe_hash_algo->update_fn(&c, hdr, hdrlen);\n \tthe_hash_algo->update_fn(&c, dat->buf, dat->len);\n@@ -1091,7 +1091,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)\n \thashfile_checkpoint(pack_file, &checkpoint);\n \toffset = checkpoint.offset;\n \n-\thdrlen = xsnprintf((char *)out_buf, out_sz, \"blob %\" PRIuMAX, len) + 1;\n+\thdrlen = format_object_header((char *)out_buf, out_sz, OBJ_BLOB, len);\n \n \tthe_hash_algo->init_fn(&c);\n \tthe_hash_algo->update_fn(&c, out_buf, hdrlen);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 3c2e6aee3cc..01574378ce2 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -449,8 +449,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size,\n \tint hdrlen;\n \n \tif (!is_delta_type(type)) {\n-\t\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX,\n-\t\t\t\t   type_name(type),(uintmax_t)size) + 1;\n+\t\thdrlen = format_object_header(hdr, sizeof(hdr), type, size);\n \t\tthe_hash_algo->init_fn(&c);\n \t\tthe_hash_algo->update_fn(&c, hdr, hdrlen);\n \t} else\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 8785b2ac806..85b3ebaf971 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -220,8 +220,8 @@ static int deflate_to_pack(struct bulk_checkin_state *state,\n \tif (seekback == (off_t) -1)\n \t\treturn error(\"cannot find the current offset\");\n \n-\theader_len = xsnprintf((char *)obuf, sizeof(obuf), \"%s %\" PRIuMAX,\n-\t\t\t       type_name(type), (uintmax_t)size) + 1;\n+\theader_len = format_object_header((char *)obuf, sizeof(obuf),\n+\t\t\t\t\t  type, size);\n \tthe_hash_algo->init_fn(&ctx);\n \tthe_hash_algo->update_fn(&ctx, obuf, header_len);\n \ndiff --git a/http-push.c b/http-push.c\nindex 3309aaf004a..f0c044dcf76 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -363,7 +363,7 @@ static void start_put(struct transfer_request *request)\n \tgit_zstream stream;\n \n \tunpacked = read_object_file(&request->obj->oid, &type, &len);\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(type), (uintmax_t)len) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type, len);\n \n \t/* Set it up */\n \tgit_deflate_init(&stream, zlib_compression_level);\ndiff --git a/object-file.c b/object-file.c\nindex eeb6814780a..3fcd46cf9ed 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1049,6 +1049,23 @@ void *xmmap(void *start, size_t length,\n \treturn ret;\n }\n \n+static int format_object_header_literally(char *str, size_t size,\n+\t\t\t\t\t  const char *type, size_t objsize)\n+{\n+\treturn xsnprintf(str, size, \"%s %\"PRIuMAX, type, (uintmax_t)objsize) + 1;\n+}\n+\n+int format_object_header(char *str, size_t size, enum object_type type,\n+\t\t\t size_t objsize)\n+{\n+\tconst char *name = type_name(type);\n+\n+\tif (!name)\n+\t\tBUG(\"could not get a type name for 'enum object_type' value %d\", type);\n+\n+\treturn format_object_header_literally(str, size, name, objsize);\n+}\n+\n /*\n  * With an in-core object data in \"map\", rehash it to make sure the\n  * object name actually matches \"oid\" to detect object corruption.\n@@ -1077,7 +1094,7 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\treturn -1;\n \n \t/* Generate the header */\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(obj_type), (uintmax_t)size) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size);\n \n \t/* Sha1.. */\n \tr->hash_algo->init_fn(&c);\n@@ -1777,7 +1794,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo,\n \tgit_hash_ctx c;\n \n \t/* Generate the header */\n-\t*hdrlen = xsnprintf(hdr, *hdrlen, \"%s %\"PRIuMAX , type, (uintmax_t)len)+1;\n+\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n \n \t/* Sha1.. */\n \talgo->init_fn(&c);\n@@ -2051,7 +2068,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)\n \tbuf = read_object(the_repository, oid, &type, &len);\n \tif (!buf)\n \t\treturn error(_(\"cannot read object for %s\"), oid_to_hex(oid));\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(type), (uintmax_t)len) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type, len);\n \tret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);\n \tfree(buf);\n \ndiff --git a/object-store.h b/object-store.h\nindex 44f6868cc9c..8b4413d0ce7 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -331,6 +331,14 @@ int repo_has_object_file_with_flags(struct repository *r,\n  */\n int has_loose_object_nonlocal(const struct object_id *);\n \n+/**\n+ * format_object_header() is a thin wrapper around s xsnprintf() that\n+ * writes the initial \"<type> <obj-len>\" part of the loose object\n+ * header. It returns the size that snprintf() returns + 1.\n+ */\n+int format_object_header(char *str, size_t size, enum object_type type,\n+\t\t\t size_t objsize);\n+\n void assert_oid_type(const struct object_id *oid, enum object_type expect);\n \n /*\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447730","messageId":"patch-v2-04.11-d259f901114-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 04/11] object-file API: have write_object_file() take \"enum object_type\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:18Z","receivedAt":"2022-02-04T13:51:41Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the write_object_file() function to take an \"enum object_type\"\ninstead of a \"const char *type\". Its callers either passed\n{commit,tree,blob,tag}_type and can pass the corresponding OBJ_* type\ninstead, or were hardcoding strings like \"blob\".\n\nThis avoids the back & forth fragility where the callers of\nwrite_object_file() would have the enum type, and convert it\nthemselves via type_name(). We do have to now do that conversion\nourselves before calling write_object_file_prepare(), but those\ncodepaths will be similarly adjusted in subsequent commits.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n apply.c                  |  8 ++++----\n builtin/checkout.c       |  2 +-\n builtin/mktag.c          |  2 +-\n builtin/mktree.c         |  2 +-\n builtin/notes.c          |  3 +--\n builtin/receive-pack.c   |  2 +-\n builtin/replace.c        |  2 +-\n builtin/tag.c            |  2 +-\n builtin/unpack-objects.c |  6 +++---\n cache-tree.c             |  2 +-\n commit.c                 |  2 +-\n match-trees.c            |  2 +-\n merge-ort.c              |  4 ++--\n merge-recursive.c        |  2 +-\n notes-cache.c            |  2 +-\n notes.c                  |  8 ++++----\n object-file.c            | 10 +++++-----\n object-store.h           |  4 ++--\n read-cache.c             |  2 +-\n 19 files changed, 33 insertions(+), 34 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex 7ffadc3b17a..e82a7c30f01 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -3589,7 +3589,7 @@ static int try_threeway(struct apply_state *state,\n \n \t/* Preimage the patch was prepared for */\n \tif (patch->is_new)\n-\t\twrite_object_file(\"\", 0, blob_type, &pre_oid);\n+\t\twrite_object_file(\"\", 0, OBJ_BLOB, &pre_oid);\n \telse if (get_oid(patch->old_oid_prefix, &pre_oid) ||\n \t\t read_blob_object(&buf, &pre_oid, patch->old_mode))\n \t\treturn error(_(\"repository lacks the necessary blob to perform 3-way merge.\"));\n@@ -3605,7 +3605,7 @@ static int try_threeway(struct apply_state *state,\n \t\treturn -1;\n \t}\n \t/* post_oid is theirs */\n-\twrite_object_file(tmp_image.buf, tmp_image.len, blob_type, &post_oid);\n+\twrite_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &post_oid);\n \tclear_image(&tmp_image);\n \n \t/* our_oid is ours */\n@@ -3618,7 +3618,7 @@ static int try_threeway(struct apply_state *state,\n \t\t\treturn error(_(\"cannot read the current contents of '%s'\"),\n \t\t\t\t     patch->old_name);\n \t}\n-\twrite_object_file(tmp_image.buf, tmp_image.len, blob_type, &our_oid);\n+\twrite_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &our_oid);\n \tclear_image(&tmp_image);\n \n \t/* in-core three-way merge between post and our using pre as base */\n@@ -4346,7 +4346,7 @@ static int add_index_file(struct apply_state *state,\n \t\t\t}\n \t\t\tfill_stat_cache_info(state->repo->index, ce, &st);\n \t\t}\n-\t\tif (write_object_file(buf, size, blob_type, &ce->oid) < 0) {\n+\t\tif (write_object_file(buf, size, OBJ_BLOB, &ce->oid) < 0) {\n \t\t\tdiscard_cache_entry(ce);\n \t\t\treturn error(_(\"unable to create backing store \"\n \t\t\t\t       \"for newly created file %s\"), path);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex cc804ba8e1e..24cc235939f 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -298,7 +298,7 @@ static int checkout_merged(int pos, const struct checkout *state,\n \t * (it also writes the merge result to the object database even\n \t * when it may contain conflicts).\n \t */\n-\tif (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid))\n+\tif (write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &oid))\n \t\tdie(_(\"Unable to add merge result for '%s'\"), path);\n \tfree(result_buf.ptr);\n \tce = make_transient_cache_entry(mode, &oid, path, 2, ce_mem_pool);\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 3b2dbbb37e6..96a3686af53 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -100,7 +100,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)\n \tif (verify_object_in_tag(&tagged_oid, &tagged_type))\n \t\tdie(_(\"tag on stdin did not refer to a valid object\"));\n \n-\tif (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)\n+\tif (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0)\n \t\tdie(_(\"unable to write tag file\"));\n \n \tstrbuf_release(&buf);\ndiff --git a/builtin/mktree.c b/builtin/mktree.c\nindex ae78ca1c029..a1213aaa961 100644\n--- a/builtin/mktree.c\n+++ b/builtin/mktree.c\n@@ -58,7 +58,7 @@ static void write_tree(struct object_id *oid)\n \t\tstrbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz);\n \t}\n \n-\twrite_object_file(buf.buf, buf.len, tree_type, oid);\n+\twrite_object_file(buf.buf, buf.len, OBJ_TREE, oid);\n \tstrbuf_release(&buf);\n }\n \ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 05d60483e82..d81acaeaf78 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -199,9 +199,8 @@ static void prepare_note_data(const struct object_id *object, struct note_data *\n \n static void write_note_data(struct note_data *d, struct object_id *oid)\n {\n-\tif (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) {\n+\tif (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) {\n \t\tint status = die_message(_(\"unable to write note object\"));\n-\n \t\tif (d->edit_path)\n \t\t\tdie_message(_(\"the note contents have been left in %s\"),\n \t\t\t\t    d->edit_path);\ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 9f4a0b816cf..231d576927b 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -762,7 +762,7 @@ static void prepare_push_cert_sha1(struct child_process *proc)\n \t\tint bogs /* beginning_of_gpg_sig */;\n \n \t\talready_done = 1;\n-\t\tif (write_object_file(push_cert.buf, push_cert.len, \"blob\",\n+\t\tif (write_object_file(push_cert.buf, push_cert.len, OBJ_BLOB,\n \t\t\t\t      &push_cert_oid))\n \t\t\toidclr(&push_cert_oid);\n \ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 6ff1734d587..995ca683302 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -474,7 +474,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle)\n \t\treturn -1;\n \t}\n \n-\tif (write_object_file(buf.buf, buf.len, commit_type, &new_oid)) {\n+\tif (write_object_file(buf.buf, buf.len, OBJ_COMMIT, &new_oid)) {\n \t\tstrbuf_release(&buf);\n \t\treturn error(_(\"could not write replacement commit for: '%s'\"),\n \t\t\t     old_ref);\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 134b3f1edf0..31e6b155c04 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -238,7 +238,7 @@ static int build_tag_object(struct strbuf *buf, int sign, struct object_id *resu\n {\n \tif (sign && do_sign(buf) < 0)\n \t\treturn error(_(\"unable to sign the tag\"));\n-\tif (write_object_file(buf->buf, buf->len, tag_type, result) < 0)\n+\tif (write_object_file(buf->buf, buf->len, OBJ_TAG, result) < 0)\n \t\treturn error(_(\"unable to write tag file\"));\n \treturn 0;\n }\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 4a9466295ba..808041551fd 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -177,7 +177,7 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf)\n \tstruct object_id oid;\n \n \tif (write_object_file(obj_buf->buffer, obj_buf->size,\n-\t\t\t      type_name(obj->type), &oid) < 0)\n+\t\t\t      obj->type, &oid) < 0)\n \t\tdie(\"failed to write object %s\", oid_to_hex(&obj->oid));\n \tobj->flags |= FLAG_WRITTEN;\n }\n@@ -243,7 +243,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t\t\t void *buf, unsigned long size)\n {\n \tif (!strict) {\n-\t\tif (write_object_file(buf, size, type_name(type),\n+\t\tif (write_object_file(buf, size, type,\n \t\t\t\t      &obj_list[nr].oid) < 0)\n \t\t\tdie(\"failed to write object\");\n \t\tadded_object(nr, type, buf, size);\n@@ -251,7 +251,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t\tobj_list[nr].obj = NULL;\n \t} else if (type == OBJ_BLOB) {\n \t\tstruct blob *blob;\n-\t\tif (write_object_file(buf, size, type_name(type),\n+\t\tif (write_object_file(buf, size, type,\n \t\t\t\t      &obj_list[nr].oid) < 0)\n \t\t\tdie(\"failed to write object\");\n \t\tadded_object(nr, type, buf, size);\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 65ca9933613..fdbbd191d22 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -440,7 +440,7 @@ static int update_one(struct cache_tree *it,\n \t} else if (dryrun) {\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n \t\t\t\t tree_type, &it->oid);\n-\t} else if (write_object_file_flags(buffer.buf, buffer.len, tree_type,\n+\t} else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE,\n \t\t\t\t\t   &it->oid, flags & WRITE_TREE_SILENT\n \t\t\t\t\t   ? HASH_SILENT : 0)) {\n \t\tstrbuf_release(&buffer);\ndiff --git a/commit.c b/commit.c\nindex a348f085b2b..6cc0ba9c11b 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1567,7 +1567,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \t\tgoto out;\n \t}\n \n-\tresult = write_object_file(buffer.buf, buffer.len, commit_type, ret);\n+\tresult = write_object_file(buffer.buf, buffer.len, OBJ_COMMIT, ret);\n out:\n \tstrbuf_release(&buffer);\n \treturn result;\ndiff --git a/match-trees.c b/match-trees.c\nindex df413989fa8..49398e599fe 100644\n--- a/match-trees.c\n+++ b/match-trees.c\n@@ -235,7 +235,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,\n \t\trewrite_with = oid2;\n \t}\n \thashcpy(rewrite_here, rewrite_with->hash);\n-\tstatus = write_object_file(buf, sz, tree_type, result);\n+\tstatus = write_object_file(buf, sz, OBJ_TREE, result);\n \tfree(buf);\n \treturn status;\n }\ndiff --git a/merge-ort.c b/merge-ort.c\nindex c3197970219..d4ba2955f11 100644\n--- a/merge-ort.c\n+++ b/merge-ort.c\n@@ -1888,7 +1888,7 @@ static int handle_content_merge(struct merge_options *opt,\n \n \t\tif (!ret &&\n \t\t    write_object_file(result_buf.ptr, result_buf.size,\n-\t\t\t\t      blob_type, &result->oid))\n+\t\t\t\t      OBJ_BLOB, &result->oid))\n \t\t\tret = err(opt, _(\"Unable to add %s to database\"),\n \t\t\t\t  path);\n \n@@ -3343,7 +3343,7 @@ static void write_tree(struct object_id *result_oid,\n \t}\n \n \t/* Write this object file out, and record in result_oid */\n-\twrite_object_file(buf.buf, buf.len, tree_type, result_oid);\n+\twrite_object_file(buf.buf, buf.len, OBJ_TREE, result_oid);\n \tstrbuf_release(&buf);\n }\n \ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex d9457797dbb..e0cbbf2d022 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1373,7 +1373,7 @@ static int merge_mode_and_contents(struct merge_options *opt,\n \n \t\t\tif (!ret &&\n \t\t\t    write_object_file(result_buf.ptr, result_buf.size,\n-\t\t\t\t\t      blob_type, &result->blob.oid))\n+\t\t\t\t\t      OBJ_BLOB, &result->blob.oid))\n \t\t\t\tret = err(opt, _(\"Unable to add %s to database\"),\n \t\t\t\t\t  a->path);\n \ndiff --git a/notes-cache.c b/notes-cache.c\nindex 2473314d686..9dfd251a815 100644\n--- a/notes-cache.c\n+++ b/notes-cache.c\n@@ -92,7 +92,7 @@ int notes_cache_put(struct notes_cache *c, struct object_id *key_oid,\n {\n \tstruct object_id value_oid;\n \n-\tif (write_object_file(data, size, \"blob\", &value_oid) < 0)\n+\tif (write_object_file(data, size, OBJ_BLOB, &value_oid) < 0)\n \t\treturn -1;\n \treturn add_note(&c->tree, key_oid, &value_oid, NULL);\n }\ndiff --git a/notes.c b/notes.c\nindex f87dac40684..7452e71cc8d 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -675,7 +675,7 @@ static int tree_write_stack_finish_subtree(struct tree_write_stack *tws)\n \t\tret = tree_write_stack_finish_subtree(n);\n \t\tif (ret)\n \t\t\treturn ret;\n-\t\tret = write_object_file(n->buf.buf, n->buf.len, tree_type, &s);\n+\t\tret = write_object_file(n->buf.buf, n->buf.len, OBJ_TREE, &s);\n \t\tif (ret)\n \t\t\treturn ret;\n \t\tstrbuf_release(&n->buf);\n@@ -836,7 +836,7 @@ int combine_notes_concatenate(struct object_id *cur_oid,\n \tfree(new_msg);\n \n \t/* create a new blob object from buf */\n-\tret = write_object_file(buf, buf_len, blob_type, cur_oid);\n+\tret = write_object_file(buf, buf_len, OBJ_BLOB, cur_oid);\n \tfree(buf);\n \treturn ret;\n }\n@@ -916,7 +916,7 @@ int combine_notes_cat_sort_uniq(struct object_id *cur_oid,\n \t\t\t\t string_list_join_lines_helper, &buf))\n \t\tgoto out;\n \n-\tret = write_object_file(buf.buf, buf.len, blob_type, cur_oid);\n+\tret = write_object_file(buf.buf, buf.len, OBJ_BLOB, cur_oid);\n \n out:\n \tstrbuf_release(&buf);\n@@ -1192,7 +1192,7 @@ int write_notes_tree(struct notes_tree *t, struct object_id *result)\n \tret = for_each_note(t, flags, write_each_note, &cb_data) ||\n \t      write_each_non_note_until(NULL, &cb_data) ||\n \t      tree_write_stack_finish_subtree(&root) ||\n-\t      write_object_file(root.buf.buf, root.buf.len, tree_type, result);\n+\t      write_object_file(root.buf.buf, root.buf.len, OBJ_TREE, result);\n \tstrbuf_release(&root.buf);\n \treturn ret;\n }\ndiff --git a/object-file.c b/object-file.c\nindex 3fcd46cf9ed..59eb793e0ac 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2014,7 +2014,7 @@ static int freshen_packed_object(const struct object_id *oid)\n }\n \n int write_object_file_flags(const void *buf, unsigned long len,\n-\t\t\t    const char *type, struct object_id *oid,\n+\t\t\t    enum object_type type, struct object_id *oid,\n \t\t\t    unsigned flags)\n {\n \tchar hdr[MAX_HEADER_LEN];\n@@ -2023,7 +2023,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t/* Normally if we have it in the pack then we do not bother writing\n \t * it out into .git/objects/??/?{38} file.\n \t */\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr,\n+\twrite_object_file_prepare(the_hash_algo, buf, len, type_name(type), oid, hdr,\n \t\t\t\t  &hdrlen);\n \tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n \t\treturn 0;\n@@ -2162,7 +2162,7 @@ static int index_mem(struct index_state *istate,\n \t}\n \n \tif (write_object)\n-\t\tret = write_object_file(buf, size, type_name(type), oid);\n+\t\tret = write_object_file(buf, size, type, oid);\n \telse\n \t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n \t\t\t\t oid);\n@@ -2189,7 +2189,7 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\t\t\t get_conv_flags(flags));\n \n \tif (write_object)\n-\t\tret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB),\n+\t\tret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB,\n \t\t\t\t\toid);\n \telse\n \t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n@@ -2313,7 +2313,7 @@ int index_path(struct index_state *istate, struct object_id *oid,\n \t\tif (!(flags & HASH_WRITE_OBJECT))\n \t\t\thash_object_file(the_hash_algo, sb.buf, sb.len,\n \t\t\t\t\t blob_type, oid);\n-\t\telse if (write_object_file(sb.buf, sb.len, blob_type, oid))\n+\t\telse if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))\n \t\t\trc = error(_(\"%s: failed to insert into database\"), path);\n \t\tstrbuf_release(&sb);\n \t\tbreak;\ndiff --git a/object-store.h b/object-store.h\nindex 8b4413d0ce7..eab1e2a967e 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -250,10 +250,10 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \t\t      struct object_id *oid);\n \n int write_object_file_flags(const void *buf, unsigned long len,\n-\t\t\t    const char *type, struct object_id *oid,\n+\t\t\t    enum object_type type, struct object_id *oid,\n \t\t\t    unsigned flags);\n static inline int write_object_file(const void *buf, unsigned long len,\n-\t\t\t\t    const char *type, struct object_id *oid)\n+\t\t\t\t    enum object_type type, struct object_id *oid)\n {\n \treturn write_object_file_flags(buf, len, type, oid, 0);\n }\ndiff --git a/read-cache.c b/read-cache.c\nindex cbe73f14e5e..b8ae30a0e71 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -735,7 +735,7 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,\n void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)\n {\n \tstruct object_id oid;\n-\tif (write_object_file(\"\", 0, blob_type, &oid))\n+\tif (write_object_file(\"\", 0, OBJ_BLOB, &oid))\n \t\tdie(_(\"cannot create an empty blob in the object database\"));\n \toidcpy(&ce->oid, &oid);\n }\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447731","messageId":"patch-v2-01.11-53334bc970a-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 01/11] object-file.c: split up declaration of unrelated variables","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:15Z","receivedAt":"2022-02-04T13:51:42Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split up the declaration of the \"ret\" and \"re_allocated\"\nvariables. It's not our usual style to group variable declarations\nsimply because they share a type, we'd only prefer to do so when the\ntwo are closely related (e.g. \"int i, j\"). This change makes a\nsubsequent and meaningful change's diff smaller.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex 8be57f48de7..ecc77973292 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2118,7 +2118,8 @@ static int index_mem(struct index_state *istate,\n \t\t     enum object_type type,\n \t\t     const char *path, unsigned flags)\n {\n-\tint ret, re_allocated = 0;\n+\tint ret;\n+\tint re_allocated = 0;\n \tint write_object = flags & HASH_WRITE_OBJECT;\n \n \tif (!type)\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447732","messageId":"patch-v2-05.11-207aec4eb64-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 05/11] object API: correct \"buf\" v.s. \"map\" mismatch in *.c and *.h","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:19Z","receivedAt":"2022-02-04T13:51:47Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the name of the second argument to check_object_signature() to\nbe \"buf\" in object-file.c, making it consistent with the prototype in\ncache..h\n\nThis fixes an inconsistency that's been with us since 2ade9340262 (Add\n\"check_sha1_signature()\" helper function, 2005-04-08), and makes a\nsubsequent commit's diff smaller, as we'll move these API docs to\ncache.h.\n\nWhile we're at it fix a small grammar error in the documentation,\ndropping an \"an\" before \"in-core object-data\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex 59eb793e0ac..271acf4dd15 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1067,13 +1067,13 @@ int format_object_header(char *str, size_t size, enum object_type type,\n }\n \n /*\n- * With an in-core object data in \"map\", rehash it to make sure the\n+ * With in-core object data in \"buf\", rehash it to make sure the\n  * object name actually matches \"oid\" to detect object corruption.\n- * With \"map\" == NULL, try reading the object named with \"oid\" using\n+ * With \"buf\" == NULL, try reading the object named with \"oid\" using\n  * the streaming interface and rehash it to do the same.\n  */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *map, unsigned long size, const char *type,\n+\t\t\t   void *buf, unsigned long size, const char *type,\n \t\t\t   struct object_id *real_oidp)\n {\n \tstruct object_id tmp;\n@@ -1084,8 +1084,8 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen;\n \n-\tif (map) {\n-\t\thash_object_file(r->hash_algo, map, size, type, real_oid);\n+\tif (buf) {\n+\t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n \t\treturn !oideq(oid, real_oid) ? -1 : 0;\n \t}\n \n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447733","messageId":"patch-v2-06.11-636a647ac51-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 06/11] object API: make check_object_signature() oideq()-like, move docs","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:20Z","receivedAt":"2022-02-04T13:51:48Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Make the return value of check_object_signature() behave like oideq()\nand memcmp() instead of returning negative values on failure.\n\nThis reduces the boilerplate required when calling the function, and\nmakes the calling code behave the same is if though we'd called\noideq(), which is basically what we're doing here. We already had some\ncallers using \"f() < 0\", with others using \"!f()\". Instead of\ndeclaring the latter a bug let's convert all callers to it.\n\nIt is unfortunate that there's also cases where we \"return -1\" on\nvarious errors, and we can't tell those apart from the expected OID\nbeing less than the real OID, but this was the case already.\n\nThis change is rather dangerous stand-alone as we're changing the\nreturn semantics, but not changing the prototype. Therefore any\nout-of-tree code rebased on this change would start doing the opposite\nof what it was meant to do. In a subsequent commit we'll make that a\nnon-issue by changing the signature of the function, ensuring that the\ncompiler will catch any such misuse.\n\nWhile we're at it let's re-flow some of the callers to wrap at 79\ncharacters, and move the API documentation to cache.h, where the\nprototype of this function lives.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/fast-export.c |  4 ++--\n builtin/index-pack.c  |  5 ++---\n builtin/mktag.c       |  5 ++---\n cache.h               |  9 +++++++++\n object-file.c         | 16 +++++-----------\n object.c              |  6 +++---\n pack-check.c          |  4 ++--\n 7 files changed, 25 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex 9f1c730e587..7a79cb186b1 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -299,8 +299,8 @@ static void export_blob(const struct object_id *oid)\n \t\tbuf = read_object_file(oid, &type, &size);\n \t\tif (!buf)\n \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n-\t\tif (check_object_signature(the_repository, oid, buf, size,\n-\t\t\t\t\t   type_name(type), NULL) < 0)\n+\t\tif (!check_object_signature(the_repository, oid, buf, size,\n+\t\t\t\t\t    type_name(type), NULL))\n \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n \t\tobject = parse_object_buffer(the_repository, oid, type,\n \t\t\t\t\t     size, buf, &eaten);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 01574378ce2..6db3e728ff4 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1412,9 +1412,8 @@ static void fix_unresolved_deltas(struct hashfile *f)\n \t\tif (!data)\n \t\t\tcontinue;\n \n-\t\tif (check_object_signature(the_repository, &d->oid,\n-\t\t\t\t\t   data, size,\n-\t\t\t\t\t   type_name(type), NULL))\n+\t\tif (!check_object_signature(the_repository, &d->oid, data,\n+\t\t\t\t\t    size, type_name(type), NULL))\n \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n \n \t\t/*\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 96a3686af53..a715bf53cf0 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -61,9 +61,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n \t\t    type_name(*tagged_type), type_name(type));\n \n \trepl = lookup_replace_object(the_repository, tagged_oid);\n-\tret = check_object_signature(the_repository, repl,\n-\t\t\t\t     buffer, size, type_name(*tagged_type),\n-\t\t\t\t     NULL);\n+\tret = !check_object_signature(the_repository, repl, buffer, size,\n+\t\t\t\t      type_name(*tagged_type), NULL);\n \tfree(buffer);\n \n \treturn ret;\ndiff --git a/cache.h b/cache.h\nindex 281f00ab1b1..3a156dcb37b 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1319,6 +1319,15 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,\n struct object_info;\n int parse_loose_header(const char *hdr, struct object_info *oi);\n \n+/**\n+ * With in-core object data in \"buf\", rehash it to make sure the\n+ * object name actually matches \"oid\" to detect object corruption.\n+ * With \"buf\" == NULL, try reading the object named with \"oid\" using\n+ * the streaming interface and rehash it to do the same.\n+ *\n+ * Treat the return value like oideq() (which is like memcmp()),\n+ * except that negative values might also indicate a generic error.\n+ */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\t\t   void *buf, unsigned long size, const char *type,\n \t\t\t   struct object_id *real_oidp);\ndiff --git a/object-file.c b/object-file.c\nindex 271acf4dd15..4c38ddad5dc 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1066,12 +1066,6 @@ int format_object_header(char *str, size_t size, enum object_type type,\n \treturn format_object_header_literally(str, size, name, objsize);\n }\n \n-/*\n- * With in-core object data in \"buf\", rehash it to make sure the\n- * object name actually matches \"oid\" to detect object corruption.\n- * With \"buf\" == NULL, try reading the object named with \"oid\" using\n- * the streaming interface and rehash it to do the same.\n- */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\t\t   void *buf, unsigned long size, const char *type,\n \t\t\t   struct object_id *real_oidp)\n@@ -1086,7 +1080,7 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \n \tif (buf) {\n \t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n-\t\treturn !oideq(oid, real_oid) ? -1 : 0;\n+\t\treturn oideq(oid, real_oid);\n \t}\n \n \tst = open_istream(r, oid, &obj_type, &size, NULL);\n@@ -1113,7 +1107,7 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \t}\n \tr->hash_algo->final_oid_fn(real_oid, &c);\n \tclose_istream(st);\n-\treturn !oideq(oid, real_oid) ? -1 : 0;\n+\treturn oideq(oid, real_oid);\n }\n \n int git_open_cloexec(const char *name, int flags)\n@@ -2617,9 +2611,9 @@ int read_loose_object(const char *path,\n \t\t\tgit_inflate_end(&stream);\n \t\t\tgoto out;\n \t\t}\n-\t\tif (check_object_signature(the_repository, expected_oid,\n-\t\t\t\t\t   *contents, *size,\n-\t\t\t\t\t   oi->type_name->buf, real_oid))\n+\t\tif (!check_object_signature(the_repository, expected_oid,\n+\t\t\t\t\t    *contents, *size,\n+\t\t\t\t\t    oi->type_name->buf, real_oid))\n \t\t\tgoto out;\n \t}\n \ndiff --git a/object.c b/object.c\nindex c37501fc120..b778b32407d 100644\n--- a/object.c\n+++ b/object.c\n@@ -279,7 +279,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n \t    (!obj && repo_has_object_file(r, oid) &&\n \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n-\t\tif (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) {\n+\t\tif (!check_object_signature(r, repl, NULL, 0, NULL, NULL)) {\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n \t\t\treturn NULL;\n \t\t}\n@@ -289,8 +289,8 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \n \tbuffer = repo_read_object_file(r, oid, &type, &size);\n \tif (buffer) {\n-\t\tif (check_object_signature(r, repl, buffer, size,\n-\t\t\t\t\t   type_name(type), NULL) < 0) {\n+\t\tif (!check_object_signature(r, repl, buffer, size,\n+\t\t\t\t\t    type_name(type), NULL)) {\n \t\t\tfree(buffer);\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n \t\t\treturn NULL;\ndiff --git a/pack-check.c b/pack-check.c\nindex 3f418e3a6af..35cca10057c 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -142,8 +142,8 @@ static int verify_packfile(struct repository *r,\n \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n \t\t\t\t    (uintmax_t)entries[i].offset);\n-\t\telse if (check_object_signature(r, &oid, data, size,\n-\t\t\t\t\t\ttype_name(type), NULL))\n+\t\telse if (!check_object_signature(r, &oid, data, size,\n+\t\t\t\t\t\t type_name(type), NULL))\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n \t\telse if (fn) {\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447734","messageId":"patch-v2-07.11-c38af53e889-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 07/11] object-file API: split up and simplify check_object_signature()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:21Z","receivedAt":"2022-02-04T13:51:49Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split up the check_object_signature() function into that non-streaming\nversion (it accepts an already filled \"buf\"), and a new\nstream_object_signature() which will retrieve the object from storage,\nand hash it on-the-fly.\n\nAll of the callers of check_object_signature() were effectively\ncalling two different functions, if we go by cyclomatic\ncomplexity. I.e. they'd either take the early \"if (map)\" branch and\nreturn early, or not. This has been the case since the \"if (map)\"\ncondition was added in 090ea12671b (parse_object: avoid putting whole\nblob in core, 2012-03-07).\n\nWe can then further simplify the resulting check_object_signature()\nfunction since only one caller wanted to pass a non-NULL \"buf\" and a\nnon-NULL \"real_oidp\". That \"read_loose_object()\" codepath used by \"git\nfsck\" can instead use hash_object_file() followed by oideq().\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/fast-export.c |  2 +-\n builtin/index-pack.c  |  2 +-\n builtin/mktag.c       |  2 +-\n cache.h               | 12 ++++++++----\n object-file.c         | 33 +++++++++++++++++++--------------\n object.c              |  4 ++--\n pack-check.c          |  9 ++++++---\n 7 files changed, 38 insertions(+), 26 deletions(-)\n\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex 7a79cb186b1..1878ec34960 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -300,7 +300,7 @@ static void export_blob(const struct object_id *oid)\n \t\tif (!buf)\n \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n \t\tif (!check_object_signature(the_repository, oid, buf, size,\n-\t\t\t\t\t    type_name(type), NULL))\n+\t\t\t\t\t    type_name(type)))\n \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n \t\tobject = parse_object_buffer(the_repository, oid, type,\n \t\t\t\t\t     size, buf, &eaten);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 6db3e728ff4..eaa7b6698d1 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1413,7 +1413,7 @@ static void fix_unresolved_deltas(struct hashfile *f)\n \t\t\tcontinue;\n \n \t\tif (!check_object_signature(the_repository, &d->oid, data,\n-\t\t\t\t\t    size, type_name(type), NULL))\n+\t\t\t\t\t    size, type_name(type)))\n \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n \n \t\t/*\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex a715bf53cf0..1282e8cd9e2 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -62,7 +62,7 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n \n \trepl = lookup_replace_object(the_repository, tagged_oid);\n \tret = !check_object_signature(the_repository, repl, buffer, size,\n-\t\t\t\t      type_name(*tagged_type), NULL);\n+\t\t\t\t      type_name(*tagged_type));\n \tfree(buffer);\n \n \treturn ret;\ndiff --git a/cache.h b/cache.h\nindex 3a156dcb37b..5a13bbfd904 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1322,15 +1322,19 @@ int parse_loose_header(const char *hdr, struct object_info *oi);\n /**\n  * With in-core object data in \"buf\", rehash it to make sure the\n  * object name actually matches \"oid\" to detect object corruption.\n- * With \"buf\" == NULL, try reading the object named with \"oid\" using\n- * the streaming interface and rehash it to do the same.\n  *\n  * Treat the return value like oideq() (which is like memcmp()),\n  * except that negative values might also indicate a generic error.\n  */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type,\n-\t\t\t   struct object_id *real_oidp);\n+\t\t\t   void *buf, unsigned long size, const char *type);\n+\n+/**\n+ * A streaming version of check_object_signature().\n+ * Try reading the object named with \"oid\" using\n+ * the streaming interface and rehash it to do the same.\n+ */\n+int stream_object_signature(struct repository *r, const struct object_id *oid);\n \n int finalize_object_file(const char *tmpfile, const char *filename);\n \ndiff --git a/object-file.c b/object-file.c\nindex 4c38ddad5dc..937a107c5ab 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1067,22 +1067,25 @@ int format_object_header(char *str, size_t size, enum object_type type,\n }\n \n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type,\n-\t\t\t   struct object_id *real_oidp)\n+\t\t\t   void *buf, unsigned long size, const char *type)\n {\n-\tstruct object_id tmp;\n-\tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n+\tstruct object_id real_oid;\n+\n+\thash_object_file(r->hash_algo, buf, size, type, &real_oid);\n+\n+\treturn oideq(oid, &real_oid);\n+}\n+\n+int stream_object_signature(struct repository *r, const struct object_id *oid)\n+{\n+\tstruct object_id real_oid;\n+\tunsigned long size;\n \tenum object_type obj_type;\n \tstruct git_istream *st;\n \tgit_hash_ctx c;\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen;\n \n-\tif (buf) {\n-\t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n-\t\treturn oideq(oid, real_oid);\n-\t}\n-\n \tst = open_istream(r, oid, &obj_type, &size, NULL);\n \tif (!st)\n \t\treturn -1;\n@@ -1105,9 +1108,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\t\tbreak;\n \t\tr->hash_algo->update_fn(&c, buf, readlen);\n \t}\n-\tr->hash_algo->final_oid_fn(real_oid, &c);\n+\tr->hash_algo->final_oid_fn(&real_oid, &c);\n \tclose_istream(st);\n-\treturn oideq(oid, real_oid);\n+\treturn oideq(oid, &real_oid);\n }\n \n int git_open_cloexec(const char *name, int flags)\n@@ -2611,9 +2614,11 @@ int read_loose_object(const char *path,\n \t\t\tgit_inflate_end(&stream);\n \t\t\tgoto out;\n \t\t}\n-\t\tif (!check_object_signature(the_repository, expected_oid,\n-\t\t\t\t\t    *contents, *size,\n-\t\t\t\t\t    oi->type_name->buf, real_oid))\n+\n+\t\thash_object_file(the_repository->hash_algo,\n+\t\t\t\t *contents, *size, oi->type_name->buf,\n+\t\t\t\t real_oid);\n+\t\tif (!oideq(expected_oid, real_oid))\n \t\t\tgoto out;\n \t}\n \ndiff --git a/object.c b/object.c\nindex b778b32407d..b3f9cd5c8cd 100644\n--- a/object.c\n+++ b/object.c\n@@ -279,7 +279,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n \t    (!obj && repo_has_object_file(r, oid) &&\n \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n-\t\tif (!check_object_signature(r, repl, NULL, 0, NULL, NULL)) {\n+\t\tif (!stream_object_signature(r, repl)) {\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n \t\t\treturn NULL;\n \t\t}\n@@ -290,7 +290,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \tbuffer = repo_read_object_file(r, oid, &type, &size);\n \tif (buffer) {\n \t\tif (!check_object_signature(r, repl, buffer, size,\n-\t\t\t\t\t    type_name(type), NULL)) {\n+\t\t\t\t\t    type_name(type))) {\n \t\t\tfree(buffer);\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n \t\t\treturn NULL;\ndiff --git a/pack-check.c b/pack-check.c\nindex 35cca10057c..4a27e77704b 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -127,7 +127,7 @@ static int verify_packfile(struct repository *r,\n \n \t\tif (type == OBJ_BLOB && big_file_threshold <= size) {\n \t\t\t/*\n-\t\t\t * Let check_object_signature() check it with\n+\t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\n \t\t\t * the data in-core only to discard.\n \t\t\t */\n@@ -142,8 +142,11 @@ static int verify_packfile(struct repository *r,\n \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n \t\t\t\t    (uintmax_t)entries[i].offset);\n-\t\telse if (!check_object_signature(r, &oid, data, size,\n-\t\t\t\t\t\t type_name(type), NULL))\n+\t\telse if (data && !check_object_signature(r, &oid, data, size,\n+\t\t\t\t\t\t\t type_name(type)))\n+\t\t\terr = error(\"packed %s from %s is corrupt\",\n+\t\t\t\t    oid_to_hex(&oid), p->pack_name);\n+\t\telse if (!data && !stream_object_signature(r, &oid))\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n \t\telse if (fn) {\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447735","messageId":"patch-v2-08.11-a5ebd04d462-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 08/11] object API: rename hash_object_file_literally() to write_*()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:22Z","receivedAt":"2022-02-04T13:51:53Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Before 0c3db67cc81 (hash-object --literally: fix buffer overrun with\nextra-long object type, 2015-05-04) the hash-object code being changed\nhere called write_sha1_file() to both hash and write a loose\nobject. Before that we'd use hash_sha1_file() to if \"-w\" wasn't\nprovided, and otherwise call write_sha1_file().\n\nNow we'll always call the same function for both writing. Let's rename\nit from hash_*_literally() to write_*_literally(). Even though the\nwrite_*() might not actually write if HASH_WRITE_OBJECT isn't in\n\"flags\", having it be more similar to write_object_file_flags() than\nhash_object_file(), but carrying a name that would suggest that it's a\nvariant of the latter is confusing.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/hash-object.c | 2 +-\n object-file.c         | 6 +++---\n object-store.h        | 6 +++---\n 3 files changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex c7b3ad74c60..f4cbd9c4ae3 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -25,7 +25,7 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig\n \tif (strbuf_read(&buf, fd, 4096) < 0)\n \t\tret = -1;\n \telse\n-\t\tret = hash_object_file_literally(buf.buf, buf.len, type, oid,\n+\t\tret = write_object_file_literally(buf.buf, buf.len, type, oid,\n \t\t\t\t\t\t flags);\n \tstrbuf_release(&buf);\n \treturn ret;\ndiff --git a/object-file.c b/object-file.c\nindex 937a107c5ab..a68af32308e 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2027,9 +2027,9 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \treturn write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags);\n }\n \n-int hash_object_file_literally(const void *buf, unsigned long len,\n-\t\t\t       const char *type, struct object_id *oid,\n-\t\t\t       unsigned flags)\n+int write_object_file_literally(const void *buf, unsigned long len,\n+\t\t\t\tconst char *type, struct object_id *oid,\n+\t\t\t\tunsigned flags)\n {\n \tchar *header;\n \tint hdrlen, status = 0;\ndiff --git a/object-store.h b/object-store.h\nindex eab1e2a967e..29169d117f7 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -258,9 +258,9 @@ static inline int write_object_file(const void *buf, unsigned long len,\n \treturn write_object_file_flags(buf, len, type, oid, 0);\n }\n \n-int hash_object_file_literally(const void *buf, unsigned long len,\n-\t\t\t       const char *type, struct object_id *oid,\n-\t\t\t       unsigned flags);\n+int write_object_file_literally(const void *buf, unsigned long len,\n+\t\t\t\tconst char *type, struct object_id *oid,\n+\t\t\t\tunsigned flags);\n \n /*\n  * Add an object file to the in-memory object store, without writing it\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447736","messageId":"patch-v2-09.11-40647be525b-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 09/11] object-file API: have hash_object_file() take \"enum object_type\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:23Z","receivedAt":"2022-02-04T13:51:59Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the hash_object_file() function to take an \"enum\nobject_type\".\n\nSince a preceding commit all of its callers are passing either\n\"{commit,tree,blob,tag}_type\", or the result of a call to type_name(),\nthe parse_object() caller that would pass NULL is now using\nstream_object_signature().\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n apply.c                  |  4 ++--\n builtin/fast-export.c    |  2 +-\n builtin/index-pack.c     |  4 ++--\n builtin/mktag.c          |  2 +-\n builtin/replace.c        |  2 +-\n builtin/unpack-objects.c |  2 +-\n cache-tree.c             |  6 +++---\n cache.h                  |  3 ++-\n convert.c                |  2 +-\n diffcore-rename.c        |  2 +-\n dir.c                    |  2 +-\n log-tree.c               |  2 +-\n object-file.c            | 35 +++++++++++++++++++++--------------\n object-store.h           |  2 +-\n object.c                 |  3 +--\n pack-check.c             |  2 +-\n 16 files changed, 41 insertions(+), 34 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex e82a7c30f01..8513755e254 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -3157,7 +3157,7 @@ static int apply_binary(struct apply_state *state,\n \t\t * See if the old one matches what the patch\n \t\t * applies to.\n \t\t */\n-\t\thash_object_file(the_hash_algo, img->buf, img->len, blob_type,\n+\t\thash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,\n \t\t\t\t &oid);\n \t\tif (strcmp(oid_to_hex(&oid), patch->old_oid_prefix))\n \t\t\treturn error(_(\"the patch applies to '%s' (%s), \"\n@@ -3203,7 +3203,7 @@ static int apply_binary(struct apply_state *state,\n \t\t\t\t     name);\n \n \t\t/* verify that the result matches */\n-\t\thash_object_file(the_hash_algo, img->buf, img->len, blob_type,\n+\t\thash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,\n \t\t\t\t &oid);\n \t\tif (strcmp(oid_to_hex(&oid), patch->new_oid_prefix))\n \t\t\treturn error(_(\"binary patch to '%s' creates incorrect result (expecting %s, got %s)\"),\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex 1878ec34960..187985666e7 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -300,7 +300,7 @@ static void export_blob(const struct object_id *oid)\n \t\tif (!buf)\n \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n \t\tif (!check_object_signature(the_repository, oid, buf, size,\n-\t\t\t\t\t    type_name(type)))\n+\t\t\t\t\t    type))\n \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n \t\tobject = parse_object_buffer(the_repository, oid, type,\n \t\t\t\t\t     size, buf, &eaten);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex eaa7b6698d1..1c0d3971074 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -970,7 +970,7 @@ static struct base_data *resolve_delta(struct object_entry *delta_obj,\n \tif (!result_data)\n \t\tbad_object(delta_obj->idx.offset, _(\"failed to apply delta\"));\n \thash_object_file(the_hash_algo, result_data, result_size,\n-\t\t\t type_name(delta_obj->real_type), &delta_obj->idx.oid);\n+\t\t\t delta_obj->real_type, &delta_obj->idx.oid);\n \tsha1_object(result_data, NULL, result_size, delta_obj->real_type,\n \t\t    &delta_obj->idx.oid);\n \n@@ -1413,7 +1413,7 @@ static void fix_unresolved_deltas(struct hashfile *f)\n \t\t\tcontinue;\n \n \t\tif (!check_object_signature(the_repository, &d->oid, data,\n-\t\t\t\t\t    size, type_name(type)))\n+\t\t\t\t\t    size, type))\n \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n \n \t\t/*\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 1282e8cd9e2..bebc88faed0 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -62,7 +62,7 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n \n \trepl = lookup_replace_object(the_repository, tagged_oid);\n \tret = !check_object_signature(the_repository, repl, buffer, size,\n-\t\t\t\t      type_name(*tagged_type));\n+\t\t\t\t     *tagged_type);\n \tfree(buffer);\n \n \treturn ret;\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 995ca683302..53a3b246570 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -409,7 +409,7 @@ static int check_one_mergetag(struct commit *commit,\n \tint i;\n \n \thash_object_file(the_hash_algo, extra->value, extra->len,\n-\t\t\t type_name(OBJ_TAG), &tag_oid);\n+\t\t\t OBJ_TAG, &tag_oid);\n \ttag = lookup_tag(the_repository, &tag_oid);\n \tif (!tag)\n \t\treturn error(_(\"bad mergetag in commit '%s'\"), ref);\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 808041551fd..dbeb0680a58 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -266,7 +266,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t} else {\n \t\tstruct object *obj;\n \t\tint eaten;\n-\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n+\t\thash_object_file(the_hash_algo, buf, size, type,\n \t\t\t\t &obj_list[nr].oid);\n \t\tadded_object(nr, type, buf, size);\n \t\tobj = parse_object_buffer(the_repository, &obj_list[nr].oid,\ndiff --git a/cache-tree.c b/cache-tree.c\nindex fdbbd191d22..6752f69d515 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -432,14 +432,14 @@ static int update_one(struct cache_tree *it,\n \tif (repair) {\n \t\tstruct object_id oid;\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n-\t\t\t\t tree_type, &oid);\n+\t\t\t\t OBJ_TREE, &oid);\n \t\tif (has_object_file_with_flags(&oid, OBJECT_INFO_SKIP_FETCH_OBJECT))\n \t\t\toidcpy(&it->oid, &oid);\n \t\telse\n \t\t\tto_invalidate = 1;\n \t} else if (dryrun) {\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n-\t\t\t\t tree_type, &it->oid);\n+\t\t\t\t OBJ_TREE, &it->oid);\n \t} else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE,\n \t\t\t\t\t   &it->oid, flags & WRITE_TREE_SILENT\n \t\t\t\t\t   ? HASH_SILENT : 0)) {\n@@ -948,7 +948,7 @@ static int verify_one(struct repository *r,\n \t\tstrbuf_addf(&tree_buf, \"%o %.*s%c\", mode, entlen, name, '\\0');\n \t\tstrbuf_add(&tree_buf, oid->hash, r->hash_algo->rawsz);\n \t}\n-\thash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, tree_type,\n+\thash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, OBJ_TREE,\n \t\t\t &new_oid);\n \tif (!oideq(&new_oid, &it->oid))\n \t\tBUG(\"cache-tree for path %.*s does not match. \"\ndiff --git a/cache.h b/cache.h\nindex 5a13bbfd904..42761bb12cb 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1327,7 +1327,8 @@ int parse_loose_header(const char *hdr, struct object_info *oi);\n  * except that negative values might also indicate a generic error.\n  */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type);\n+\t\t\t   void *map, unsigned long size,\n+\t\t\t   enum object_type type);\n \n /**\n  * A streaming version of check_object_signature().\ndiff --git a/convert.c b/convert.c\nindex df7186bd813..d88072fe320 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -1159,7 +1159,7 @@ static int ident_to_worktree(const char *src, size_t len,\n \t/* are we \"faking\" in place editing ? */\n \tif (src == buf->buf)\n \t\tto_free = strbuf_detach(buf, NULL);\n-\thash_object_file(the_hash_algo, src, len, \"blob\", &oid);\n+\thash_object_file(the_hash_algo, src, len, OBJ_BLOB, &oid);\n \n \tstrbuf_grow(buf, len + cnt * (the_hash_algo->hexsz + 3));\n \tfor (;;) {\ndiff --git a/diffcore-rename.c b/diffcore-rename.c\nindex bebd4ed6a42..c0422d9e709 100644\n--- a/diffcore-rename.c\n+++ b/diffcore-rename.c\n@@ -261,7 +261,7 @@ static unsigned int hash_filespec(struct repository *r,\n \t\tif (diff_populate_filespec(r, filespec, NULL))\n \t\t\treturn 0;\n \t\thash_object_file(r->hash_algo, filespec->data, filespec->size,\n-\t\t\t\t \"blob\", &filespec->oid);\n+\t\t\t\t OBJ_BLOB, &filespec->oid);\n \t}\n \treturn oidhash(&filespec->oid);\n }\ndiff --git a/dir.c b/dir.c\nindex d91295f2bcd..5674e8a6256 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1113,7 +1113,7 @@ static int add_patterns(const char *fname, const char *base, int baselen,\n \t\t\t\t       &istate->cache[pos]->oid);\n \t\t\telse\n \t\t\t\thash_object_file(the_hash_algo, buf, size,\n-\t\t\t\t\t\t \"blob\", &oid_stat->oid);\n+\t\t\t\t\t\t OBJ_BLOB, &oid_stat->oid);\n \t\t\tfill_stat_data(&oid_stat->stat, &st);\n \t\t\toid_stat->valid = 1;\n \t\t}\ndiff --git a/log-tree.c b/log-tree.c\nindex d3e7a40b648..27a5b0bd61a 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -561,7 +561,7 @@ static int show_one_mergetag(struct commit *commit,\n \tstruct strbuf signature = STRBUF_INIT;\n \n \thash_object_file(the_hash_algo, extra->value, extra->len,\n-\t\t\t type_name(OBJ_TAG), &oid);\n+\t\t\t OBJ_TAG, &oid);\n \ttag = lookup_tag(the_repository, &oid);\n \tif (!tag)\n \t\treturn -1; /* error message already given */\ndiff --git a/object-file.c b/object-file.c\nindex a68af32308e..97a3493f5fb 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1067,7 +1067,8 @@ int format_object_header(char *str, size_t size, enum object_type type,\n }\n \n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type)\n+\t\t\t   void *buf, unsigned long size,\n+\t\t\t   enum object_type type)\n {\n \tstruct object_id real_oid;\n \n@@ -1676,7 +1677,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,\n {\n \tstruct cached_object *co;\n \n-\thash_object_file(the_hash_algo, buf, len, type_name(type), oid);\n+\thash_object_file(the_hash_algo, buf, len, type, oid);\n \tif (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) ||\n \t    find_cached_object(oid))\n \t\treturn 0;\n@@ -1850,15 +1851,23 @@ static int write_buffer(int fd, const void *buf, size_t len)\n \treturn 0;\n }\n \n-void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t     unsigned long len, const char *type,\n-\t\t     struct object_id *oid)\n+static void hash_object_file_literally(const struct git_hash_algo *algo,\n+\t\t\t\t       const void *buf, unsigned long len,\n+\t\t\t\t       const char *type, struct object_id *oid)\n {\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n+\n \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n+void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n+\t\t      unsigned long len, enum object_type type,\n+\t\t      struct object_id *oid)\n+{\n+\thash_object_file_literally(algo, buf, len, type_name(type), oid);\n+}\n+\n /* Finalize a file on disk, and close it. */\n static void close_loose_object(int fd)\n {\n@@ -2161,9 +2170,7 @@ static int index_mem(struct index_state *istate,\n \tif (write_object)\n \t\tret = write_object_file(buf, size, type, oid);\n \telse\n-\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n-\t\t\t\t oid);\n-\n+\t\thash_object_file(the_hash_algo, buf, size, type, oid);\n \tif (re_allocated)\n \t\tfree(buf);\n \treturn ret;\n@@ -2189,8 +2196,8 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\tret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB,\n \t\t\t\t\toid);\n \telse\n-\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n-\t\t\t\t type_name(OBJ_BLOB), oid);\n+\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len, OBJ_BLOB,\n+\t\t\t\t oid);\n \tstrbuf_release(&sbuf);\n \treturn ret;\n }\n@@ -2309,7 +2316,7 @@ int index_path(struct index_state *istate, struct object_id *oid,\n \t\t\treturn error_errno(\"readlink(\\\"%s\\\")\", path);\n \t\tif (!(flags & HASH_WRITE_OBJECT))\n \t\t\thash_object_file(the_hash_algo, sb.buf, sb.len,\n-\t\t\t\t\t blob_type, oid);\n+\t\t\t\t\t OBJ_BLOB, oid);\n \t\telse if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))\n \t\t\trc = error(_(\"%s: failed to insert into database\"), path);\n \t\tstrbuf_release(&sb);\n@@ -2615,9 +2622,9 @@ int read_loose_object(const char *path,\n \t\t\tgoto out;\n \t\t}\n \n-\t\thash_object_file(the_repository->hash_algo,\n-\t\t\t\t *contents, *size, oi->type_name->buf,\n-\t\t\t\t real_oid);\n+\t\thash_object_file_literally(the_repository->hash_algo,\n+\t\t\t\t\t   *contents, *size,\n+\t\t\t\t\t   oi->type_name->buf, real_oid);\n \t\tif (!oideq(expected_oid, real_oid))\n \t\t\tgoto out;\n \t}\ndiff --git a/object-store.h b/object-store.h\nindex 29169d117f7..bd2322ed8ce 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -246,7 +246,7 @@ static inline void *repo_read_object_file(struct repository *r,\n int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);\n \n void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t      unsigned long len, const char *type,\n+\t\t      unsigned long len, enum object_type type,\n \t\t      struct object_id *oid);\n \n int write_object_file_flags(const void *buf, unsigned long len,\ndiff --git a/object.c b/object.c\nindex b3f9cd5c8cd..2cc9edb7512 100644\n--- a/object.c\n+++ b/object.c\n@@ -289,8 +289,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \n \tbuffer = repo_read_object_file(r, oid, &type, &size);\n \tif (buffer) {\n-\t\tif (!check_object_signature(r, repl, buffer, size,\n-\t\t\t\t\t    type_name(type))) {\n+\t\tif (!check_object_signature(r, repl, buffer, size, type)) {\n \t\t\tfree(buffer);\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n \t\t\treturn NULL;\ndiff --git a/pack-check.c b/pack-check.c\nindex 4a27e77704b..f1df16ef9a7 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -143,7 +143,7 @@ static int verify_packfile(struct repository *r,\n \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n \t\t\t\t    (uintmax_t)entries[i].offset);\n \t\telse if (data && !check_object_signature(r, &oid, data, size,\n-\t\t\t\t\t\t\t type_name(type)))\n+\t\t\t\t\t\t\t type))\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n \t\telse if (!data && !stream_object_signature(r, &oid))\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447737","messageId":"patch-v2-10.11-e39edfbce05-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 10/11] object-file.c: add a literal version of write_object_file_prepare()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:24Z","receivedAt":"2022-02-04T13:52:15Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split off a *_literally() variant of the write_object_file_prepare()\nfunction. To do this create a new \"hash_object_body()\" static helper.\n\nWe now defer the type_name() call until the very last moment in\nformat_object_header() for those callers that aren't \"hash-object\n--literally\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c | 39 +++++++++++++++++++++++++++++----------\n 1 file changed, 29 insertions(+), 10 deletions(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex 97a3493f5fb..cba33b25197 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1784,21 +1784,40 @@ void *read_object_with_reference(struct repository *r,\n \t}\n }\n \n+static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c,\n+\t\t\t     const void *buf, unsigned long len,\n+\t\t\t     struct object_id *oid,\n+\t\t\t     char *hdr, int *hdrlen)\n+{\n+\talgo->init_fn(c);\n+\talgo->update_fn(c, hdr, *hdrlen);\n+\talgo->update_fn(c, buf, len);\n+\talgo->final_oid_fn(oid, c);\n+}\n+\n static void write_object_file_prepare(const struct git_hash_algo *algo,\n \t\t\t\t      const void *buf, unsigned long len,\n-\t\t\t\t      const char *type, struct object_id *oid,\n+\t\t\t\t      enum object_type type, struct object_id *oid,\n \t\t\t\t      char *hdr, int *hdrlen)\n {\n \tgit_hash_ctx c;\n \n \t/* Generate the header */\n-\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n+\t*hdrlen = format_object_header(hdr, *hdrlen, type, len);\n \n \t/* Sha1.. */\n-\talgo->init_fn(&c);\n-\talgo->update_fn(&c, hdr, *hdrlen);\n-\talgo->update_fn(&c, buf, len);\n-\talgo->final_oid_fn(oid, &c);\n+\thash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);\n+}\n+\n+static void write_object_file_prepare_literally(const struct git_hash_algo *algo,\n+\t\t\t\t      const void *buf, unsigned long len,\n+\t\t\t\t      const char *type, struct object_id *oid,\n+\t\t\t\t      char *hdr, int *hdrlen)\n+{\n+\tgit_hash_ctx c;\n+\n+\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n+\thash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);\n }\n \n /*\n@@ -1858,7 +1877,7 @@ static void hash_object_file_literally(const struct git_hash_algo *algo,\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n \n-\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n+\twrite_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n@@ -2029,7 +2048,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t/* Normally if we have it in the pack then we do not bother writing\n \t * it out into .git/objects/??/?{38} file.\n \t */\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type_name(type), oid, hdr,\n+\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr,\n \t\t\t\t  &hdrlen);\n \tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n \t\treturn 0;\n@@ -2046,8 +2065,8 @@ int write_object_file_literally(const void *buf, unsigned long len,\n \t/* type string, SP, %lu of the length plus NUL must fit this */\n \thdrlen = strlen(type) + MAX_HEADER_LEN;\n \theader = xmalloc(hdrlen);\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, header,\n-\t\t\t\t  &hdrlen);\n+\twrite_object_file_prepare_literally(the_hash_algo, buf, len, type,\n+\t\t\t\t\t    oid, header, &hdrlen);\n \n \tif (!(flags & HASH_WRITE_OBJECT))\n \t\tgoto cleanup;\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447738","messageId":"patch-v2-11.11-f2b1cb861a0-20220204T135005Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v2 11/11] object-file API: pass an enum to read_object_with_reference()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T13:51:25Z","receivedAt":"2022-02-04T13:52:17Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the read_object_with_reference() function to take an \"enum\nobject_type\". It was not prepared to handle an arbitrary \"const\nchar *type\", as it was itself calling type_from_string().\n\nLet's change the only caller that passes in user data to use\ntype_from_string(), and convert the rest to use e.g. \"OBJ_TREE\"\ninstead of \"tree_type\".\n\nThe \"cat-file\" caller is not on the codepath that\nhandles\"--allow-unknown\", so the type_from_string() there is safe. Its\nuse of type_from_string() doesn't functionally differ from that of the\npre-image.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/cat-file.c     | 11 +++++++----\n builtin/fast-import.c  |  6 +++---\n builtin/grep.c         |  4 ++--\n builtin/pack-objects.c |  2 +-\n cache.h                |  2 +-\n object-file.c          |  5 ++---\n tree-walk.c            |  6 +++---\n 7 files changed, 19 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex d94050e6c18..3c5bc505e0a 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -154,7 +154,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\tbreak;\n \n \tcase 0:\n-\t\tif (type_from_string(exp_type) == OBJ_BLOB) {\n+\t{\n+\t\tenum object_type exp_type_id = type_from_string(exp_type);\n+\n+\t\tif (exp_type_id == OBJ_BLOB) {\n \t\t\tstruct object_id blob_oid;\n \t\t\tif (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) {\n \t\t\t\tchar *buffer = read_object_file(&oid, &type,\n@@ -176,10 +179,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\t\t * fall-back to the usual case.\n \t\t\t */\n \t\t}\n-\t\tbuf = read_object_with_reference(the_repository,\n-\t\t\t\t\t\t &oid, exp_type, &size, NULL);\n+\t\tbuf = read_object_with_reference(the_repository, &oid,\n+\t\t\t\t\t\t exp_type_id, &size, NULL);\n \t\tbreak;\n-\n+\t}\n \tdefault:\n \t\tdie(\"git cat-file: unknown option: %s\", exp_type);\n \t}\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 123df7d9a53..c52e807f56e 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -2483,7 +2483,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa\n \t\tunsigned long size;\n \t\tchar *buf = read_object_with_reference(the_repository,\n \t\t\t\t\t\t       &commit_oid,\n-\t\t\t\t\t\t       commit_type, &size,\n+\t\t\t\t\t\t       OBJ_COMMIT, &size,\n \t\t\t\t\t\t       &commit_oid);\n \t\tif (!buf || size < the_hash_algo->hexsz + 6)\n \t\t\tdie(\"Not a valid commit: %s\", p);\n@@ -2555,7 +2555,7 @@ static void parse_from_existing(struct branch *b)\n \t\tchar *buf;\n \n \t\tbuf = read_object_with_reference(the_repository,\n-\t\t\t\t\t\t &b->oid, commit_type, &size,\n+\t\t\t\t\t\t &b->oid, OBJ_COMMIT, &size,\n \t\t\t\t\t\t &b->oid);\n \t\tparse_from_commit(b, buf, size);\n \t\tfree(buf);\n@@ -2651,7 +2651,7 @@ static struct hash_list *parse_merge(unsigned int *count)\n \t\t\tunsigned long size;\n \t\t\tchar *buf = read_object_with_reference(the_repository,\n \t\t\t\t\t\t\t       &n->oid,\n-\t\t\t\t\t\t\t       commit_type,\n+\t\t\t\t\t\t\t       OBJ_COMMIT,\n \t\t\t\t\t\t\t       &size, &n->oid);\n \t\t\tif (!buf || size < the_hash_algo->hexsz + 6)\n \t\t\t\tdie(\"Not a valid commit: %s\", from);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 9e34a820ad4..75e07b5623a 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t\tobject_type = oid_object_info(subrepo, oid, NULL);\n \t\tobj_read_unlock();\n \t\tdata = read_object_with_reference(subrepo,\n-\t\t\t\t\t\t  oid, tree_type,\n+\t\t\t\t\t\t  oid, OBJ_TREE,\n \t\t\t\t\t\t  &size, NULL);\n \t\tif (!data)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(oid));\n@@ -651,7 +651,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,\n \t\tint hit, len;\n \n \t\tdata = read_object_with_reference(opt->repo,\n-\t\t\t\t\t\t  &obj->oid, tree_type,\n+\t\t\t\t\t\t  &obj->oid, OBJ_TREE,\n \t\t\t\t\t\t  &size, NULL);\n \t\tif (!data)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(&obj->oid));\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex ba2006f2212..c4df3df3141 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1802,7 +1802,7 @@ static void add_preferred_base(struct object_id *oid)\n \t\treturn;\n \n \tdata = read_object_with_reference(the_repository, oid,\n-\t\t\t\t\t  tree_type, &size, &tree_oid);\n+\t\t\t\t\t  OBJ_TREE, &size, &tree_oid);\n \tif (!data)\n \t\treturn;\n \ndiff --git a/cache.h b/cache.h\nindex 42761bb12cb..357f4cb642f 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1561,7 +1561,7 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char\n \n void *read_object_with_reference(struct repository *r,\n \t\t\t\t const struct object_id *oid,\n-\t\t\t\t const char *required_type,\n+\t\t\t\t enum object_type required_type,\n \t\t\t\t unsigned long *size,\n \t\t\t\t struct object_id *oid_ret);\n \ndiff --git a/object-file.c b/object-file.c\nindex cba33b25197..5c9525479c2 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1737,16 +1737,15 @@ void *read_object_file_extended(struct repository *r,\n \n void *read_object_with_reference(struct repository *r,\n \t\t\t\t const struct object_id *oid,\n-\t\t\t\t const char *required_type_name,\n+\t\t\t\t enum object_type required_type,\n \t\t\t\t unsigned long *size,\n \t\t\t\t struct object_id *actual_oid_return)\n {\n-\tenum object_type type, required_type;\n+\tenum object_type type;\n \tvoid *buffer;\n \tunsigned long isize;\n \tstruct object_id actual_oid;\n \n-\trequired_type = type_from_string(required_type_name);\n \toidcpy(&actual_oid, oid);\n \twhile (1) {\n \t\tint ref_length = -1;\ndiff --git a/tree-walk.c b/tree-walk.c\nindex 3a94959d64a..506234b4b81 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -89,7 +89,7 @@ void *fill_tree_descriptor(struct repository *r,\n \tvoid *buf = NULL;\n \n \tif (oid) {\n-\t\tbuf = read_object_with_reference(r, oid, tree_type, &size, NULL);\n+\t\tbuf = read_object_with_reference(r, oid, OBJ_TREE, &size, NULL);\n \t\tif (!buf)\n \t\t\tdie(\"unable to read tree %s\", oid_to_hex(oid));\n \t}\n@@ -605,7 +605,7 @@ int get_tree_entry(struct repository *r,\n \tunsigned long size;\n \tstruct object_id root;\n \n-\ttree = read_object_with_reference(r, tree_oid, tree_type, &size, &root);\n+\ttree = read_object_with_reference(r, tree_oid, OBJ_TREE, &size, &root);\n \tif (!tree)\n \t\treturn -1;\n \n@@ -677,7 +677,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r,\n \t\t\tunsigned long size;\n \t\t\ttree = read_object_with_reference(r,\n \t\t\t\t\t\t\t  &current_tree_oid,\n-\t\t\t\t\t\t\t  tree_type, &size,\n+\t\t\t\t\t\t\t  OBJ_TREE, &size,\n \t\t\t\t\t\t\t  &root);\n \t\t\tif (!tree)\n \t\t\t\tgoto done;\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447766","messageId":"xmqqtudel5hj.fsf@gitster.g","threadId":"57347","inReplyTo":"patch-v2-04.11-d259f901114-20220204T135005Z-avarab@gmail.com","subject":"Re: [PATCH v2 04/11] object-file API: have write_object_file() take \"enum object_type\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-02-04T20:52:08Z","receivedAt":"2022-02-04T20:52:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> diff --git a/builtin/notes.c b/builtin/notes.c\n> index 05d60483e82..d81acaeaf78 100644\n> --- a/builtin/notes.c\n> +++ b/builtin/notes.c\n> @@ -199,9 +199,8 @@ static void prepare_note_data(const struct object_id *object, struct note_data *\n>  \n>  static void write_note_data(struct note_data *d, struct object_id *oid)\n>  {\n> -\tif (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) {\n> +\tif (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) {\n>  \t\tint status = die_message(_(\"unable to write note object\"));\n> -\n>  \t\tif (d->edit_path)\n\nUnrelated change here.  It would be OK if it were an improvement,\nbut it is not X-<.\n\nEverything else in this change looked sensible.\n"},{"id":"447767","messageId":"xmqqo83ml5dg.fsf@gitster.g","threadId":"57347","inReplyTo":"patch-v2-05.11-207aec4eb64-20220204T135005Z-avarab@gmail.com","subject":"Re: [PATCH v2 05/11] object API: correct \"buf\" v.s. \"map\" mismatch in *.c and *.h","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-02-04T20:54:35Z","receivedAt":"2022-02-04T20:54:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Change the name of the second argument to check_object_signature() to\n> be \"buf\" in object-file.c, making it consistent with the prototype in\n> cache..h\n\nDouble dot X-<.\n"},{"id":"447768","messageId":"xmqqczk2l4f1.fsf@gitster.g","threadId":"57347","inReplyTo":"patch-v2-06.11-636a647ac51-20220204T135005Z-avarab@gmail.com","subject":"Re: [PATCH v2 06/11] object API: make check_object_signature() oideq()-like, move docs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-02-04T21:15:14Z","receivedAt":"2022-02-04T21:15:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Make the return value of check_object_signature() behave like oideq()\n> and memcmp() instead of returning negative values on failure.\n\nFirst of all, oideq() and memcmp() behave completely oppositely to\neach other.  When given two same things, eq() says \"true\" and cmp()\nsays 0.  They use the opposite polarity.  Which one do you want?\n\nI am not enthused to see a function that used to signal success with\n0 and failure with a negative value to suddenly start returning 1\nfor \"they are identical\" and 0 for \"they are not the same\", without\nchanging its name or parameters to help compilers catch new call\nsites that still expect the old behaviour (hence can use \"ret < 0\",\nand \"ret\" interchangeably to check for \"failure - the given data\ndoes not hash to the object name\").\n\n> This reduces the boilerplate required when calling the function, and\n> makes the calling code behave the same is if though we'd called\n> oideq(), which is basically what we're doing here. We already had some\n> callers using \"f() < 0\", with others using \"!f()\". Instead of\n> declaring the latter a bug let's convert all callers to it.\n>\n> It is unfortunate that there's also cases where we \"return -1\" on\n> various errors, and we can't tell those apart from the expected OID\n> being less than the real OID, but this was the case already.\n\nWell, it is not checking \"less than\" to begin with, no?  The point\nof calling this function is to see if the \"object_signature\" (aka\n\"hash\") is correct for the object data we have, and yield yes/no (or\nsuccess or failure) answer.  If we encountered an error while trying\nto compute that answer, well, we failed to ensure that the hash\nmatches the contents, so it is reasonable to say \"no, it does not\nmatch\".\n\n> This change is rather dangerous stand-alone as we're changing the\n> return semantics, but not changing the prototype.\n\nYes, if you know it, why do it and have reviewers spend their cycles?\n\nIf the function is renamed so that its name ends with \"eq\" or\n\"matches\" (e.g. object_signature_matches()), such a change may be\njustified, though.\n"},{"id":"447787","messageId":"patch-v3-01.12-53334bc970a-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 01/12] object-file.c: split up declaration of unrelated variables","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:23Z","receivedAt":"2022-02-04T23:48:46Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split up the declaration of the \"ret\" and \"re_allocated\"\nvariables. It's not our usual style to group variable declarations\nsimply because they share a type, we'd only prefer to do so when the\ntwo are closely related (e.g. \"int i, j\"). This change makes a\nsubsequent and meaningful change's diff smaller.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex 8be57f48de7..ecc77973292 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2118,7 +2118,8 @@ static int index_mem(struct index_state *istate,\n \t\t     enum object_type type,\n \t\t     const char *path, unsigned flags)\n {\n-\tint ret, re_allocated = 0;\n+\tint ret;\n+\tint re_allocated = 0;\n \tint write_object = flags & HASH_WRITE_OBJECT;\n \n \tif (!type)\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447788","messageId":"patch-v3-02.12-5ba49778ac1-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 02/12] object-file API: return \"void\", not \"int\" from hash_object_file()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:24Z","receivedAt":"2022-02-04T23:48:48Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"The hash_object_file() function added in abdc3fc8421 (Add\nhash_sha1_file(), 2006-10-14) did not have a meaningful return value,\nand it never has.\n\nOne was seemingly added to avoid adding braces to the \"ret = \"\nassignments being modified here. Let's instead assign \"0\" to the \"ret\"\nvariables at the beginning of the relevant functions, and have them\nreturn \"void\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c  | 16 ++++++++--------\n object-store.h |  6 +++---\n 2 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex ecc77973292..eeb6814780a 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1836,14 +1836,13 @@ static int write_buffer(int fd, const void *buf, size_t len)\n \treturn 0;\n }\n \n-int hash_object_file(const struct git_hash_algo *algo, const void *buf,\n+void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \t\t     unsigned long len, const char *type,\n \t\t     struct object_id *oid)\n {\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n-\treturn 0;\n }\n \n /* Finalize a file on disk, and close it. */\n@@ -2118,7 +2117,7 @@ static int index_mem(struct index_state *istate,\n \t\t     enum object_type type,\n \t\t     const char *path, unsigned flags)\n {\n-\tint ret;\n+\tint ret = 0;\n \tint re_allocated = 0;\n \tint write_object = flags & HASH_WRITE_OBJECT;\n \n@@ -2148,8 +2147,9 @@ static int index_mem(struct index_state *istate,\n \tif (write_object)\n \t\tret = write_object_file(buf, size, type_name(type), oid);\n \telse\n-\t\tret = hash_object_file(the_hash_algo, buf, size,\n-\t\t\t\t       type_name(type), oid);\n+\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n+\t\t\t\t oid);\n+\n \tif (re_allocated)\n \t\tfree(buf);\n \treturn ret;\n@@ -2161,7 +2161,7 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\t\t\t     const char *path,\n \t\t\t\t     unsigned flags)\n {\n-\tint ret;\n+\tint ret = 0;\n \tconst int write_object = flags & HASH_WRITE_OBJECT;\n \tstruct strbuf sbuf = STRBUF_INIT;\n \n@@ -2175,8 +2175,8 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\tret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB),\n \t\t\t\t\toid);\n \telse\n-\t\tret = hash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n-\t\t\t\t       type_name(OBJ_BLOB), oid);\n+\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n+\t\t\t\t type_name(OBJ_BLOB), oid);\n \tstrbuf_release(&sbuf);\n \treturn ret;\n }\ndiff --git a/object-store.h b/object-store.h\nindex 6f89482df03..44f6868cc9c 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -245,9 +245,9 @@ static inline void *repo_read_object_file(struct repository *r,\n /* Read and unpack an object file into memory, write memory to an object file */\n int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);\n \n-int hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t     unsigned long len, const char *type,\n-\t\t     struct object_id *oid);\n+void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n+\t\t      unsigned long len, const char *type,\n+\t\t      struct object_id *oid);\n \n int write_object_file_flags(const void *buf, unsigned long len,\n \t\t\t    const char *type, struct object_id *oid,\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447789","messageId":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com","subject":"[PATCH v3 00/12] object-file API: pass object enums, tidy up streaming interface","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:22Z","receivedAt":"2022-02-04T23:48:48Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"See the v2 for a summary and goals:\nhttps://lore.kernel.org/git/cover-v2-00.11-00000000000-20220204T135005Z-avarab@gmail.com/\n\nThis early re-roll addresses Junio's comments on it so far, i.e. the\nminor whitespace/typos, and then having the interface retain the \"if\n(f() < 0)\" interface.\n\nThe reason I'd changed it initially was because the callers used a\nmixture of \"if (f())\" and \"if (f() < 0)\", but let's just keep it as it\nis, with a couple of new patches to fix the existing callers to use\n\"if (f() < 0)\" consistently.\n\nA corresponding re-roll to the topic that depends on this one isn't\nneeded, as this part of the API wasn't used by it. For that topic see:\nhttps://lore.kernel.org/git/cover-v10-0.6-00000000000-20220204T135538Z-avarab@gmail.com/\n\nÆvar Arnfjörð Bjarmason (12):\n  object-file.c: split up declaration of unrelated variables\n  object-file API: return \"void\", not \"int\" from hash_object_file()\n  object-file API: add a format_object_header() function\n  object-file API: have write_object_file() take \"enum object_type\"\n  object API: correct \"buf\" v.s. \"map\" mismatch in *.c and *.h\n  object API docs: move check_object_signature() docs to cache.h\n  object API users + docs: check <0, not !0 with\n    check_object_signature()\n  object-file API: split up and simplify check_object_signature()\n  object API: rename hash_object_file_literally() to write_*()\n  object-file API: have hash_object_file() take \"enum object_type\"\n  object-file.c: add a literal version of write_object_file_prepare()\n  object-file API: pass an enum to read_object_with_reference()\n\n apply.c                  |  12 ++--\n builtin/cat-file.c       |  11 +--\n builtin/checkout.c       |   2 +-\n builtin/fast-export.c    |   2 +-\n builtin/fast-import.c    |  12 ++--\n builtin/grep.c           |   4 +-\n builtin/hash-object.c    |   2 +-\n builtin/index-pack.c     |  10 ++-\n builtin/mktag.c          |   9 ++-\n builtin/mktree.c         |   2 +-\n builtin/notes.c          |   2 +-\n builtin/pack-objects.c   |   2 +-\n builtin/receive-pack.c   |   2 +-\n builtin/replace.c        |   4 +-\n builtin/tag.c            |   2 +-\n builtin/unpack-objects.c |   8 +--\n bulk-checkin.c           |   4 +-\n cache-tree.c             |   8 +--\n cache.h                  |  20 +++++-\n commit.c                 |   2 +-\n convert.c                |   2 +-\n diffcore-rename.c        |   2 +-\n dir.c                    |   2 +-\n http-push.c              |   2 +-\n log-tree.c               |   2 +-\n match-trees.c            |   2 +-\n merge-ort.c              |   4 +-\n merge-recursive.c        |   2 +-\n notes-cache.c            |   2 +-\n notes.c                  |   8 +--\n object-file.c            | 145 +++++++++++++++++++++++++--------------\n object-store.h           |  24 ++++---\n object.c                 |   5 +-\n pack-check.c             |   9 ++-\n read-cache.c             |   2 +-\n tree-walk.c              |   6 +-\n 36 files changed, 202 insertions(+), 137 deletions(-)\n\nRange-diff against v2:\n -:  ----------- >  1:  53334bc970a object-file.c: split up declaration of unrelated variables\n -:  ----------- >  2:  5ba49778ac1 object-file API: return \"void\", not \"int\" from hash_object_file()\n -:  ----------- >  3:  92fd020d199 object-file API: add a format_object_header() function\n 1:  d259f901114 !  4:  795ac3dea2a object-file API: have write_object_file() take \"enum object_type\"\n    @@ builtin/notes.c: static void prepare_note_data(const struct object_id *object, s\n     -\tif (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) {\n     +\tif (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) {\n      \t\tint status = die_message(_(\"unable to write note object\"));\n    --\n    + \n      \t\tif (d->edit_path)\n    - \t\t\tdie_message(_(\"the note contents have been left in %s\"),\n    - \t\t\t\t    d->edit_path);\n     \n      ## builtin/receive-pack.c ##\n     @@ builtin/receive-pack.c: static void prepare_push_cert_sha1(struct child_process *proc)\n 2:  207aec4eb64 !  5:  6faf46277b5 object API: correct \"buf\" v.s. \"map\" mismatch in *.c and *.h\n    @@ Commit message\n     \n         Change the name of the second argument to check_object_signature() to\n         be \"buf\" in object-file.c, making it consistent with the prototype in\n    -    cache..h\n    +    cache.h\n     \n         This fixes an inconsistency that's been with us since 2ade9340262 (Add\n         \"check_sha1_signature()\" helper function, 2005-04-08), and makes a\n 3:  636a647ac51 !  6:  bdddaa3648f object API: make check_object_signature() oideq()-like, move docs\n    @@ Metadata\n     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n      ## Commit message ##\n    -    object API: make check_object_signature() oideq()-like, move docs\n    +    object API docs: move check_object_signature() docs to cache.h\n     \n    -    Make the return value of check_object_signature() behave like oideq()\n    -    and memcmp() instead of returning negative values on failure.\n    -\n    -    This reduces the boilerplate required when calling the function, and\n    -    makes the calling code behave the same is if though we'd called\n    -    oideq(), which is basically what we're doing here. We already had some\n    -    callers using \"f() < 0\", with others using \"!f()\". Instead of\n    -    declaring the latter a bug let's convert all callers to it.\n    -\n    -    It is unfortunate that there's also cases where we \"return -1\" on\n    -    various errors, and we can't tell those apart from the expected OID\n    -    being less than the real OID, but this was the case already.\n    -\n    -    This change is rather dangerous stand-alone as we're changing the\n    -    return semantics, but not changing the prototype. Therefore any\n    -    out-of-tree code rebased on this change would start doing the opposite\n    -    of what it was meant to do. In a subsequent commit we'll make that a\n    -    non-issue by changing the signature of the function, ensuring that the\n    -    compiler will catch any such misuse.\n    -\n    -    While we're at it let's re-flow some of the callers to wrap at 79\n    -    characters, and move the API documentation to cache.h, where the\n    -    prototype of this function lives.\n    +    Move the API documentation for check_object_signature() to cache.h,\n    +    where its prototype is declared. This is in preparation for adding a\n    +    companion function.\n     \n         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n    - ## builtin/fast-export.c ##\n    -@@ builtin/fast-export.c: static void export_blob(const struct object_id *oid)\n    - \t\tbuf = read_object_file(oid, &type, &size);\n    - \t\tif (!buf)\n    - \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n    --\t\tif (check_object_signature(the_repository, oid, buf, size,\n    --\t\t\t\t\t   type_name(type), NULL) < 0)\n    -+\t\tif (!check_object_signature(the_repository, oid, buf, size,\n    -+\t\t\t\t\t    type_name(type), NULL))\n    - \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n    - \t\tobject = parse_object_buffer(the_repository, oid, type,\n    - \t\t\t\t\t     size, buf, &eaten);\n    -\n    - ## builtin/index-pack.c ##\n    -@@ builtin/index-pack.c: static void fix_unresolved_deltas(struct hashfile *f)\n    - \t\tif (!data)\n    - \t\t\tcontinue;\n    - \n    --\t\tif (check_object_signature(the_repository, &d->oid,\n    --\t\t\t\t\t   data, size,\n    --\t\t\t\t\t   type_name(type), NULL))\n    -+\t\tif (!check_object_signature(the_repository, &d->oid, data,\n    -+\t\t\t\t\t    size, type_name(type), NULL))\n    - \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n    - \n    - \t\t/*\n    -\n    - ## builtin/mktag.c ##\n    -@@ builtin/mktag.c: static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n    - \t\t    type_name(*tagged_type), type_name(type));\n    - \n    - \trepl = lookup_replace_object(the_repository, tagged_oid);\n    --\tret = check_object_signature(the_repository, repl,\n    --\t\t\t\t     buffer, size, type_name(*tagged_type),\n    --\t\t\t\t     NULL);\n    -+\tret = !check_object_signature(the_repository, repl, buffer, size,\n    -+\t\t\t\t      type_name(*tagged_type), NULL);\n    - \tfree(buffer);\n    - \n    - \treturn ret;\n    -\n      ## cache.h ##\n     @@ cache.h: enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,\n      struct object_info;\n    @@ cache.h: enum unpack_loose_header_result unpack_loose_header(git_zstream *stream\n     + * object name actually matches \"oid\" to detect object corruption.\n     + * With \"buf\" == NULL, try reading the object named with \"oid\" using\n     + * the streaming interface and rehash it to do the same.\n    -+ *\n    -+ * Treat the return value like oideq() (which is like memcmp()),\n    -+ * except that negative values might also indicate a generic error.\n     + */\n      int check_object_signature(struct repository *r, const struct object_id *oid,\n      \t\t\t   void *buf, unsigned long size, const char *type,\n    @@ object-file.c: int format_object_header(char *str, size_t size, enum object_type\n      int check_object_signature(struct repository *r, const struct object_id *oid,\n      \t\t\t   void *buf, unsigned long size, const char *type,\n      \t\t\t   struct object_id *real_oidp)\n    -@@ object-file.c: int check_object_signature(struct repository *r, const struct object_id *oid,\n    - \n    - \tif (buf) {\n    - \t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n    --\t\treturn !oideq(oid, real_oid) ? -1 : 0;\n    -+\t\treturn oideq(oid, real_oid);\n    - \t}\n    - \n    - \tst = open_istream(r, oid, &obj_type, &size, NULL);\n    -@@ object-file.c: int check_object_signature(struct repository *r, const struct object_id *oid,\n    - \t}\n    - \tr->hash_algo->final_oid_fn(real_oid, &c);\n    - \tclose_istream(st);\n    --\treturn !oideq(oid, real_oid) ? -1 : 0;\n    -+\treturn oideq(oid, real_oid);\n    - }\n    - \n    - int git_open_cloexec(const char *name, int flags)\n    -@@ object-file.c: int read_loose_object(const char *path,\n    - \t\t\tgit_inflate_end(&stream);\n    - \t\t\tgoto out;\n    - \t\t}\n    --\t\tif (check_object_signature(the_repository, expected_oid,\n    --\t\t\t\t\t   *contents, *size,\n    --\t\t\t\t\t   oi->type_name->buf, real_oid))\n    -+\t\tif (!check_object_signature(the_repository, expected_oid,\n    -+\t\t\t\t\t    *contents, *size,\n    -+\t\t\t\t\t    oi->type_name->buf, real_oid))\n    - \t\t\tgoto out;\n    - \t}\n    - \n    -\n    - ## object.c ##\n    -@@ object.c: struct object *parse_object(struct repository *r, const struct object_id *oid)\n    - \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n    - \t    (!obj && repo_has_object_file(r, oid) &&\n    - \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n    --\t\tif (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) {\n    -+\t\tif (!check_object_signature(r, repl, NULL, 0, NULL, NULL)) {\n    - \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n    - \t\t\treturn NULL;\n    - \t\t}\n    -@@ object.c: struct object *parse_object(struct repository *r, const struct object_id *oid)\n    - \n    - \tbuffer = repo_read_object_file(r, oid, &type, &size);\n    - \tif (buffer) {\n    --\t\tif (check_object_signature(r, repl, buffer, size,\n    --\t\t\t\t\t   type_name(type), NULL) < 0) {\n    -+\t\tif (!check_object_signature(r, repl, buffer, size,\n    -+\t\t\t\t\t    type_name(type), NULL)) {\n    - \t\t\tfree(buffer);\n    - \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n    - \t\t\treturn NULL;\n    -\n    - ## pack-check.c ##\n    -@@ pack-check.c: static int verify_packfile(struct repository *r,\n    - \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\n    - \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n    - \t\t\t\t    (uintmax_t)entries[i].offset);\n    --\t\telse if (check_object_signature(r, &oid, data, size,\n    --\t\t\t\t\t\ttype_name(type), NULL))\n    -+\t\telse if (!check_object_signature(r, &oid, data, size,\n    -+\t\t\t\t\t\t type_name(type), NULL))\n    - \t\t\terr = error(\"packed %s from %s is corrupt\",\n    - \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n    - \t\telse if (fn) {\n -:  ----------- >  7:  75abf75a437 object API users + docs: check <0, not !0 with check_object_signature()\n 4:  c38af53e889 !  8:  478d2915731 object-file API: split up and simplify check_object_signature()\n    @@ builtin/fast-export.c\n     @@ builtin/fast-export.c: static void export_blob(const struct object_id *oid)\n      \t\tif (!buf)\n      \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n    - \t\tif (!check_object_signature(the_repository, oid, buf, size,\n    --\t\t\t\t\t    type_name(type), NULL))\n    -+\t\t\t\t\t    type_name(type)))\n    + \t\tif (check_object_signature(the_repository, oid, buf, size,\n    +-\t\t\t\t\t   type_name(type), NULL) < 0)\n    ++\t\t\t\t\t   type_name(type)) < 0)\n      \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n      \t\tobject = parse_object_buffer(the_repository, oid, type,\n      \t\t\t\t\t     size, buf, &eaten);\n    @@ builtin/index-pack.c\n     @@ builtin/index-pack.c: static void fix_unresolved_deltas(struct hashfile *f)\n      \t\t\tcontinue;\n      \n    - \t\tif (!check_object_signature(the_repository, &d->oid, data,\n    --\t\t\t\t\t    size, type_name(type), NULL))\n    -+\t\t\t\t\t    size, type_name(type)))\n    + \t\tif (check_object_signature(the_repository, &d->oid, data, size,\n    +-\t\t\t\t\t   type_name(type), NULL) < 0)\n    ++\t\t\t\t\t   type_name(type)) < 0)\n      \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n      \n      \t\t/*\n     \n      ## builtin/mktag.c ##\n     @@ builtin/mktag.c: static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n    + \t\t    type_name(*tagged_type), type_name(type));\n      \n      \trepl = lookup_replace_object(the_repository, tagged_oid);\n    - \tret = !check_object_signature(the_repository, repl, buffer, size,\n    --\t\t\t\t      type_name(*tagged_type), NULL);\n    -+\t\t\t\t      type_name(*tagged_type));\n    +-\tret = check_object_signature(the_repository, repl,\n    +-\t\t\t\t     buffer, size, type_name(*tagged_type),\n    +-\t\t\t\t     NULL);\n    ++\tret = check_object_signature(the_repository, repl, buffer, size,\n    ++\t\t\t\t     type_name(*tagged_type));\n      \tfree(buffer);\n      \n      \treturn ret;\n    @@ cache.h: int parse_loose_header(const char *hdr, struct object_info *oi);\n     - * With \"buf\" == NULL, try reading the object named with \"oid\" using\n     - * the streaming interface and rehash it to do the same.\n       *\n    -  * Treat the return value like oideq() (which is like memcmp()),\n    -  * except that negative values might also indicate a generic error.\n    +  * A negative value indicates an error, usually that the OID is not\n    +  * what we expected, but it might also indicate another error.\n       */\n      int check_object_signature(struct repository *r, const struct object_id *oid,\n     -\t\t\t   void *buf, unsigned long size, const char *type,\n    @@ object-file.c: int format_object_header(char *str, size_t size, enum object_type\n     +\n     +\thash_object_file(r->hash_algo, buf, size, type, &real_oid);\n     +\n    -+\treturn oideq(oid, &real_oid);\n    ++\treturn !oideq(oid, &real_oid) ? -1 : 0;\n     +}\n     +\n     +int stream_object_signature(struct repository *r, const struct object_id *oid)\n    @@ object-file.c: int format_object_header(char *str, size_t size, enum object_type\n      \n     -\tif (buf) {\n     -\t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n    --\t\treturn oideq(oid, real_oid);\n    +-\t\treturn !oideq(oid, real_oid) ? -1 : 0;\n     -\t}\n     -\n      \tst = open_istream(r, oid, &obj_type, &size, NULL);\n    @@ object-file.c: int check_object_signature(struct repository *r, const struct obj\n     -\tr->hash_algo->final_oid_fn(real_oid, &c);\n     +\tr->hash_algo->final_oid_fn(&real_oid, &c);\n      \tclose_istream(st);\n    --\treturn oideq(oid, real_oid);\n    -+\treturn oideq(oid, &real_oid);\n    +-\treturn !oideq(oid, real_oid) ? -1 : 0;\n    ++\treturn !oideq(oid, &real_oid) ? -1 : 0;\n      }\n      \n      int git_open_cloexec(const char *name, int flags)\n    @@ object-file.c: int read_loose_object(const char *path,\n      \t\t\tgit_inflate_end(&stream);\n      \t\t\tgoto out;\n      \t\t}\n    --\t\tif (!check_object_signature(the_repository, expected_oid,\n    --\t\t\t\t\t    *contents, *size,\n    --\t\t\t\t\t    oi->type_name->buf, real_oid))\n    -+\n    +-\t\tif (check_object_signature(the_repository, expected_oid,\n    +-\t\t\t\t\t   *contents, *size,\n    +-\t\t\t\t\t   oi->type_name->buf, real_oid) < 0)\n     +\t\thash_object_file(the_repository->hash_algo,\n     +\t\t\t\t *contents, *size, oi->type_name->buf,\n     +\t\t\t\t real_oid);\n    @@ object.c: struct object *parse_object(struct repository *r, const struct object_\n      \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n      \t    (!obj && repo_has_object_file(r, oid) &&\n      \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n    --\t\tif (!check_object_signature(r, repl, NULL, 0, NULL, NULL)) {\n    -+\t\tif (!stream_object_signature(r, repl)) {\n    +-\t\tif (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) {\n    ++\t\tif (stream_object_signature(r, repl) < 0) {\n      \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n      \t\t\treturn NULL;\n      \t\t}\n     @@ object.c: struct object *parse_object(struct repository *r, const struct object_id *oid)\n      \tbuffer = repo_read_object_file(r, oid, &type, &size);\n      \tif (buffer) {\n    - \t\tif (!check_object_signature(r, repl, buffer, size,\n    --\t\t\t\t\t    type_name(type), NULL)) {\n    -+\t\t\t\t\t    type_name(type))) {\n    + \t\tif (check_object_signature(r, repl, buffer, size,\n    +-\t\t\t\t\t   type_name(type), NULL) < 0) {\n    ++\t\t\t\t\t   type_name(type)) < 0) {\n      \t\t\tfree(buffer);\n      \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n      \t\t\treturn NULL;\n    @@ pack-check.c: static int verify_packfile(struct repository *r,\n      \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\n      \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n      \t\t\t\t    (uintmax_t)entries[i].offset);\n    --\t\telse if (!check_object_signature(r, &oid, data, size,\n    --\t\t\t\t\t\t type_name(type), NULL))\n    -+\t\telse if (data && !check_object_signature(r, &oid, data, size,\n    -+\t\t\t\t\t\t\t type_name(type)))\n    +-\t\telse if (check_object_signature(r, &oid, data, size,\n    +-\t\t\t\t\t\ttype_name(type), NULL) < 0)\n    ++\t\telse if (data && check_object_signature(r, &oid, data, size,\n    ++\t\t\t\t\t\t\ttype_name(type)) < 0)\n     +\t\t\terr = error(\"packed %s from %s is corrupt\",\n     +\t\t\t\t    oid_to_hex(&oid), p->pack_name);\n    -+\t\telse if (!data && !stream_object_signature(r, &oid))\n    ++\t\telse if (!data && stream_object_signature(r, &oid) < 0)\n      \t\t\terr = error(\"packed %s from %s is corrupt\",\n      \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n      \t\telse if (fn) {\n 5:  a5ebd04d462 =  9:  1276c2d1ed6 object API: rename hash_object_file_literally() to write_*()\n 6:  40647be525b ! 10:  2c936c674d4 object-file API: have hash_object_file() take \"enum object_type\"\n    @@ builtin/fast-export.c\n     @@ builtin/fast-export.c: static void export_blob(const struct object_id *oid)\n      \t\tif (!buf)\n      \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n    - \t\tif (!check_object_signature(the_repository, oid, buf, size,\n    --\t\t\t\t\t    type_name(type)))\n    -+\t\t\t\t\t    type))\n    + \t\tif (check_object_signature(the_repository, oid, buf, size,\n    +-\t\t\t\t\t   type_name(type)) < 0)\n    ++\t\t\t\t\t   type) < 0)\n      \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n      \t\tobject = parse_object_buffer(the_repository, oid, type,\n      \t\t\t\t\t     size, buf, &eaten);\n    @@ builtin/index-pack.c: static struct base_data *resolve_delta(struct object_entry\n     @@ builtin/index-pack.c: static void fix_unresolved_deltas(struct hashfile *f)\n      \t\t\tcontinue;\n      \n    - \t\tif (!check_object_signature(the_repository, &d->oid, data,\n    --\t\t\t\t\t    size, type_name(type)))\n    -+\t\t\t\t\t    size, type))\n    + \t\tif (check_object_signature(the_repository, &d->oid, data, size,\n    +-\t\t\t\t\t   type_name(type)) < 0)\n    ++\t\t\t\t\t   type) < 0)\n      \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n      \n      \t\t/*\n    @@ builtin/mktag.c\n     @@ builtin/mktag.c: static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n      \n      \trepl = lookup_replace_object(the_repository, tagged_oid);\n    - \tret = !check_object_signature(the_repository, repl, buffer, size,\n    --\t\t\t\t      type_name(*tagged_type));\n    + \tret = check_object_signature(the_repository, repl, buffer, size,\n    +-\t\t\t\t     type_name(*tagged_type));\n     +\t\t\t\t     *tagged_type);\n      \tfree(buffer);\n      \n    @@ cache-tree.c: static int verify_one(struct repository *r,\n     \n      ## cache.h ##\n     @@ cache.h: int parse_loose_header(const char *hdr, struct object_info *oi);\n    -  * except that negative values might also indicate a generic error.\n    +  * what we expected, but it might also indicate another error.\n       */\n      int check_object_signature(struct repository *r, const struct object_id *oid,\n     -\t\t\t   void *buf, unsigned long size, const char *type);\n    @@ object-file.c: int index_path(struct index_state *istate, struct object_id *oid,\n      \t\t\trc = error(_(\"%s: failed to insert into database\"), path);\n      \t\tstrbuf_release(&sb);\n     @@ object-file.c: int read_loose_object(const char *path,\n    + \t\t\tgit_inflate_end(&stream);\n      \t\t\tgoto out;\n      \t\t}\n    - \n     -\t\thash_object_file(the_repository->hash_algo,\n     -\t\t\t\t *contents, *size, oi->type_name->buf,\n     -\t\t\t\t real_oid);\n    @@ object.c: struct object *parse_object(struct repository *r, const struct object_\n      \n      \tbuffer = repo_read_object_file(r, oid, &type, &size);\n      \tif (buffer) {\n    --\t\tif (!check_object_signature(r, repl, buffer, size,\n    --\t\t\t\t\t    type_name(type))) {\n    -+\t\tif (!check_object_signature(r, repl, buffer, size, type)) {\n    +-\t\tif (check_object_signature(r, repl, buffer, size,\n    +-\t\t\t\t\t   type_name(type)) < 0) {\n    ++\t\tif (check_object_signature(r, repl, buffer, size, type) < 0) {\n      \t\t\tfree(buffer);\n      \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n      \t\t\treturn NULL;\n    @@ pack-check.c\n     @@ pack-check.c: static int verify_packfile(struct repository *r,\n      \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n      \t\t\t\t    (uintmax_t)entries[i].offset);\n    - \t\telse if (data && !check_object_signature(r, &oid, data, size,\n    --\t\t\t\t\t\t\t type_name(type)))\n    -+\t\t\t\t\t\t\t type))\n    + \t\telse if (data && check_object_signature(r, &oid, data, size,\n    +-\t\t\t\t\t\t\ttype_name(type)) < 0)\n    ++\t\t\t\t\t\t\ttype) < 0)\n      \t\t\terr = error(\"packed %s from %s is corrupt\",\n      \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n    - \t\telse if (!data && !stream_object_signature(r, &oid))\n    + \t\telse if (!data && stream_object_signature(r, &oid) < 0)\n 7:  e39edfbce05 = 11:  ad1a777f454 object-file.c: add a literal version of write_object_file_prepare()\n 8:  f2b1cb861a0 = 12:  d2d355e6bb8 object-file API: pass an enum to read_object_with_reference()\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447790","messageId":"patch-v3-03.12-92fd020d199-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 03/12] object-file API: add a format_object_header() function","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:25Z","receivedAt":"2022-02-04T23:48:50Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a convenience function to wrap the xsnprintf() command that\ngenerates loose object headers. This code was copy/pasted in various\nparts of the codebase, let's define it in one place and re-use it from\nthere.\n\nAll except one caller of it had a valid \"enum object_type\" for us,\nit's only write_object_file_prepare() which might need to deal with\n\"git hash-object --literally\" and a potential garbage type. Let's have\nthe primary API use an \"enum object_type\", and define a *_literally()\nfunction that can take an arbitrary \"const char *\" for the type.\n\nSee [1] for the discussion that prompted this patch, i.e. new code in\nobject-file.c that wanted to copy/paste the xsnprintf() invocation.\n\nIn the case of fast-import.c the callers unfortunately need to cast\nback & forth between \"unsigned char *\" and \"char *\", since\nformat_object_header() ad encode_in_pack_object_header() take\ndifferent signedness.\n\n1. https://lore.kernel.org/git/211213.86bl1l9bfz.gmgdl@evledraar.gmail.com/\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/fast-import.c |  6 +++---\n builtin/index-pack.c  |  3 +--\n bulk-checkin.c        |  4 ++--\n http-push.c           |  2 +-\n object-file.c         | 23 ++++++++++++++++++++---\n object-store.h        |  8 ++++++++\n 6 files changed, 35 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 2b2e28bad79..123df7d9a53 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -937,8 +937,8 @@ static int store_object(\n \tgit_hash_ctx c;\n \tgit_zstream s;\n \n-\thdrlen = xsnprintf((char *)hdr, sizeof(hdr), \"%s %lu\",\n-\t\t\t   type_name(type), (unsigned long)dat->len) + 1;\n+\thdrlen = format_object_header((char *)hdr, sizeof(hdr), type,\n+\t\t\t\t      dat->len);\n \tthe_hash_algo->init_fn(&c);\n \tthe_hash_algo->update_fn(&c, hdr, hdrlen);\n \tthe_hash_algo->update_fn(&c, dat->buf, dat->len);\n@@ -1091,7 +1091,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)\n \thashfile_checkpoint(pack_file, &checkpoint);\n \toffset = checkpoint.offset;\n \n-\thdrlen = xsnprintf((char *)out_buf, out_sz, \"blob %\" PRIuMAX, len) + 1;\n+\thdrlen = format_object_header((char *)out_buf, out_sz, OBJ_BLOB, len);\n \n \tthe_hash_algo->init_fn(&c);\n \tthe_hash_algo->update_fn(&c, out_buf, hdrlen);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 3c2e6aee3cc..01574378ce2 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -449,8 +449,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size,\n \tint hdrlen;\n \n \tif (!is_delta_type(type)) {\n-\t\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX,\n-\t\t\t\t   type_name(type),(uintmax_t)size) + 1;\n+\t\thdrlen = format_object_header(hdr, sizeof(hdr), type, size);\n \t\tthe_hash_algo->init_fn(&c);\n \t\tthe_hash_algo->update_fn(&c, hdr, hdrlen);\n \t} else\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 8785b2ac806..85b3ebaf971 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -220,8 +220,8 @@ static int deflate_to_pack(struct bulk_checkin_state *state,\n \tif (seekback == (off_t) -1)\n \t\treturn error(\"cannot find the current offset\");\n \n-\theader_len = xsnprintf((char *)obuf, sizeof(obuf), \"%s %\" PRIuMAX,\n-\t\t\t       type_name(type), (uintmax_t)size) + 1;\n+\theader_len = format_object_header((char *)obuf, sizeof(obuf),\n+\t\t\t\t\t  type, size);\n \tthe_hash_algo->init_fn(&ctx);\n \tthe_hash_algo->update_fn(&ctx, obuf, header_len);\n \ndiff --git a/http-push.c b/http-push.c\nindex 3309aaf004a..f0c044dcf76 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -363,7 +363,7 @@ static void start_put(struct transfer_request *request)\n \tgit_zstream stream;\n \n \tunpacked = read_object_file(&request->obj->oid, &type, &len);\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(type), (uintmax_t)len) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type, len);\n \n \t/* Set it up */\n \tgit_deflate_init(&stream, zlib_compression_level);\ndiff --git a/object-file.c b/object-file.c\nindex eeb6814780a..3fcd46cf9ed 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1049,6 +1049,23 @@ void *xmmap(void *start, size_t length,\n \treturn ret;\n }\n \n+static int format_object_header_literally(char *str, size_t size,\n+\t\t\t\t\t  const char *type, size_t objsize)\n+{\n+\treturn xsnprintf(str, size, \"%s %\"PRIuMAX, type, (uintmax_t)objsize) + 1;\n+}\n+\n+int format_object_header(char *str, size_t size, enum object_type type,\n+\t\t\t size_t objsize)\n+{\n+\tconst char *name = type_name(type);\n+\n+\tif (!name)\n+\t\tBUG(\"could not get a type name for 'enum object_type' value %d\", type);\n+\n+\treturn format_object_header_literally(str, size, name, objsize);\n+}\n+\n /*\n  * With an in-core object data in \"map\", rehash it to make sure the\n  * object name actually matches \"oid\" to detect object corruption.\n@@ -1077,7 +1094,7 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\treturn -1;\n \n \t/* Generate the header */\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(obj_type), (uintmax_t)size) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size);\n \n \t/* Sha1.. */\n \tr->hash_algo->init_fn(&c);\n@@ -1777,7 +1794,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo,\n \tgit_hash_ctx c;\n \n \t/* Generate the header */\n-\t*hdrlen = xsnprintf(hdr, *hdrlen, \"%s %\"PRIuMAX , type, (uintmax_t)len)+1;\n+\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n \n \t/* Sha1.. */\n \talgo->init_fn(&c);\n@@ -2051,7 +2068,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)\n \tbuf = read_object(the_repository, oid, &type, &len);\n \tif (!buf)\n \t\treturn error(_(\"cannot read object for %s\"), oid_to_hex(oid));\n-\thdrlen = xsnprintf(hdr, sizeof(hdr), \"%s %\"PRIuMAX , type_name(type), (uintmax_t)len) + 1;\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type, len);\n \tret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);\n \tfree(buf);\n \ndiff --git a/object-store.h b/object-store.h\nindex 44f6868cc9c..8b4413d0ce7 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -331,6 +331,14 @@ int repo_has_object_file_with_flags(struct repository *r,\n  */\n int has_loose_object_nonlocal(const struct object_id *);\n \n+/**\n+ * format_object_header() is a thin wrapper around s xsnprintf() that\n+ * writes the initial \"<type> <obj-len>\" part of the loose object\n+ * header. It returns the size that snprintf() returns + 1.\n+ */\n+int format_object_header(char *str, size_t size, enum object_type type,\n+\t\t\t size_t objsize);\n+\n void assert_oid_type(const struct object_id *oid, enum object_type expect);\n \n /*\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447791","messageId":"patch-v3-04.12-795ac3dea2a-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 04/12] object-file API: have write_object_file() take \"enum object_type\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:26Z","receivedAt":"2022-02-04T23:48:57Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the write_object_file() function to take an \"enum object_type\"\ninstead of a \"const char *type\". Its callers either passed\n{commit,tree,blob,tag}_type and can pass the corresponding OBJ_* type\ninstead, or were hardcoding strings like \"blob\".\n\nThis avoids the back & forth fragility where the callers of\nwrite_object_file() would have the enum type, and convert it\nthemselves via type_name(). We do have to now do that conversion\nourselves before calling write_object_file_prepare(), but those\ncodepaths will be similarly adjusted in subsequent commits.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n apply.c                  |  8 ++++----\n builtin/checkout.c       |  2 +-\n builtin/mktag.c          |  2 +-\n builtin/mktree.c         |  2 +-\n builtin/notes.c          |  2 +-\n builtin/receive-pack.c   |  2 +-\n builtin/replace.c        |  2 +-\n builtin/tag.c            |  2 +-\n builtin/unpack-objects.c |  6 +++---\n cache-tree.c             |  2 +-\n commit.c                 |  2 +-\n match-trees.c            |  2 +-\n merge-ort.c              |  4 ++--\n merge-recursive.c        |  2 +-\n notes-cache.c            |  2 +-\n notes.c                  |  8 ++++----\n object-file.c            | 10 +++++-----\n object-store.h           |  4 ++--\n read-cache.c             |  2 +-\n 19 files changed, 33 insertions(+), 33 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex 7ffadc3b17a..e82a7c30f01 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -3589,7 +3589,7 @@ static int try_threeway(struct apply_state *state,\n \n \t/* Preimage the patch was prepared for */\n \tif (patch->is_new)\n-\t\twrite_object_file(\"\", 0, blob_type, &pre_oid);\n+\t\twrite_object_file(\"\", 0, OBJ_BLOB, &pre_oid);\n \telse if (get_oid(patch->old_oid_prefix, &pre_oid) ||\n \t\t read_blob_object(&buf, &pre_oid, patch->old_mode))\n \t\treturn error(_(\"repository lacks the necessary blob to perform 3-way merge.\"));\n@@ -3605,7 +3605,7 @@ static int try_threeway(struct apply_state *state,\n \t\treturn -1;\n \t}\n \t/* post_oid is theirs */\n-\twrite_object_file(tmp_image.buf, tmp_image.len, blob_type, &post_oid);\n+\twrite_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &post_oid);\n \tclear_image(&tmp_image);\n \n \t/* our_oid is ours */\n@@ -3618,7 +3618,7 @@ static int try_threeway(struct apply_state *state,\n \t\t\treturn error(_(\"cannot read the current contents of '%s'\"),\n \t\t\t\t     patch->old_name);\n \t}\n-\twrite_object_file(tmp_image.buf, tmp_image.len, blob_type, &our_oid);\n+\twrite_object_file(tmp_image.buf, tmp_image.len, OBJ_BLOB, &our_oid);\n \tclear_image(&tmp_image);\n \n \t/* in-core three-way merge between post and our using pre as base */\n@@ -4346,7 +4346,7 @@ static int add_index_file(struct apply_state *state,\n \t\t\t}\n \t\t\tfill_stat_cache_info(state->repo->index, ce, &st);\n \t\t}\n-\t\tif (write_object_file(buf, size, blob_type, &ce->oid) < 0) {\n+\t\tif (write_object_file(buf, size, OBJ_BLOB, &ce->oid) < 0) {\n \t\t\tdiscard_cache_entry(ce);\n \t\t\treturn error(_(\"unable to create backing store \"\n \t\t\t\t       \"for newly created file %s\"), path);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex cc804ba8e1e..24cc235939f 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -298,7 +298,7 @@ static int checkout_merged(int pos, const struct checkout *state,\n \t * (it also writes the merge result to the object database even\n \t * when it may contain conflicts).\n \t */\n-\tif (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid))\n+\tif (write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &oid))\n \t\tdie(_(\"Unable to add merge result for '%s'\"), path);\n \tfree(result_buf.ptr);\n \tce = make_transient_cache_entry(mode, &oid, path, 2, ce_mem_pool);\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 3b2dbbb37e6..96a3686af53 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -100,7 +100,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)\n \tif (verify_object_in_tag(&tagged_oid, &tagged_type))\n \t\tdie(_(\"tag on stdin did not refer to a valid object\"));\n \n-\tif (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)\n+\tif (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0)\n \t\tdie(_(\"unable to write tag file\"));\n \n \tstrbuf_release(&buf);\ndiff --git a/builtin/mktree.c b/builtin/mktree.c\nindex ae78ca1c029..a1213aaa961 100644\n--- a/builtin/mktree.c\n+++ b/builtin/mktree.c\n@@ -58,7 +58,7 @@ static void write_tree(struct object_id *oid)\n \t\tstrbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz);\n \t}\n \n-\twrite_object_file(buf.buf, buf.len, tree_type, oid);\n+\twrite_object_file(buf.buf, buf.len, OBJ_TREE, oid);\n \tstrbuf_release(&buf);\n }\n \ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 05d60483e82..4cc84dfa768 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -199,7 +199,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data *\n \n static void write_note_data(struct note_data *d, struct object_id *oid)\n {\n-\tif (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) {\n+\tif (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) {\n \t\tint status = die_message(_(\"unable to write note object\"));\n \n \t\tif (d->edit_path)\ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 9f4a0b816cf..231d576927b 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -762,7 +762,7 @@ static void prepare_push_cert_sha1(struct child_process *proc)\n \t\tint bogs /* beginning_of_gpg_sig */;\n \n \t\talready_done = 1;\n-\t\tif (write_object_file(push_cert.buf, push_cert.len, \"blob\",\n+\t\tif (write_object_file(push_cert.buf, push_cert.len, OBJ_BLOB,\n \t\t\t\t      &push_cert_oid))\n \t\t\toidclr(&push_cert_oid);\n \ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 6ff1734d587..995ca683302 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -474,7 +474,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle)\n \t\treturn -1;\n \t}\n \n-\tif (write_object_file(buf.buf, buf.len, commit_type, &new_oid)) {\n+\tif (write_object_file(buf.buf, buf.len, OBJ_COMMIT, &new_oid)) {\n \t\tstrbuf_release(&buf);\n \t\treturn error(_(\"could not write replacement commit for: '%s'\"),\n \t\t\t     old_ref);\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 134b3f1edf0..31e6b155c04 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -238,7 +238,7 @@ static int build_tag_object(struct strbuf *buf, int sign, struct object_id *resu\n {\n \tif (sign && do_sign(buf) < 0)\n \t\treturn error(_(\"unable to sign the tag\"));\n-\tif (write_object_file(buf->buf, buf->len, tag_type, result) < 0)\n+\tif (write_object_file(buf->buf, buf->len, OBJ_TAG, result) < 0)\n \t\treturn error(_(\"unable to write tag file\"));\n \treturn 0;\n }\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 4a9466295ba..808041551fd 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -177,7 +177,7 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf)\n \tstruct object_id oid;\n \n \tif (write_object_file(obj_buf->buffer, obj_buf->size,\n-\t\t\t      type_name(obj->type), &oid) < 0)\n+\t\t\t      obj->type, &oid) < 0)\n \t\tdie(\"failed to write object %s\", oid_to_hex(&obj->oid));\n \tobj->flags |= FLAG_WRITTEN;\n }\n@@ -243,7 +243,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t\t\t void *buf, unsigned long size)\n {\n \tif (!strict) {\n-\t\tif (write_object_file(buf, size, type_name(type),\n+\t\tif (write_object_file(buf, size, type,\n \t\t\t\t      &obj_list[nr].oid) < 0)\n \t\t\tdie(\"failed to write object\");\n \t\tadded_object(nr, type, buf, size);\n@@ -251,7 +251,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t\tobj_list[nr].obj = NULL;\n \t} else if (type == OBJ_BLOB) {\n \t\tstruct blob *blob;\n-\t\tif (write_object_file(buf, size, type_name(type),\n+\t\tif (write_object_file(buf, size, type,\n \t\t\t\t      &obj_list[nr].oid) < 0)\n \t\t\tdie(\"failed to write object\");\n \t\tadded_object(nr, type, buf, size);\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 65ca9933613..fdbbd191d22 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -440,7 +440,7 @@ static int update_one(struct cache_tree *it,\n \t} else if (dryrun) {\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n \t\t\t\t tree_type, &it->oid);\n-\t} else if (write_object_file_flags(buffer.buf, buffer.len, tree_type,\n+\t} else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE,\n \t\t\t\t\t   &it->oid, flags & WRITE_TREE_SILENT\n \t\t\t\t\t   ? HASH_SILENT : 0)) {\n \t\tstrbuf_release(&buffer);\ndiff --git a/commit.c b/commit.c\nindex a348f085b2b..6cc0ba9c11b 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1567,7 +1567,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \t\tgoto out;\n \t}\n \n-\tresult = write_object_file(buffer.buf, buffer.len, commit_type, ret);\n+\tresult = write_object_file(buffer.buf, buffer.len, OBJ_COMMIT, ret);\n out:\n \tstrbuf_release(&buffer);\n \treturn result;\ndiff --git a/match-trees.c b/match-trees.c\nindex df413989fa8..49398e599fe 100644\n--- a/match-trees.c\n+++ b/match-trees.c\n@@ -235,7 +235,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,\n \t\trewrite_with = oid2;\n \t}\n \thashcpy(rewrite_here, rewrite_with->hash);\n-\tstatus = write_object_file(buf, sz, tree_type, result);\n+\tstatus = write_object_file(buf, sz, OBJ_TREE, result);\n \tfree(buf);\n \treturn status;\n }\ndiff --git a/merge-ort.c b/merge-ort.c\nindex c3197970219..d4ba2955f11 100644\n--- a/merge-ort.c\n+++ b/merge-ort.c\n@@ -1888,7 +1888,7 @@ static int handle_content_merge(struct merge_options *opt,\n \n \t\tif (!ret &&\n \t\t    write_object_file(result_buf.ptr, result_buf.size,\n-\t\t\t\t      blob_type, &result->oid))\n+\t\t\t\t      OBJ_BLOB, &result->oid))\n \t\t\tret = err(opt, _(\"Unable to add %s to database\"),\n \t\t\t\t  path);\n \n@@ -3343,7 +3343,7 @@ static void write_tree(struct object_id *result_oid,\n \t}\n \n \t/* Write this object file out, and record in result_oid */\n-\twrite_object_file(buf.buf, buf.len, tree_type, result_oid);\n+\twrite_object_file(buf.buf, buf.len, OBJ_TREE, result_oid);\n \tstrbuf_release(&buf);\n }\n \ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex d9457797dbb..e0cbbf2d022 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -1373,7 +1373,7 @@ static int merge_mode_and_contents(struct merge_options *opt,\n \n \t\t\tif (!ret &&\n \t\t\t    write_object_file(result_buf.ptr, result_buf.size,\n-\t\t\t\t\t      blob_type, &result->blob.oid))\n+\t\t\t\t\t      OBJ_BLOB, &result->blob.oid))\n \t\t\t\tret = err(opt, _(\"Unable to add %s to database\"),\n \t\t\t\t\t  a->path);\n \ndiff --git a/notes-cache.c b/notes-cache.c\nindex 2473314d686..9dfd251a815 100644\n--- a/notes-cache.c\n+++ b/notes-cache.c\n@@ -92,7 +92,7 @@ int notes_cache_put(struct notes_cache *c, struct object_id *key_oid,\n {\n \tstruct object_id value_oid;\n \n-\tif (write_object_file(data, size, \"blob\", &value_oid) < 0)\n+\tif (write_object_file(data, size, OBJ_BLOB, &value_oid) < 0)\n \t\treturn -1;\n \treturn add_note(&c->tree, key_oid, &value_oid, NULL);\n }\ndiff --git a/notes.c b/notes.c\nindex f87dac40684..7452e71cc8d 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -675,7 +675,7 @@ static int tree_write_stack_finish_subtree(struct tree_write_stack *tws)\n \t\tret = tree_write_stack_finish_subtree(n);\n \t\tif (ret)\n \t\t\treturn ret;\n-\t\tret = write_object_file(n->buf.buf, n->buf.len, tree_type, &s);\n+\t\tret = write_object_file(n->buf.buf, n->buf.len, OBJ_TREE, &s);\n \t\tif (ret)\n \t\t\treturn ret;\n \t\tstrbuf_release(&n->buf);\n@@ -836,7 +836,7 @@ int combine_notes_concatenate(struct object_id *cur_oid,\n \tfree(new_msg);\n \n \t/* create a new blob object from buf */\n-\tret = write_object_file(buf, buf_len, blob_type, cur_oid);\n+\tret = write_object_file(buf, buf_len, OBJ_BLOB, cur_oid);\n \tfree(buf);\n \treturn ret;\n }\n@@ -916,7 +916,7 @@ int combine_notes_cat_sort_uniq(struct object_id *cur_oid,\n \t\t\t\t string_list_join_lines_helper, &buf))\n \t\tgoto out;\n \n-\tret = write_object_file(buf.buf, buf.len, blob_type, cur_oid);\n+\tret = write_object_file(buf.buf, buf.len, OBJ_BLOB, cur_oid);\n \n out:\n \tstrbuf_release(&buf);\n@@ -1192,7 +1192,7 @@ int write_notes_tree(struct notes_tree *t, struct object_id *result)\n \tret = for_each_note(t, flags, write_each_note, &cb_data) ||\n \t      write_each_non_note_until(NULL, &cb_data) ||\n \t      tree_write_stack_finish_subtree(&root) ||\n-\t      write_object_file(root.buf.buf, root.buf.len, tree_type, result);\n+\t      write_object_file(root.buf.buf, root.buf.len, OBJ_TREE, result);\n \tstrbuf_release(&root.buf);\n \treturn ret;\n }\ndiff --git a/object-file.c b/object-file.c\nindex 3fcd46cf9ed..59eb793e0ac 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2014,7 +2014,7 @@ static int freshen_packed_object(const struct object_id *oid)\n }\n \n int write_object_file_flags(const void *buf, unsigned long len,\n-\t\t\t    const char *type, struct object_id *oid,\n+\t\t\t    enum object_type type, struct object_id *oid,\n \t\t\t    unsigned flags)\n {\n \tchar hdr[MAX_HEADER_LEN];\n@@ -2023,7 +2023,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t/* Normally if we have it in the pack then we do not bother writing\n \t * it out into .git/objects/??/?{38} file.\n \t */\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr,\n+\twrite_object_file_prepare(the_hash_algo, buf, len, type_name(type), oid, hdr,\n \t\t\t\t  &hdrlen);\n \tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n \t\treturn 0;\n@@ -2162,7 +2162,7 @@ static int index_mem(struct index_state *istate,\n \t}\n \n \tif (write_object)\n-\t\tret = write_object_file(buf, size, type_name(type), oid);\n+\t\tret = write_object_file(buf, size, type, oid);\n \telse\n \t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n \t\t\t\t oid);\n@@ -2189,7 +2189,7 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\t\t\t get_conv_flags(flags));\n \n \tif (write_object)\n-\t\tret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB),\n+\t\tret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB,\n \t\t\t\t\toid);\n \telse\n \t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n@@ -2313,7 +2313,7 @@ int index_path(struct index_state *istate, struct object_id *oid,\n \t\tif (!(flags & HASH_WRITE_OBJECT))\n \t\t\thash_object_file(the_hash_algo, sb.buf, sb.len,\n \t\t\t\t\t blob_type, oid);\n-\t\telse if (write_object_file(sb.buf, sb.len, blob_type, oid))\n+\t\telse if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))\n \t\t\trc = error(_(\"%s: failed to insert into database\"), path);\n \t\tstrbuf_release(&sb);\n \t\tbreak;\ndiff --git a/object-store.h b/object-store.h\nindex 8b4413d0ce7..eab1e2a967e 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -250,10 +250,10 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n \t\t      struct object_id *oid);\n \n int write_object_file_flags(const void *buf, unsigned long len,\n-\t\t\t    const char *type, struct object_id *oid,\n+\t\t\t    enum object_type type, struct object_id *oid,\n \t\t\t    unsigned flags);\n static inline int write_object_file(const void *buf, unsigned long len,\n-\t\t\t\t    const char *type, struct object_id *oid)\n+\t\t\t\t    enum object_type type, struct object_id *oid)\n {\n \treturn write_object_file_flags(buf, len, type, oid, 0);\n }\ndiff --git a/read-cache.c b/read-cache.c\nindex cbe73f14e5e..b8ae30a0e71 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -735,7 +735,7 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,\n void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)\n {\n \tstruct object_id oid;\n-\tif (write_object_file(\"\", 0, blob_type, &oid))\n+\tif (write_object_file(\"\", 0, OBJ_BLOB, &oid))\n \t\tdie(_(\"cannot create an empty blob in the object database\"));\n \toidcpy(&ce->oid, &oid);\n }\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447792","messageId":"patch-v3-05.12-6faf46277b5-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 05/12] object API: correct \"buf\" v.s. \"map\" mismatch in *.c and *.h","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:27Z","receivedAt":"2022-02-04T23:48:58Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the name of the second argument to check_object_signature() to\nbe \"buf\" in object-file.c, making it consistent with the prototype in\ncache.h\n\nThis fixes an inconsistency that's been with us since 2ade9340262 (Add\n\"check_sha1_signature()\" helper function, 2005-04-08), and makes a\nsubsequent commit's diff smaller, as we'll move these API docs to\ncache.h.\n\nWhile we're at it fix a small grammar error in the documentation,\ndropping an \"an\" before \"in-core object-data\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex 59eb793e0ac..271acf4dd15 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1067,13 +1067,13 @@ int format_object_header(char *str, size_t size, enum object_type type,\n }\n \n /*\n- * With an in-core object data in \"map\", rehash it to make sure the\n+ * With in-core object data in \"buf\", rehash it to make sure the\n  * object name actually matches \"oid\" to detect object corruption.\n- * With \"map\" == NULL, try reading the object named with \"oid\" using\n+ * With \"buf\" == NULL, try reading the object named with \"oid\" using\n  * the streaming interface and rehash it to do the same.\n  */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *map, unsigned long size, const char *type,\n+\t\t\t   void *buf, unsigned long size, const char *type,\n \t\t\t   struct object_id *real_oidp)\n {\n \tstruct object_id tmp;\n@@ -1084,8 +1084,8 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen;\n \n-\tif (map) {\n-\t\thash_object_file(r->hash_algo, map, size, type, real_oid);\n+\tif (buf) {\n+\t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n \t\treturn !oideq(oid, real_oid) ? -1 : 0;\n \t}\n \n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447793","messageId":"patch-v3-06.12-bdddaa3648f-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 06/12] object API docs: move check_object_signature() docs to cache.h","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:28Z","receivedAt":"2022-02-04T23:49:00Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Move the API documentation for check_object_signature() to cache.h,\nwhere its prototype is declared. This is in preparation for adding a\ncompanion function.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n cache.h       | 6 ++++++\n object-file.c | 6 ------\n 2 files changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 281f00ab1b1..98d1ef08579 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1319,6 +1319,12 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,\n struct object_info;\n int parse_loose_header(const char *hdr, struct object_info *oi);\n \n+/**\n+ * With in-core object data in \"buf\", rehash it to make sure the\n+ * object name actually matches \"oid\" to detect object corruption.\n+ * With \"buf\" == NULL, try reading the object named with \"oid\" using\n+ * the streaming interface and rehash it to do the same.\n+ */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\t\t   void *buf, unsigned long size, const char *type,\n \t\t\t   struct object_id *real_oidp);\ndiff --git a/object-file.c b/object-file.c\nindex 271acf4dd15..44e0b32d71a 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1066,12 +1066,6 @@ int format_object_header(char *str, size_t size, enum object_type type,\n \treturn format_object_header_literally(str, size, name, objsize);\n }\n \n-/*\n- * With in-core object data in \"buf\", rehash it to make sure the\n- * object name actually matches \"oid\" to detect object corruption.\n- * With \"buf\" == NULL, try reading the object named with \"oid\" using\n- * the streaming interface and rehash it to do the same.\n- */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\t\t   void *buf, unsigned long size, const char *type,\n \t\t\t   struct object_id *real_oidp)\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447794","messageId":"patch-v3-09.12-1276c2d1ed6-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 09/12] object API: rename hash_object_file_literally() to write_*()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:31Z","receivedAt":"2022-02-04T23:49:01Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Before 0c3db67cc81 (hash-object --literally: fix buffer overrun with\nextra-long object type, 2015-05-04) the hash-object code being changed\nhere called write_sha1_file() to both hash and write a loose\nobject. Before that we'd use hash_sha1_file() to if \"-w\" wasn't\nprovided, and otherwise call write_sha1_file().\n\nNow we'll always call the same function for both writing. Let's rename\nit from hash_*_literally() to write_*_literally(). Even though the\nwrite_*() might not actually write if HASH_WRITE_OBJECT isn't in\n\"flags\", having it be more similar to write_object_file_flags() than\nhash_object_file(), but carrying a name that would suggest that it's a\nvariant of the latter is confusing.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/hash-object.c | 2 +-\n object-file.c         | 6 +++---\n object-store.h        | 6 +++---\n 3 files changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/hash-object.c b/builtin/hash-object.c\nindex c7b3ad74c60..f4cbd9c4ae3 100644\n--- a/builtin/hash-object.c\n+++ b/builtin/hash-object.c\n@@ -25,7 +25,7 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig\n \tif (strbuf_read(&buf, fd, 4096) < 0)\n \t\tret = -1;\n \telse\n-\t\tret = hash_object_file_literally(buf.buf, buf.len, type, oid,\n+\t\tret = write_object_file_literally(buf.buf, buf.len, type, oid,\n \t\t\t\t\t\t flags);\n \tstrbuf_release(&buf);\n \treturn ret;\ndiff --git a/object-file.c b/object-file.c\nindex f9854922741..9e5b849693e 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2027,9 +2027,9 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \treturn write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags);\n }\n \n-int hash_object_file_literally(const void *buf, unsigned long len,\n-\t\t\t       const char *type, struct object_id *oid,\n-\t\t\t       unsigned flags)\n+int write_object_file_literally(const void *buf, unsigned long len,\n+\t\t\t\tconst char *type, struct object_id *oid,\n+\t\t\t\tunsigned flags)\n {\n \tchar *header;\n \tint hdrlen, status = 0;\ndiff --git a/object-store.h b/object-store.h\nindex eab1e2a967e..29169d117f7 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -258,9 +258,9 @@ static inline int write_object_file(const void *buf, unsigned long len,\n \treturn write_object_file_flags(buf, len, type, oid, 0);\n }\n \n-int hash_object_file_literally(const void *buf, unsigned long len,\n-\t\t\t       const char *type, struct object_id *oid,\n-\t\t\t       unsigned flags);\n+int write_object_file_literally(const void *buf, unsigned long len,\n+\t\t\t\tconst char *type, struct object_id *oid,\n+\t\t\t\tunsigned flags);\n \n /*\n  * Add an object file to the in-memory object store, without writing it\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447795","messageId":"patch-v3-08.12-478d2915731-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 08/12] object-file API: split up and simplify check_object_signature()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:30Z","receivedAt":"2022-02-04T23:49:04Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split up the check_object_signature() function into that non-streaming\nversion (it accepts an already filled \"buf\"), and a new\nstream_object_signature() which will retrieve the object from storage,\nand hash it on-the-fly.\n\nAll of the callers of check_object_signature() were effectively\ncalling two different functions, if we go by cyclomatic\ncomplexity. I.e. they'd either take the early \"if (map)\" branch and\nreturn early, or not. This has been the case since the \"if (map)\"\ncondition was added in 090ea12671b (parse_object: avoid putting whole\nblob in core, 2012-03-07).\n\nWe can then further simplify the resulting check_object_signature()\nfunction since only one caller wanted to pass a non-NULL \"buf\" and a\nnon-NULL \"real_oidp\". That \"read_loose_object()\" codepath used by \"git\nfsck\" can instead use hash_object_file() followed by oideq().\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/fast-export.c |  2 +-\n builtin/index-pack.c  |  2 +-\n builtin/mktag.c       |  5 ++---\n cache.h               | 12 ++++++++----\n object-file.c         | 32 ++++++++++++++++++--------------\n object.c              |  4 ++--\n pack-check.c          |  9 ++++++---\n 7 files changed, 38 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex 9f1c730e587..319859db30e 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -300,7 +300,7 @@ static void export_blob(const struct object_id *oid)\n \t\tif (!buf)\n \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n \t\tif (check_object_signature(the_repository, oid, buf, size,\n-\t\t\t\t\t   type_name(type), NULL) < 0)\n+\t\t\t\t\t   type_name(type)) < 0)\n \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n \t\tobject = parse_object_buffer(the_repository, oid, type,\n \t\t\t\t\t     size, buf, &eaten);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 416f60a98c1..e1927205a7b 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1413,7 +1413,7 @@ static void fix_unresolved_deltas(struct hashfile *f)\n \t\t\tcontinue;\n \n \t\tif (check_object_signature(the_repository, &d->oid, data, size,\n-\t\t\t\t\t   type_name(type), NULL) < 0)\n+\t\t\t\t\t   type_name(type)) < 0)\n \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n \n \t\t/*\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 98d1e66f327..4d28eceeba6 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -61,9 +61,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n \t\t    type_name(*tagged_type), type_name(type));\n \n \trepl = lookup_replace_object(the_repository, tagged_oid);\n-\tret = check_object_signature(the_repository, repl,\n-\t\t\t\t     buffer, size, type_name(*tagged_type),\n-\t\t\t\t     NULL);\n+\tret = check_object_signature(the_repository, repl, buffer, size,\n+\t\t\t\t     type_name(*tagged_type));\n \tfree(buffer);\n \n \treturn ret;\ndiff --git a/cache.h b/cache.h\nindex 5d081952121..c068f99c793 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1322,15 +1322,19 @@ int parse_loose_header(const char *hdr, struct object_info *oi);\n /**\n  * With in-core object data in \"buf\", rehash it to make sure the\n  * object name actually matches \"oid\" to detect object corruption.\n- * With \"buf\" == NULL, try reading the object named with \"oid\" using\n- * the streaming interface and rehash it to do the same.\n  *\n  * A negative value indicates an error, usually that the OID is not\n  * what we expected, but it might also indicate another error.\n  */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type,\n-\t\t\t   struct object_id *real_oidp);\n+\t\t\t   void *buf, unsigned long size, const char *type);\n+\n+/**\n+ * A streaming version of check_object_signature().\n+ * Try reading the object named with \"oid\" using\n+ * the streaming interface and rehash it to do the same.\n+ */\n+int stream_object_signature(struct repository *r, const struct object_id *oid);\n \n int finalize_object_file(const char *tmpfile, const char *filename);\n \ndiff --git a/object-file.c b/object-file.c\nindex d628f58c0d2..f9854922741 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1067,22 +1067,25 @@ int format_object_header(char *str, size_t size, enum object_type type,\n }\n \n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type,\n-\t\t\t   struct object_id *real_oidp)\n+\t\t\t   void *buf, unsigned long size, const char *type)\n {\n-\tstruct object_id tmp;\n-\tstruct object_id *real_oid = real_oidp ? real_oidp : &tmp;\n+\tstruct object_id real_oid;\n+\n+\thash_object_file(r->hash_algo, buf, size, type, &real_oid);\n+\n+\treturn !oideq(oid, &real_oid) ? -1 : 0;\n+}\n+\n+int stream_object_signature(struct repository *r, const struct object_id *oid)\n+{\n+\tstruct object_id real_oid;\n+\tunsigned long size;\n \tenum object_type obj_type;\n \tstruct git_istream *st;\n \tgit_hash_ctx c;\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen;\n \n-\tif (buf) {\n-\t\thash_object_file(r->hash_algo, buf, size, type, real_oid);\n-\t\treturn !oideq(oid, real_oid) ? -1 : 0;\n-\t}\n-\n \tst = open_istream(r, oid, &obj_type, &size, NULL);\n \tif (!st)\n \t\treturn -1;\n@@ -1105,9 +1108,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\t\tbreak;\n \t\tr->hash_algo->update_fn(&c, buf, readlen);\n \t}\n-\tr->hash_algo->final_oid_fn(real_oid, &c);\n+\tr->hash_algo->final_oid_fn(&real_oid, &c);\n \tclose_istream(st);\n-\treturn !oideq(oid, real_oid) ? -1 : 0;\n+\treturn !oideq(oid, &real_oid) ? -1 : 0;\n }\n \n int git_open_cloexec(const char *name, int flags)\n@@ -2611,9 +2614,10 @@ int read_loose_object(const char *path,\n \t\t\tgit_inflate_end(&stream);\n \t\t\tgoto out;\n \t\t}\n-\t\tif (check_object_signature(the_repository, expected_oid,\n-\t\t\t\t\t   *contents, *size,\n-\t\t\t\t\t   oi->type_name->buf, real_oid) < 0)\n+\t\thash_object_file(the_repository->hash_algo,\n+\t\t\t\t *contents, *size, oi->type_name->buf,\n+\t\t\t\t real_oid);\n+\t\tif (!oideq(expected_oid, real_oid))\n \t\t\tgoto out;\n \t}\n \ndiff --git a/object.c b/object.c\nindex c37501fc120..d07678ef6da 100644\n--- a/object.c\n+++ b/object.c\n@@ -279,7 +279,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \tif ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||\n \t    (!obj && repo_has_object_file(r, oid) &&\n \t     oid_object_info(r, oid, NULL) == OBJ_BLOB)) {\n-\t\tif (check_object_signature(r, repl, NULL, 0, NULL, NULL) < 0) {\n+\t\tif (stream_object_signature(r, repl) < 0) {\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(oid));\n \t\t\treturn NULL;\n \t\t}\n@@ -290,7 +290,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \tbuffer = repo_read_object_file(r, oid, &type, &size);\n \tif (buffer) {\n \t\tif (check_object_signature(r, repl, buffer, size,\n-\t\t\t\t\t   type_name(type), NULL) < 0) {\n+\t\t\t\t\t   type_name(type)) < 0) {\n \t\t\tfree(buffer);\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n \t\t\treturn NULL;\ndiff --git a/pack-check.c b/pack-check.c\nindex 48d818ee7b4..d8d8f91de6b 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -127,7 +127,7 @@ static int verify_packfile(struct repository *r,\n \n \t\tif (type == OBJ_BLOB && big_file_threshold <= size) {\n \t\t\t/*\n-\t\t\t * Let check_object_signature() check it with\n+\t\t\t * Let stream_object_signature() check it with\n \t\t\t * the streaming interface; no point slurping\n \t\t\t * the data in-core only to discard.\n \t\t\t */\n@@ -142,8 +142,11 @@ static int verify_packfile(struct repository *r,\n \t\t\terr = error(\"cannot unpack %s from %s at offset %\"PRIuMAX\"\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n \t\t\t\t    (uintmax_t)entries[i].offset);\n-\t\telse if (check_object_signature(r, &oid, data, size,\n-\t\t\t\t\t\ttype_name(type), NULL) < 0)\n+\t\telse if (data && check_object_signature(r, &oid, data, size,\n+\t\t\t\t\t\t\ttype_name(type)) < 0)\n+\t\t\terr = error(\"packed %s from %s is corrupt\",\n+\t\t\t\t    oid_to_hex(&oid), p->pack_name);\n+\t\telse if (!data && stream_object_signature(r, &oid) < 0)\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n \t\telse if (fn) {\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447796","messageId":"patch-v3-07.12-75abf75a437-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 07/12] object API users + docs: check <0, not !0 with check_object_signature()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:29Z","receivedAt":"2022-02-04T23:49:05Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change those users of the object API that misused\ncheck_object_signature() by assuming it returned any non-zero when the\nOID didn't match the expected value to check <0 instead. In practice\nall of this code worked before, but it wasn't consistent with rest of\nthe users of the API.\n\nLet's also clarify what the <0 return value means in API docs.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/index-pack.c | 5 ++---\n builtin/mktag.c      | 2 +-\n cache.h              | 3 +++\n object-file.c        | 2 +-\n pack-check.c         | 2 +-\n 5 files changed, 8 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 01574378ce2..416f60a98c1 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1412,9 +1412,8 @@ static void fix_unresolved_deltas(struct hashfile *f)\n \t\tif (!data)\n \t\t\tcontinue;\n \n-\t\tif (check_object_signature(the_repository, &d->oid,\n-\t\t\t\t\t   data, size,\n-\t\t\t\t\t   type_name(type), NULL))\n+\t\tif (check_object_signature(the_repository, &d->oid, data, size,\n+\t\t\t\t\t   type_name(type), NULL) < 0)\n \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n \n \t\t/*\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 96a3686af53..98d1e66f327 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -97,7 +97,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)\n \t\t\t\t&tagged_oid, &tagged_type))\n \t\tdie(_(\"tag on stdin did not pass our strict fsck check\"));\n \n-\tif (verify_object_in_tag(&tagged_oid, &tagged_type))\n+\tif (verify_object_in_tag(&tagged_oid, &tagged_type) < 0)\n \t\tdie(_(\"tag on stdin did not refer to a valid object\"));\n \n \tif (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0)\ndiff --git a/cache.h b/cache.h\nindex 98d1ef08579..5d081952121 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1324,6 +1324,9 @@ int parse_loose_header(const char *hdr, struct object_info *oi);\n  * object name actually matches \"oid\" to detect object corruption.\n  * With \"buf\" == NULL, try reading the object named with \"oid\" using\n  * the streaming interface and rehash it to do the same.\n+ *\n+ * A negative value indicates an error, usually that the OID is not\n+ * what we expected, but it might also indicate another error.\n  */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\t\t   void *buf, unsigned long size, const char *type,\ndiff --git a/object-file.c b/object-file.c\nindex 44e0b32d71a..d628f58c0d2 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2613,7 +2613,7 @@ int read_loose_object(const char *path,\n \t\t}\n \t\tif (check_object_signature(the_repository, expected_oid,\n \t\t\t\t\t   *contents, *size,\n-\t\t\t\t\t   oi->type_name->buf, real_oid))\n+\t\t\t\t\t   oi->type_name->buf, real_oid) < 0)\n \t\t\tgoto out;\n \t}\n \ndiff --git a/pack-check.c b/pack-check.c\nindex 3f418e3a6af..48d818ee7b4 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -143,7 +143,7 @@ static int verify_packfile(struct repository *r,\n \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n \t\t\t\t    (uintmax_t)entries[i].offset);\n \t\telse if (check_object_signature(r, &oid, data, size,\n-\t\t\t\t\t\ttype_name(type), NULL))\n+\t\t\t\t\t\ttype_name(type), NULL) < 0)\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n \t\telse if (fn) {\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447797","messageId":"patch-v3-10.12-2c936c674d4-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 10/12] object-file API: have hash_object_file() take \"enum object_type\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:32Z","receivedAt":"2022-02-04T23:49:07Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the hash_object_file() function to take an \"enum\nobject_type\".\n\nSince a preceding commit all of its callers are passing either\n\"{commit,tree,blob,tag}_type\", or the result of a call to type_name(),\nthe parse_object() caller that would pass NULL is now using\nstream_object_signature().\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n apply.c                  |  4 ++--\n builtin/fast-export.c    |  2 +-\n builtin/index-pack.c     |  4 ++--\n builtin/mktag.c          |  2 +-\n builtin/replace.c        |  2 +-\n builtin/unpack-objects.c |  2 +-\n cache-tree.c             |  6 +++---\n cache.h                  |  3 ++-\n convert.c                |  2 +-\n diffcore-rename.c        |  2 +-\n dir.c                    |  2 +-\n log-tree.c               |  2 +-\n object-file.c            | 35 +++++++++++++++++++++--------------\n object-store.h           |  2 +-\n object.c                 |  3 +--\n pack-check.c             |  2 +-\n 16 files changed, 41 insertions(+), 34 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex e82a7c30f01..8513755e254 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -3157,7 +3157,7 @@ static int apply_binary(struct apply_state *state,\n \t\t * See if the old one matches what the patch\n \t\t * applies to.\n \t\t */\n-\t\thash_object_file(the_hash_algo, img->buf, img->len, blob_type,\n+\t\thash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,\n \t\t\t\t &oid);\n \t\tif (strcmp(oid_to_hex(&oid), patch->old_oid_prefix))\n \t\t\treturn error(_(\"the patch applies to '%s' (%s), \"\n@@ -3203,7 +3203,7 @@ static int apply_binary(struct apply_state *state,\n \t\t\t\t     name);\n \n \t\t/* verify that the result matches */\n-\t\thash_object_file(the_hash_algo, img->buf, img->len, blob_type,\n+\t\thash_object_file(the_hash_algo, img->buf, img->len, OBJ_BLOB,\n \t\t\t\t &oid);\n \t\tif (strcmp(oid_to_hex(&oid), patch->new_oid_prefix))\n \t\t\treturn error(_(\"binary patch to '%s' creates incorrect result (expecting %s, got %s)\"),\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex 319859db30e..52aebeb5214 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -300,7 +300,7 @@ static void export_blob(const struct object_id *oid)\n \t\tif (!buf)\n \t\t\tdie(\"could not read blob %s\", oid_to_hex(oid));\n \t\tif (check_object_signature(the_repository, oid, buf, size,\n-\t\t\t\t\t   type_name(type)) < 0)\n+\t\t\t\t\t   type) < 0)\n \t\t\tdie(\"oid mismatch in blob %s\", oid_to_hex(oid));\n \t\tobject = parse_object_buffer(the_repository, oid, type,\n \t\t\t\t\t     size, buf, &eaten);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex e1927205a7b..d0c3e0966b7 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -970,7 +970,7 @@ static struct base_data *resolve_delta(struct object_entry *delta_obj,\n \tif (!result_data)\n \t\tbad_object(delta_obj->idx.offset, _(\"failed to apply delta\"));\n \thash_object_file(the_hash_algo, result_data, result_size,\n-\t\t\t type_name(delta_obj->real_type), &delta_obj->idx.oid);\n+\t\t\t delta_obj->real_type, &delta_obj->idx.oid);\n \tsha1_object(result_data, NULL, result_size, delta_obj->real_type,\n \t\t    &delta_obj->idx.oid);\n \n@@ -1413,7 +1413,7 @@ static void fix_unresolved_deltas(struct hashfile *f)\n \t\t\tcontinue;\n \n \t\tif (check_object_signature(the_repository, &d->oid, data, size,\n-\t\t\t\t\t   type_name(type)) < 0)\n+\t\t\t\t\t   type) < 0)\n \t\t\tdie(_(\"local object %s is corrupt\"), oid_to_hex(&d->oid));\n \n \t\t/*\ndiff --git a/builtin/mktag.c b/builtin/mktag.c\nindex 4d28eceeba6..14b9fe3bc0a 100644\n--- a/builtin/mktag.c\n+++ b/builtin/mktag.c\n@@ -62,7 +62,7 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)\n \n \trepl = lookup_replace_object(the_repository, tagged_oid);\n \tret = check_object_signature(the_repository, repl, buffer, size,\n-\t\t\t\t     type_name(*tagged_type));\n+\t\t\t\t     *tagged_type);\n \tfree(buffer);\n \n \treturn ret;\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 995ca683302..53a3b246570 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -409,7 +409,7 @@ static int check_one_mergetag(struct commit *commit,\n \tint i;\n \n \thash_object_file(the_hash_algo, extra->value, extra->len,\n-\t\t\t type_name(OBJ_TAG), &tag_oid);\n+\t\t\t OBJ_TAG, &tag_oid);\n \ttag = lookup_tag(the_repository, &tag_oid);\n \tif (!tag)\n \t\treturn error(_(\"bad mergetag in commit '%s'\"), ref);\ndiff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c\nindex 808041551fd..dbeb0680a58 100644\n--- a/builtin/unpack-objects.c\n+++ b/builtin/unpack-objects.c\n@@ -266,7 +266,7 @@ static void write_object(unsigned nr, enum object_type type,\n \t} else {\n \t\tstruct object *obj;\n \t\tint eaten;\n-\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n+\t\thash_object_file(the_hash_algo, buf, size, type,\n \t\t\t\t &obj_list[nr].oid);\n \t\tadded_object(nr, type, buf, size);\n \t\tobj = parse_object_buffer(the_repository, &obj_list[nr].oid,\ndiff --git a/cache-tree.c b/cache-tree.c\nindex fdbbd191d22..6752f69d515 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -432,14 +432,14 @@ static int update_one(struct cache_tree *it,\n \tif (repair) {\n \t\tstruct object_id oid;\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n-\t\t\t\t tree_type, &oid);\n+\t\t\t\t OBJ_TREE, &oid);\n \t\tif (has_object_file_with_flags(&oid, OBJECT_INFO_SKIP_FETCH_OBJECT))\n \t\t\toidcpy(&it->oid, &oid);\n \t\telse\n \t\t\tto_invalidate = 1;\n \t} else if (dryrun) {\n \t\thash_object_file(the_hash_algo, buffer.buf, buffer.len,\n-\t\t\t\t tree_type, &it->oid);\n+\t\t\t\t OBJ_TREE, &it->oid);\n \t} else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE,\n \t\t\t\t\t   &it->oid, flags & WRITE_TREE_SILENT\n \t\t\t\t\t   ? HASH_SILENT : 0)) {\n@@ -948,7 +948,7 @@ static int verify_one(struct repository *r,\n \t\tstrbuf_addf(&tree_buf, \"%o %.*s%c\", mode, entlen, name, '\\0');\n \t\tstrbuf_add(&tree_buf, oid->hash, r->hash_algo->rawsz);\n \t}\n-\thash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, tree_type,\n+\thash_object_file(r->hash_algo, tree_buf.buf, tree_buf.len, OBJ_TREE,\n \t\t\t &new_oid);\n \tif (!oideq(&new_oid, &it->oid))\n \t\tBUG(\"cache-tree for path %.*s does not match. \"\ndiff --git a/cache.h b/cache.h\nindex c068f99c793..2027803c49a 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1327,7 +1327,8 @@ int parse_loose_header(const char *hdr, struct object_info *oi);\n  * what we expected, but it might also indicate another error.\n  */\n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type);\n+\t\t\t   void *map, unsigned long size,\n+\t\t\t   enum object_type type);\n \n /**\n  * A streaming version of check_object_signature().\ndiff --git a/convert.c b/convert.c\nindex df7186bd813..d88072fe320 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -1159,7 +1159,7 @@ static int ident_to_worktree(const char *src, size_t len,\n \t/* are we \"faking\" in place editing ? */\n \tif (src == buf->buf)\n \t\tto_free = strbuf_detach(buf, NULL);\n-\thash_object_file(the_hash_algo, src, len, \"blob\", &oid);\n+\thash_object_file(the_hash_algo, src, len, OBJ_BLOB, &oid);\n \n \tstrbuf_grow(buf, len + cnt * (the_hash_algo->hexsz + 3));\n \tfor (;;) {\ndiff --git a/diffcore-rename.c b/diffcore-rename.c\nindex bebd4ed6a42..c0422d9e709 100644\n--- a/diffcore-rename.c\n+++ b/diffcore-rename.c\n@@ -261,7 +261,7 @@ static unsigned int hash_filespec(struct repository *r,\n \t\tif (diff_populate_filespec(r, filespec, NULL))\n \t\t\treturn 0;\n \t\thash_object_file(r->hash_algo, filespec->data, filespec->size,\n-\t\t\t\t \"blob\", &filespec->oid);\n+\t\t\t\t OBJ_BLOB, &filespec->oid);\n \t}\n \treturn oidhash(&filespec->oid);\n }\ndiff --git a/dir.c b/dir.c\nindex d91295f2bcd..5674e8a6256 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1113,7 +1113,7 @@ static int add_patterns(const char *fname, const char *base, int baselen,\n \t\t\t\t       &istate->cache[pos]->oid);\n \t\t\telse\n \t\t\t\thash_object_file(the_hash_algo, buf, size,\n-\t\t\t\t\t\t \"blob\", &oid_stat->oid);\n+\t\t\t\t\t\t OBJ_BLOB, &oid_stat->oid);\n \t\t\tfill_stat_data(&oid_stat->stat, &st);\n \t\t\toid_stat->valid = 1;\n \t\t}\ndiff --git a/log-tree.c b/log-tree.c\nindex d3e7a40b648..27a5b0bd61a 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -561,7 +561,7 @@ static int show_one_mergetag(struct commit *commit,\n \tstruct strbuf signature = STRBUF_INIT;\n \n \thash_object_file(the_hash_algo, extra->value, extra->len,\n-\t\t\t type_name(OBJ_TAG), &oid);\n+\t\t\t OBJ_TAG, &oid);\n \ttag = lookup_tag(the_repository, &oid);\n \tif (!tag)\n \t\treturn -1; /* error message already given */\ndiff --git a/object-file.c b/object-file.c\nindex 9e5b849693e..b1cb78c4419 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1067,7 +1067,8 @@ int format_object_header(char *str, size_t size, enum object_type type,\n }\n \n int check_object_signature(struct repository *r, const struct object_id *oid,\n-\t\t\t   void *buf, unsigned long size, const char *type)\n+\t\t\t   void *buf, unsigned long size,\n+\t\t\t   enum object_type type)\n {\n \tstruct object_id real_oid;\n \n@@ -1676,7 +1677,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,\n {\n \tstruct cached_object *co;\n \n-\thash_object_file(the_hash_algo, buf, len, type_name(type), oid);\n+\thash_object_file(the_hash_algo, buf, len, type, oid);\n \tif (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) ||\n \t    find_cached_object(oid))\n \t\treturn 0;\n@@ -1850,15 +1851,23 @@ static int write_buffer(int fd, const void *buf, size_t len)\n \treturn 0;\n }\n \n-void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t     unsigned long len, const char *type,\n-\t\t     struct object_id *oid)\n+static void hash_object_file_literally(const struct git_hash_algo *algo,\n+\t\t\t\t       const void *buf, unsigned long len,\n+\t\t\t\t       const char *type, struct object_id *oid)\n {\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n+\n \twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n+void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n+\t\t      unsigned long len, enum object_type type,\n+\t\t      struct object_id *oid)\n+{\n+\thash_object_file_literally(algo, buf, len, type_name(type), oid);\n+}\n+\n /* Finalize a file on disk, and close it. */\n static void close_loose_object(int fd)\n {\n@@ -2161,9 +2170,7 @@ static int index_mem(struct index_state *istate,\n \tif (write_object)\n \t\tret = write_object_file(buf, size, type, oid);\n \telse\n-\t\thash_object_file(the_hash_algo, buf, size, type_name(type),\n-\t\t\t\t oid);\n-\n+\t\thash_object_file(the_hash_algo, buf, size, type, oid);\n \tif (re_allocated)\n \t\tfree(buf);\n \treturn ret;\n@@ -2189,8 +2196,8 @@ static int index_stream_convert_blob(struct index_state *istate,\n \t\tret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB,\n \t\t\t\t\toid);\n \telse\n-\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len,\n-\t\t\t\t type_name(OBJ_BLOB), oid);\n+\t\thash_object_file(the_hash_algo, sbuf.buf, sbuf.len, OBJ_BLOB,\n+\t\t\t\t oid);\n \tstrbuf_release(&sbuf);\n \treturn ret;\n }\n@@ -2309,7 +2316,7 @@ int index_path(struct index_state *istate, struct object_id *oid,\n \t\t\treturn error_errno(\"readlink(\\\"%s\\\")\", path);\n \t\tif (!(flags & HASH_WRITE_OBJECT))\n \t\t\thash_object_file(the_hash_algo, sb.buf, sb.len,\n-\t\t\t\t\t blob_type, oid);\n+\t\t\t\t\t OBJ_BLOB, oid);\n \t\telse if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid))\n \t\t\trc = error(_(\"%s: failed to insert into database\"), path);\n \t\tstrbuf_release(&sb);\n@@ -2614,9 +2621,9 @@ int read_loose_object(const char *path,\n \t\t\tgit_inflate_end(&stream);\n \t\t\tgoto out;\n \t\t}\n-\t\thash_object_file(the_repository->hash_algo,\n-\t\t\t\t *contents, *size, oi->type_name->buf,\n-\t\t\t\t real_oid);\n+\t\thash_object_file_literally(the_repository->hash_algo,\n+\t\t\t\t\t   *contents, *size,\n+\t\t\t\t\t   oi->type_name->buf, real_oid);\n \t\tif (!oideq(expected_oid, real_oid))\n \t\t\tgoto out;\n \t}\ndiff --git a/object-store.h b/object-store.h\nindex 29169d117f7..bd2322ed8ce 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -246,7 +246,7 @@ static inline void *repo_read_object_file(struct repository *r,\n int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);\n \n void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n-\t\t      unsigned long len, const char *type,\n+\t\t      unsigned long len, enum object_type type,\n \t\t      struct object_id *oid);\n \n int write_object_file_flags(const void *buf, unsigned long len,\ndiff --git a/object.c b/object.c\nindex d07678ef6da..588b8156f1d 100644\n--- a/object.c\n+++ b/object.c\n@@ -289,8 +289,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)\n \n \tbuffer = repo_read_object_file(r, oid, &type, &size);\n \tif (buffer) {\n-\t\tif (check_object_signature(r, repl, buffer, size,\n-\t\t\t\t\t   type_name(type)) < 0) {\n+\t\tif (check_object_signature(r, repl, buffer, size, type) < 0) {\n \t\t\tfree(buffer);\n \t\t\terror(_(\"hash mismatch %s\"), oid_to_hex(repl));\n \t\t\treturn NULL;\ndiff --git a/pack-check.c b/pack-check.c\nindex d8d8f91de6b..bfb593ba726 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -143,7 +143,7 @@ static int verify_packfile(struct repository *r,\n \t\t\t\t    oid_to_hex(&oid), p->pack_name,\n \t\t\t\t    (uintmax_t)entries[i].offset);\n \t\telse if (data && check_object_signature(r, &oid, data, size,\n-\t\t\t\t\t\t\ttype_name(type)) < 0)\n+\t\t\t\t\t\t\ttype) < 0)\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    oid_to_hex(&oid), p->pack_name);\n \t\telse if (!data && stream_object_signature(r, &oid) < 0)\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447798","messageId":"patch-v3-12.12-d2d355e6bb8-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 12/12] object-file API: pass an enum to read_object_with_reference()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:34Z","receivedAt":"2022-02-04T23:49:08Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change the read_object_with_reference() function to take an \"enum\nobject_type\". It was not prepared to handle an arbitrary \"const\nchar *type\", as it was itself calling type_from_string().\n\nLet's change the only caller that passes in user data to use\ntype_from_string(), and convert the rest to use e.g. \"OBJ_TREE\"\ninstead of \"tree_type\".\n\nThe \"cat-file\" caller is not on the codepath that\nhandles\"--allow-unknown\", so the type_from_string() there is safe. Its\nuse of type_from_string() doesn't functionally differ from that of the\npre-image.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n builtin/cat-file.c     | 11 +++++++----\n builtin/fast-import.c  |  6 +++---\n builtin/grep.c         |  4 ++--\n builtin/pack-objects.c |  2 +-\n cache.h                |  2 +-\n object-file.c          |  5 ++---\n tree-walk.c            |  6 +++---\n 7 files changed, 19 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex d94050e6c18..3c5bc505e0a 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -154,7 +154,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\tbreak;\n \n \tcase 0:\n-\t\tif (type_from_string(exp_type) == OBJ_BLOB) {\n+\t{\n+\t\tenum object_type exp_type_id = type_from_string(exp_type);\n+\n+\t\tif (exp_type_id == OBJ_BLOB) {\n \t\t\tstruct object_id blob_oid;\n \t\t\tif (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) {\n \t\t\t\tchar *buffer = read_object_file(&oid, &type,\n@@ -176,10 +179,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n \t\t\t * fall-back to the usual case.\n \t\t\t */\n \t\t}\n-\t\tbuf = read_object_with_reference(the_repository,\n-\t\t\t\t\t\t &oid, exp_type, &size, NULL);\n+\t\tbuf = read_object_with_reference(the_repository, &oid,\n+\t\t\t\t\t\t exp_type_id, &size, NULL);\n \t\tbreak;\n-\n+\t}\n \tdefault:\n \t\tdie(\"git cat-file: unknown option: %s\", exp_type);\n \t}\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 123df7d9a53..c52e807f56e 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -2483,7 +2483,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa\n \t\tunsigned long size;\n \t\tchar *buf = read_object_with_reference(the_repository,\n \t\t\t\t\t\t       &commit_oid,\n-\t\t\t\t\t\t       commit_type, &size,\n+\t\t\t\t\t\t       OBJ_COMMIT, &size,\n \t\t\t\t\t\t       &commit_oid);\n \t\tif (!buf || size < the_hash_algo->hexsz + 6)\n \t\t\tdie(\"Not a valid commit: %s\", p);\n@@ -2555,7 +2555,7 @@ static void parse_from_existing(struct branch *b)\n \t\tchar *buf;\n \n \t\tbuf = read_object_with_reference(the_repository,\n-\t\t\t\t\t\t &b->oid, commit_type, &size,\n+\t\t\t\t\t\t &b->oid, OBJ_COMMIT, &size,\n \t\t\t\t\t\t &b->oid);\n \t\tparse_from_commit(b, buf, size);\n \t\tfree(buf);\n@@ -2651,7 +2651,7 @@ static struct hash_list *parse_merge(unsigned int *count)\n \t\t\tunsigned long size;\n \t\t\tchar *buf = read_object_with_reference(the_repository,\n \t\t\t\t\t\t\t       &n->oid,\n-\t\t\t\t\t\t\t       commit_type,\n+\t\t\t\t\t\t\t       OBJ_COMMIT,\n \t\t\t\t\t\t\t       &size, &n->oid);\n \t\t\tif (!buf || size < the_hash_algo->hexsz + 6)\n \t\t\t\tdie(\"Not a valid commit: %s\", from);\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 9e34a820ad4..75e07b5623a 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -482,7 +482,7 @@ static int grep_submodule(struct grep_opt *opt,\n \t\tobject_type = oid_object_info(subrepo, oid, NULL);\n \t\tobj_read_unlock();\n \t\tdata = read_object_with_reference(subrepo,\n-\t\t\t\t\t\t  oid, tree_type,\n+\t\t\t\t\t\t  oid, OBJ_TREE,\n \t\t\t\t\t\t  &size, NULL);\n \t\tif (!data)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(oid));\n@@ -651,7 +651,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,\n \t\tint hit, len;\n \n \t\tdata = read_object_with_reference(opt->repo,\n-\t\t\t\t\t\t  &obj->oid, tree_type,\n+\t\t\t\t\t\t  &obj->oid, OBJ_TREE,\n \t\t\t\t\t\t  &size, NULL);\n \t\tif (!data)\n \t\t\tdie(_(\"unable to read tree (%s)\"), oid_to_hex(&obj->oid));\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex ba2006f2212..c4df3df3141 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1802,7 +1802,7 @@ static void add_preferred_base(struct object_id *oid)\n \t\treturn;\n \n \tdata = read_object_with_reference(the_repository, oid,\n-\t\t\t\t\t  tree_type, &size, &tree_oid);\n+\t\t\t\t\t  OBJ_TREE, &size, &tree_oid);\n \tif (!data)\n \t\treturn;\n \ndiff --git a/cache.h b/cache.h\nindex 2027803c49a..0e7fc8b7c2f 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1561,7 +1561,7 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char\n \n void *read_object_with_reference(struct repository *r,\n \t\t\t\t const struct object_id *oid,\n-\t\t\t\t const char *required_type,\n+\t\t\t\t enum object_type required_type,\n \t\t\t\t unsigned long *size,\n \t\t\t\t struct object_id *oid_ret);\n \ndiff --git a/object-file.c b/object-file.c\nindex c75c12dd0ba..6cbdb836cb7 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1737,16 +1737,15 @@ void *read_object_file_extended(struct repository *r,\n \n void *read_object_with_reference(struct repository *r,\n \t\t\t\t const struct object_id *oid,\n-\t\t\t\t const char *required_type_name,\n+\t\t\t\t enum object_type required_type,\n \t\t\t\t unsigned long *size,\n \t\t\t\t struct object_id *actual_oid_return)\n {\n-\tenum object_type type, required_type;\n+\tenum object_type type;\n \tvoid *buffer;\n \tunsigned long isize;\n \tstruct object_id actual_oid;\n \n-\trequired_type = type_from_string(required_type_name);\n \toidcpy(&actual_oid, oid);\n \twhile (1) {\n \t\tint ref_length = -1;\ndiff --git a/tree-walk.c b/tree-walk.c\nindex 3a94959d64a..506234b4b81 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -89,7 +89,7 @@ void *fill_tree_descriptor(struct repository *r,\n \tvoid *buf = NULL;\n \n \tif (oid) {\n-\t\tbuf = read_object_with_reference(r, oid, tree_type, &size, NULL);\n+\t\tbuf = read_object_with_reference(r, oid, OBJ_TREE, &size, NULL);\n \t\tif (!buf)\n \t\t\tdie(\"unable to read tree %s\", oid_to_hex(oid));\n \t}\n@@ -605,7 +605,7 @@ int get_tree_entry(struct repository *r,\n \tunsigned long size;\n \tstruct object_id root;\n \n-\ttree = read_object_with_reference(r, tree_oid, tree_type, &size, &root);\n+\ttree = read_object_with_reference(r, tree_oid, OBJ_TREE, &size, &root);\n \tif (!tree)\n \t\treturn -1;\n \n@@ -677,7 +677,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r,\n \t\t\tunsigned long size;\n \t\t\ttree = read_object_with_reference(r,\n \t\t\t\t\t\t\t  &current_tree_oid,\n-\t\t\t\t\t\t\t  tree_type, &size,\n+\t\t\t\t\t\t\t  OBJ_TREE, &size,\n \t\t\t\t\t\t\t  &root);\n \t\t\tif (!tree)\n \t\t\t\tgoto done;\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"447799","messageId":"patch-v3-11.12-ad1a777f454-20220204T234435Z-avarab@gmail.com","threadId":"57347","inReplyTo":"cover-v3-00.12-00000000000-20220204T234435Z-avarab@gmail.com","subject":"[PATCH v3 11/12] object-file.c: add a literal version of write_object_file_prepare()","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-04T23:48:33Z","receivedAt":"2022-02-04T23:49:11Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split off a *_literally() variant of the write_object_file_prepare()\nfunction. To do this create a new \"hash_object_body()\" static helper.\n\nWe now defer the type_name() call until the very last moment in\nformat_object_header() for those callers that aren't \"hash-object\n--literally\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n object-file.c | 39 +++++++++++++++++++++++++++++----------\n 1 file changed, 29 insertions(+), 10 deletions(-)\n\ndiff --git a/object-file.c b/object-file.c\nindex b1cb78c4419..c75c12dd0ba 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1784,21 +1784,40 @@ void *read_object_with_reference(struct repository *r,\n \t}\n }\n \n+static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c,\n+\t\t\t     const void *buf, unsigned long len,\n+\t\t\t     struct object_id *oid,\n+\t\t\t     char *hdr, int *hdrlen)\n+{\n+\talgo->init_fn(c);\n+\talgo->update_fn(c, hdr, *hdrlen);\n+\talgo->update_fn(c, buf, len);\n+\talgo->final_oid_fn(oid, c);\n+}\n+\n static void write_object_file_prepare(const struct git_hash_algo *algo,\n \t\t\t\t      const void *buf, unsigned long len,\n-\t\t\t\t      const char *type, struct object_id *oid,\n+\t\t\t\t      enum object_type type, struct object_id *oid,\n \t\t\t\t      char *hdr, int *hdrlen)\n {\n \tgit_hash_ctx c;\n \n \t/* Generate the header */\n-\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n+\t*hdrlen = format_object_header(hdr, *hdrlen, type, len);\n \n \t/* Sha1.. */\n-\talgo->init_fn(&c);\n-\talgo->update_fn(&c, hdr, *hdrlen);\n-\talgo->update_fn(&c, buf, len);\n-\talgo->final_oid_fn(oid, &c);\n+\thash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);\n+}\n+\n+static void write_object_file_prepare_literally(const struct git_hash_algo *algo,\n+\t\t\t\t      const void *buf, unsigned long len,\n+\t\t\t\t      const char *type, struct object_id *oid,\n+\t\t\t\t      char *hdr, int *hdrlen)\n+{\n+\tgit_hash_ctx c;\n+\n+\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n+\thash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);\n }\n \n /*\n@@ -1858,7 +1877,7 @@ static void hash_object_file_literally(const struct git_hash_algo *algo,\n \tchar hdr[MAX_HEADER_LEN];\n \tint hdrlen = sizeof(hdr);\n \n-\twrite_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);\n+\twrite_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen);\n }\n \n void hash_object_file(const struct git_hash_algo *algo, const void *buf,\n@@ -2029,7 +2048,7 @@ int write_object_file_flags(const void *buf, unsigned long len,\n \t/* Normally if we have it in the pack then we do not bother writing\n \t * it out into .git/objects/??/?{38} file.\n \t */\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type_name(type), oid, hdr,\n+\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr,\n \t\t\t\t  &hdrlen);\n \tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n \t\treturn 0;\n@@ -2046,8 +2065,8 @@ int write_object_file_literally(const void *buf, unsigned long len,\n \t/* type string, SP, %lu of the length plus NUL must fit this */\n \thdrlen = strlen(type) + MAX_HEADER_LEN;\n \theader = xmalloc(hdrlen);\n-\twrite_object_file_prepare(the_hash_algo, buf, len, type, oid, header,\n-\t\t\t\t  &hdrlen);\n+\twrite_object_file_prepare_literally(the_hash_algo, buf, len, type,\n+\t\t\t\t\t    oid, header, &hdrlen);\n \n \tif (!(flags & HASH_WRITE_OBJECT))\n \t\tgoto cleanup;\n-- \n2.35.1.940.ge7a5b4b05f2\n\n"},{"id":"448659","messageId":"20220217045943.30223-1-worldhello.net@gmail.com","threadId":"57347","inReplyTo":"patch-v3-03.12-92fd020d199-20220204T234435Z-avarab@gmail.com","subject":"RE: [PATCH v3 03/12] object-file API: add a format_object_header() function","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2022-02-17T04:59:43Z","receivedAt":"2022-02-17T05:00:03Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"From: Jiang Xin <zhiyou.jx@alibaba-inc.com>\n\nOn Sat, Feb 5, 2022 Ævar Arnfjörð Bjarmason wrote:\n\n> diff --git a/builtin/fast-import.c b/builtin/fast-import.c\n> index 2b2e28bad79..123df7d9a53 100644\n> --- a/builtin/fast-import.c\n> +++ b/builtin/fast-import.c\n> @@ -937,8 +937,8 @@ static int store_object(\n>  \tgit_hash_ctx c;\n>  \tgit_zstream s;\n>  \n> -\thdrlen = xsnprintf((char *)hdr, sizeof(hdr), \"%s %lu\",\n> -\t\t\t   type_name(type), (unsigned long)dat->len) + 1;\n> +\thdrlen = format_object_header((char *)hdr, sizeof(hdr), type,\n> +\t\t\t\t      dat->len);\n\nType casting can be avoid if we use \"void *\" as the first parameter of\n\"format_object_header\", and do type casting inside the helper function.\n\n> diff --git a/object-file.c b/object-file.c\n> index eeb6814780a..3fcd46cf9ed 100644\n> --- a/object-file.c\n> +++ b/object-file.c\n> @@ -1049,6 +1049,23 @@ void *xmmap(void *start, size_t length,\n>  \treturn ret;\n>  }\n>  \n> +static int format_object_header_literally(char *str, size_t size,\n> +\t\t\t\t\t  const char *type, size_t objsize)\n> +{\n> +\treturn xsnprintf(str, size, \"%s %\"PRIuMAX, type, (uintmax_t)objsize) + 1;\n> +}\n> +\n> +int format_object_header(char *str, size_t size, enum object_type type,\n> +\t\t\t size_t objsize)\n> +{\n> +\tconst char *name = type_name(type);\n> +\n> +\tif (!name)\n> +\t\tBUG(\"could not get a type name for 'enum object_type' value %d\", type);\n> +\n\nThe return value of `type_name(type)` has not been checked for the original\nimplement, how about write a online inline-function in a header file like this:\n\n\tstatic inline int format_object_header(void *str, size_t size,\n\t\t\t\t\t       const char *type_name,\n\t\t\t\t\t       size_t objsize)\n\t{\n\t\treturn xsnprintf((char *)str, size, \"%s %\"PRIuMAX, type_name,\n\t\t\t\t (uintmax_t)objsize) + 1;\n\t}\n \n> +\treturn format_object_header_literally(str, size, name, objsize);\n> +}\n\n\n--- >8 ---\nFrom: Jiang Xin <zhiyou.jx@alibaba-inc.com>\nDate: Thu, 17 Feb 2022 11:35:27 +0800\nSubject: [PATCH] fixup! object-file API: add a format_object_header() function\n\nSigned-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>\n---\n builtin/fast-import.c |  4 ++--\n builtin/index-pack.c  |  3 ++-\n bulk-checkin.c        |  4 ++--\n http-push.c           |  2 +-\n object-file.c         | 23 +++--------------------\n object-store.h        |  9 +++++++--\n 6 files changed, 17 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex 123df7d9a5..f5ec40fc1b 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -937,7 +937,7 @@ static int store_object(\n \tgit_hash_ctx c;\n \tgit_zstream s;\n \n-\thdrlen = format_object_header((char *)hdr, sizeof(hdr), type,\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type_name(type),\n \t\t\t\t      dat->len);\n \tthe_hash_algo->init_fn(&c);\n \tthe_hash_algo->update_fn(&c, hdr, hdrlen);\n@@ -1091,7 +1091,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)\n \thashfile_checkpoint(pack_file, &checkpoint);\n \toffset = checkpoint.offset;\n \n-\thdrlen = format_object_header((char *)out_buf, out_sz, OBJ_BLOB, len);\n+\thdrlen = format_object_header(out_buf, out_sz, \"blob\", len);\n \n \tthe_hash_algo->init_fn(&c);\n \tthe_hash_algo->update_fn(&c, out_buf, hdrlen);\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex 01574378ce..a37533333e 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -449,7 +449,8 @@ static void *unpack_entry_data(off_t offset, unsigned long size,\n \tint hdrlen;\n \n \tif (!is_delta_type(type)) {\n-\t\thdrlen = format_object_header(hdr, sizeof(hdr), type, size);\n+\t\thdrlen = format_object_header(hdr, sizeof(hdr), type_name(type),\n+\t\t\t\t\t      size);\n \t\tthe_hash_algo->init_fn(&c);\n \t\tthe_hash_algo->update_fn(&c, hdr, hdrlen);\n \t} else\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 85b3ebaf97..58fb59990d 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -220,8 +220,8 @@ static int deflate_to_pack(struct bulk_checkin_state *state,\n \tif (seekback == (off_t) -1)\n \t\treturn error(\"cannot find the current offset\");\n \n-\theader_len = format_object_header((char *)obuf, sizeof(obuf),\n-\t\t\t\t\t  type, size);\n+\theader_len = format_object_header(obuf, sizeof(obuf), type_name(type),\n+\t\t\t\t\t  size);\n \tthe_hash_algo->init_fn(&ctx);\n \tthe_hash_algo->update_fn(&ctx, obuf, header_len);\n \ndiff --git a/http-push.c b/http-push.c\nindex f0c044dcf7..eb2b46b2fc 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -363,7 +363,7 @@ static void start_put(struct transfer_request *request)\n \tgit_zstream stream;\n \n \tunpacked = read_object_file(&request->obj->oid, &type, &len);\n-\thdrlen = format_object_header(hdr, sizeof(hdr), type, len);\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type_name(type), len);\n \n \t/* Set it up */\n \tgit_deflate_init(&stream, zlib_compression_level);\ndiff --git a/object-file.c b/object-file.c\nindex 3fcd46cf9e..f396e78909 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -1049,23 +1049,6 @@ void *xmmap(void *start, size_t length,\n \treturn ret;\n }\n \n-static int format_object_header_literally(char *str, size_t size,\n-\t\t\t\t\t  const char *type, size_t objsize)\n-{\n-\treturn xsnprintf(str, size, \"%s %\"PRIuMAX, type, (uintmax_t)objsize) + 1;\n-}\n-\n-int format_object_header(char *str, size_t size, enum object_type type,\n-\t\t\t size_t objsize)\n-{\n-\tconst char *name = type_name(type);\n-\n-\tif (!name)\n-\t\tBUG(\"could not get a type name for 'enum object_type' value %d\", type);\n-\n-\treturn format_object_header_literally(str, size, name, objsize);\n-}\n-\n /*\n  * With an in-core object data in \"map\", rehash it to make sure the\n  * object name actually matches \"oid\" to detect object corruption.\n@@ -1094,7 +1077,7 @@ int check_object_signature(struct repository *r, const struct object_id *oid,\n \t\treturn -1;\n \n \t/* Generate the header */\n-\thdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size);\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type_name(obj_type), size);\n \n \t/* Sha1.. */\n \tr->hash_algo->init_fn(&c);\n@@ -1794,7 +1777,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo,\n \tgit_hash_ctx c;\n \n \t/* Generate the header */\n-\t*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);\n+\t*hdrlen = format_object_header(hdr, *hdrlen, type, len);\n \n \t/* Sha1.. */\n \talgo->init_fn(&c);\n@@ -2068,7 +2051,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)\n \tbuf = read_object(the_repository, oid, &type, &len);\n \tif (!buf)\n \t\treturn error(_(\"cannot read object for %s\"), oid_to_hex(oid));\n-\thdrlen = format_object_header(hdr, sizeof(hdr), type, len);\n+\thdrlen = format_object_header(hdr, sizeof(hdr), type_name(type), len);\n \tret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);\n \tfree(buf);\n \ndiff --git a/object-store.h b/object-store.h\nindex 8b4413d0ce..33b5add7ab 100644\n--- a/object-store.h\n+++ b/object-store.h\n@@ -336,8 +336,13 @@ int has_loose_object_nonlocal(const struct object_id *);\n  * writes the initial \"<type> <obj-len>\" part of the loose object\n  * header. It returns the size that snprintf() returns + 1.\n  */\n-int format_object_header(char *str, size_t size, enum object_type type,\n-\t\t\t size_t objsize);\n+static inline int format_object_header(void *str, size_t size,\n+\t\t\t\t       const char *type_name,\n+\t\t\t\t       size_t objsize)\n+{\n+\treturn xsnprintf((char *)str, size, \"%s %\"PRIuMAX, type_name,\n+\t\t\t (uintmax_t)objsize) + 1;\n+}\n \n void assert_oid_type(const struct object_id *oid, enum object_type expect);\n \n-- \n2.35.0.rc2\n\n"},{"id":"448674","messageId":"220217.86mtipj14m.gmgdl@evledraar.gmail.com","threadId":"57347","inReplyTo":"20220217045943.30223-1-worldhello.net@gmail.com","subject":"Re: [PATCH v3 03/12] object-file API: add a format_object_header() function","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-02-17T09:21:38Z","receivedAt":"2022-02-17T09:27:04Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Thu, Feb 17 2022, Jiang Xin wrote:\n\n> From: Jiang Xin <zhiyou.jx@alibaba-inc.com>\n>\n> On Sat, Feb 5, 2022 Ævar Arnfjörð Bjarmason wrote:\n>\n>> diff --git a/builtin/fast-import.c b/builtin/fast-import.c\n>> index 2b2e28bad79..123df7d9a53 100644\n>> --- a/builtin/fast-import.c\n>> +++ b/builtin/fast-import.c\n>> @@ -937,8 +937,8 @@ static int store_object(\n>>  \tgit_hash_ctx c;\n>>  \tgit_zstream s;\n>>  \n>> -\thdrlen = xsnprintf((char *)hdr, sizeof(hdr), \"%s %lu\",\n>> -\t\t\t   type_name(type), (unsigned long)dat->len) + 1;\n>> +\thdrlen = format_object_header((char *)hdr, sizeof(hdr), type,\n>> +\t\t\t\t      dat->len);\n>\n> Type casting can be avoid if we use \"void *\" as the first parameter of\n> \"format_object_header\", and do type casting inside the helper function.\n> [...]\n> The return value of `type_name(type)` has not been checked for the original\n> implement, how about write a online inline-function in a header file like this:\n>\n> \tstatic inline int format_object_header(void *str, size_t size,\n> \t\t\t\t\t       const char *type_name,\n> \t\t\t\t\t       size_t objsize)\n> \t{\n> \t\treturn xsnprintf((char *)str, size, \"%s %\"PRIuMAX, type_name,\n> \t\t\t\t (uintmax_t)objsize) + 1;\n> \t}\n\nI don't think the casting in the callers is bad, in that for the callers\nthat do use \"char *\" we get the compiler to help us with type checking.\n\nUsing a void * is something we really reserve only for callback-type\nvalues, because it mens that now nobody gets any type checking.\n\nI think if we wanted to avoid the casts it would make more sense to add\na trivial ucformat_object_header() wrapper or whatever, which would take\n\"unsigned chan *\" and do the cast, or just tweak the relevant calling\ncode to change the type (IIRC some of it used unsigned v.s. signed for\nno particular reason).\n\nBut I think just leaving this part as it is is better here...\n\n> [...]\n>> +\tif (!name)\n>> +\t\tBUG(\"could not get a type name for 'enum object_type' value %d\", type);\n>> +\n>\n> The return value of `type_name(type)` has not been checked for the original\n> implement, how about write a online inline-function in a header file like this:\n\nYes, this part is not a faithful conversion on my part, but I think it\nmade sense when converting this to a library function.\n\nThe alternative is that we'd segfault on some platforms (not glibc,\nsince it's OK with null %s arguments), just checking it is cheap & I\nthink a good sanity check...\n"},{"id":"449851","messageId":"CANYiYbFZN=mvcxRT4Cf4Gzao89KR2UjMJXnJM63S2zAtbD32Jg@mail.gmail.com","threadId":"57347","inReplyTo":"220217.86mtipj14m.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH v3 03/12] object-file API: add a format_object_header() function","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2022-03-01T03:09:16Z","receivedAt":"2022-03-01T03:09:36Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"On Thu, Feb 17, 2022 at 5:25 PM Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n>\n>\n> On Thu, Feb 17 2022, Jiang Xin wrote:\n>\n> > From: Jiang Xin <zhiyou.jx@alibaba-inc.com>\n> >\n> > Type casting can be avoid if we use \"void *\" as the first parameter of\n> > \"format_object_header\", and do type casting inside the helper function.\n> > [...]\n> > The return value of `type_name(type)` has not been checked for the original\n> > implement, how about write a online inline-function in a header file like this:\n> >\n> >       static inline int format_object_header(void *str, size_t size,\n> >                                              const char *type_name,\n> >                                              size_t objsize)\n> >       {\n> >               return xsnprintf((char *)str, size, \"%s %\"PRIuMAX, type_name,\n> >                                (uintmax_t)objsize) + 1;\n> >       }\n>\n> I don't think the casting in the callers is bad, in that for the callers\n> that do use \"char *\" we get the compiler to help us with type checking.\n>\n> Using a void * is something we really reserve only for callback-type\n> values, because it mens that now nobody gets any type checking.\n>\n> I think if we wanted to avoid the casts it would make more sense to add\n> a trivial ucformat_object_header() wrapper or whatever, which would take\n> \"unsigned chan *\" and do the cast, or just tweak the relevant calling\n> code to change the type (IIRC some of it used unsigned v.s. signed for\n> no particular reason).\n>\n> But I think just leaving this part as it is is better here...\n>\n> > [...]\n> >> +    if (!name)\n> >> +            BUG(\"could not get a type name for 'enum object_type' value %d\", type);\n> >> +\n> >\n> > The return value of `type_name(type)` has not been checked for the original\n> > implement, how about write a online inline-function in a header file like this:\n>\n> Yes, this part is not a faithful conversion on my part, but I think it\n> made sense when converting this to a library function.\n>\n> The alternative is that we'd segfault on some platforms (not glibc,\n> since it's OK with null %s arguments), just checking it is cheap & I\n> think a good sanity check...\n\nAfter sending the last email, I was offline for over a week due to an\nemergency at home.\n\nAccording to the rest patches of this series, your implementation of\n\"format_object_header()\" which uses \"enum object_type\" as the\nparameter instead of \"char *type\" is better.  And adding a validation\nfor `type_name(type)` is also better than my one-line inline function.\nThis series of patches LGTM.\n\n--\nJiang Xin\n"}]}