From bbea0ddeb9bd9eefe568a9f4456cccf630704d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:23 +0100 Subject: object-file.c: split up declaration of unrelated variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split up the declaration of the "ret" and "re_allocated" variables. It's not our usual style to group variable declarations simply because they share a type, we'd only prefer to do so when the two are closely related (e.g. "int i, j"). This change makes a subsequent and meaningful change's diff smaller. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 8be57f48de..ecc7797329 100644 --- a/object-file.c +++ b/object-file.c @@ -2118,7 +2118,8 @@ static int index_mem(struct index_state *istate, enum object_type type, const char *path, unsigned flags) { - int ret, re_allocated = 0; + int ret; + int re_allocated = 0; int write_object = flags & HASH_WRITE_OBJECT; if (!type) -- cgit v1.2.3 From 63e05f90562cc8db5c450dbceeab6677b6e5351f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:24 +0100 Subject: object-file API: return "void", not "int" from hash_object_file() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hash_object_file() function added in abdc3fc8421 (Add hash_sha1_file(), 2006-10-14) did not have a meaningful return value, and it never has. One was seemingly added to avoid adding braces to the "ret = " assignments being modified here. Let's instead assign "0" to the "ret" variables at the beginning of the relevant functions, and have them return "void". Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index ecc7797329..eeb6814780 100644 --- a/object-file.c +++ b/object-file.c @@ -1836,14 +1836,13 @@ static int write_buffer(int fd, const void *buf, size_t len) return 0; } -int hash_object_file(const struct git_hash_algo *algo, const void *buf, +void hash_object_file(const struct git_hash_algo *algo, const void *buf, unsigned long len, const char *type, struct object_id *oid) { char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); - return 0; } /* Finalize a file on disk, and close it. */ @@ -2118,7 +2117,7 @@ static int index_mem(struct index_state *istate, enum object_type type, const char *path, unsigned flags) { - int ret; + int ret = 0; int re_allocated = 0; int write_object = flags & HASH_WRITE_OBJECT; @@ -2148,8 +2147,9 @@ static int index_mem(struct index_state *istate, if (write_object) ret = write_object_file(buf, size, type_name(type), oid); else - ret = hash_object_file(the_hash_algo, buf, size, - type_name(type), oid); + hash_object_file(the_hash_algo, buf, size, type_name(type), + oid); + if (re_allocated) free(buf); return ret; @@ -2161,7 +2161,7 @@ static int index_stream_convert_blob(struct index_state *istate, const char *path, unsigned flags) { - int ret; + int ret = 0; const int write_object = flags & HASH_WRITE_OBJECT; struct strbuf sbuf = STRBUF_INIT; @@ -2175,8 +2175,8 @@ static int index_stream_convert_blob(struct index_state *istate, ret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB), oid); else - ret = hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, - type_name(OBJ_BLOB), oid); + hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, + type_name(OBJ_BLOB), oid); strbuf_release(&sbuf); return ret; } -- cgit v1.2.3 From b04cdea46cf5ae60066fa6dd12d5449bf3ef283f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:25 +0100 Subject: object-file API: add a format_object_header() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a convenience function to wrap the xsnprintf() command that generates loose object headers. This code was copy/pasted in various parts of the codebase, let's define it in one place and re-use it from there. All except one caller of it had a valid "enum object_type" for us, it's only write_object_file_prepare() which might need to deal with "git hash-object --literally" and a potential garbage type. Let's have the primary API use an "enum object_type", and define a *_literally() function that can take an arbitrary "const char *" for the type. See [1] for the discussion that prompted this patch, i.e. new code in object-file.c that wanted to copy/paste the xsnprintf() invocation. In the case of fast-import.c the callers unfortunately need to cast back & forth between "unsigned char *" and "char *", since format_object_header() ad encode_in_pack_object_header() take different signedness. 1. https://lore.kernel.org/git/211213.86bl1l9bfz.gmgdl@evledraar.gmail.com/ Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Jiang Xin Signed-off-by: Junio C Hamano --- object-file.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index eeb6814780..3fcd46cf9e 100644 --- a/object-file.c +++ b/object-file.c @@ -1049,6 +1049,23 @@ void *xmmap(void *start, size_t length, return ret; } +static int format_object_header_literally(char *str, size_t size, + const char *type, size_t objsize) +{ + return xsnprintf(str, size, "%s %"PRIuMAX, type, (uintmax_t)objsize) + 1; +} + +int format_object_header(char *str, size_t size, enum object_type type, + size_t objsize) +{ + const char *name = type_name(type); + + if (!name) + BUG("could not get a type name for 'enum object_type' value %d", type); + + return format_object_header_literally(str, size, name, objsize); +} + /* * With an in-core object data in "map", rehash it to make sure the * object name actually matches "oid" to detect object corruption. @@ -1077,7 +1094,7 @@ int check_object_signature(struct repository *r, const struct object_id *oid, return -1; /* Generate the header */ - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(obj_type), (uintmax_t)size) + 1; + hdrlen = format_object_header(hdr, sizeof(hdr), obj_type, size); /* Sha1.. */ r->hash_algo->init_fn(&c); @@ -1777,7 +1794,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo, git_hash_ctx c; /* Generate the header */ - *hdrlen = xsnprintf(hdr, *hdrlen, "%s %"PRIuMAX , type, (uintmax_t)len)+1; + *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len); /* Sha1.. */ algo->init_fn(&c); @@ -2051,7 +2068,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime) buf = read_object(the_repository, oid, &type, &len); if (!buf) return error(_("cannot read object for %s"), oid_to_hex(oid)); - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1; + hdrlen = format_object_header(hdr, sizeof(hdr), type, len); ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0); free(buf); -- cgit v1.2.3 From c80d226a046170b1c8dd82ef72a27373ddd5880e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:26 +0100 Subject: object-file API: have write_object_file() take "enum object_type" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the write_object_file() function to take an "enum object_type" instead of a "const char *type". Its callers either passed {commit,tree,blob,tag}_type and can pass the corresponding OBJ_* type instead, or were hardcoding strings like "blob". This avoids the back & forth fragility where the callers of write_object_file() would have the enum type, and convert it themselves via type_name(). We do have to now do that conversion ourselves before calling write_object_file_prepare(), but those codepaths will be similarly adjusted in subsequent commits. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 3fcd46cf9e..59eb793e0a 100644 --- a/object-file.c +++ b/object-file.c @@ -2014,7 +2014,7 @@ static int freshen_packed_object(const struct object_id *oid) } int write_object_file_flags(const void *buf, unsigned long len, - const char *type, struct object_id *oid, + enum object_type type, struct object_id *oid, unsigned flags) { char hdr[MAX_HEADER_LEN]; @@ -2023,7 +2023,7 @@ int write_object_file_flags(const void *buf, unsigned long len, /* Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. */ - write_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr, + write_object_file_prepare(the_hash_algo, buf, len, type_name(type), oid, hdr, &hdrlen); if (freshen_packed_object(oid) || freshen_loose_object(oid)) return 0; @@ -2162,7 +2162,7 @@ static int index_mem(struct index_state *istate, } if (write_object) - ret = write_object_file(buf, size, type_name(type), oid); + ret = write_object_file(buf, size, type, oid); else hash_object_file(the_hash_algo, buf, size, type_name(type), oid); @@ -2189,7 +2189,7 @@ static int index_stream_convert_blob(struct index_state *istate, get_conv_flags(flags)); if (write_object) - ret = write_object_file(sbuf.buf, sbuf.len, type_name(OBJ_BLOB), + ret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB, oid); else hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, @@ -2313,7 +2313,7 @@ int index_path(struct index_state *istate, struct object_id *oid, if (!(flags & HASH_WRITE_OBJECT)) hash_object_file(the_hash_algo, sb.buf, sb.len, blob_type, oid); - else if (write_object_file(sb.buf, sb.len, blob_type, oid)) + else if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid)) rc = error(_("%s: failed to insert into database"), path); strbuf_release(&sb); break; -- cgit v1.2.3 From 73182b2d84e3348ab87ef5ecbe3315881381c29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:27 +0100 Subject: object API: correct "buf" v.s. "map" mismatch in *.c and *.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the name of the second argument to check_object_signature() to be "buf" in object-file.c, making it consistent with the prototype in cache.h This fixes an inconsistency that's been with us since 2ade9340262 (Add "check_sha1_signature()" helper function, 2005-04-08), and makes a subsequent commit's diff smaller, as we'll move these API docs to cache.h. While we're at it fix a small grammar error in the documentation, dropping an "an" before "in-core object-data". Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 59eb793e0a..271acf4dd1 100644 --- a/object-file.c +++ b/object-file.c @@ -1067,13 +1067,13 @@ int format_object_header(char *str, size_t size, enum object_type type, } /* - * With an in-core object data in "map", rehash it to make sure the + * With in-core object data in "buf", rehash it to make sure the * object name actually matches "oid" to detect object corruption. - * With "map" == NULL, try reading the object named with "oid" using + * With "buf" == NULL, try reading the object named with "oid" using * the streaming interface and rehash it to do the same. */ int check_object_signature(struct repository *r, const struct object_id *oid, - void *map, unsigned long size, const char *type, + void *buf, unsigned long size, const char *type, struct object_id *real_oidp) { struct object_id tmp; @@ -1084,8 +1084,8 @@ int check_object_signature(struct repository *r, const struct object_id *oid, char hdr[MAX_HEADER_LEN]; int hdrlen; - if (map) { - hash_object_file(r->hash_algo, map, size, type, real_oid); + if (buf) { + hash_object_file(r->hash_algo, buf, size, type, real_oid); return !oideq(oid, real_oid) ? -1 : 0; } -- cgit v1.2.3 From cdcaaec9a6028f53f9b44efb6dce9f15bb394b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:28 +0100 Subject: object API docs: move check_object_signature() docs to cache.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the API documentation for check_object_signature() to cache.h, where its prototype is declared. This is in preparation for adding a companion function. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 271acf4dd1..44e0b32d71 100644 --- a/object-file.c +++ b/object-file.c @@ -1066,12 +1066,6 @@ int format_object_header(char *str, size_t size, enum object_type type, return format_object_header_literally(str, size, name, objsize); } -/* - * With in-core object data in "buf", rehash it to make sure the - * object name actually matches "oid" to detect object corruption. - * With "buf" == NULL, try reading the object named with "oid" using - * the streaming interface and rehash it to do the same. - */ int check_object_signature(struct repository *r, const struct object_id *oid, void *buf, unsigned long size, const char *type, struct object_id *real_oidp) -- cgit v1.2.3 From ee213de22d15e801ba3712be0cb8ecbf7415fa1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:29 +0100 Subject: object API users + docs: check <0, not !0 with check_object_signature() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change those users of the object API that misused check_object_signature() by assuming it returned any non-zero when the OID didn't match the expected value to check <0 instead. In practice all of this code worked before, but it wasn't consistent with rest of the users of the API. Let's also clarify what the <0 return value means in API docs. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 44e0b32d71..d628f58c0d 100644 --- a/object-file.c +++ b/object-file.c @@ -2613,7 +2613,7 @@ int read_loose_object(const char *path, } if (check_object_signature(the_repository, expected_oid, *contents, *size, - oi->type_name->buf, real_oid)) + oi->type_name->buf, real_oid) < 0) goto out; } -- cgit v1.2.3 From 0f156dbb04b434d95ce5465e6b07d8869d55e8e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:30 +0100 Subject: object-file API: split up and simplify check_object_signature() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split up the check_object_signature() function into that non-streaming version (it accepts an already filled "buf"), and a new stream_object_signature() which will retrieve the object from storage, and hash it on-the-fly. All of the callers of check_object_signature() were effectively calling two different functions, if we go by cyclomatic complexity. I.e. they'd either take the early "if (map)" branch and return early, or not. This has been the case since the "if (map)" condition was added in 090ea12671b (parse_object: avoid putting whole blob in core, 2012-03-07). We can then further simplify the resulting check_object_signature() function since only one caller wanted to pass a non-NULL "buf" and a non-NULL "real_oidp". That "read_loose_object()" codepath used by "git fsck" can instead use hash_object_file() followed by oideq(). Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index d628f58c0d..f985492274 100644 --- a/object-file.c +++ b/object-file.c @@ -1067,22 +1067,25 @@ int format_object_header(char *str, size_t size, enum object_type type, } int check_object_signature(struct repository *r, const struct object_id *oid, - void *buf, unsigned long size, const char *type, - struct object_id *real_oidp) + void *buf, unsigned long size, const char *type) { - struct object_id tmp; - struct object_id *real_oid = real_oidp ? real_oidp : &tmp; + struct object_id real_oid; + + hash_object_file(r->hash_algo, buf, size, type, &real_oid); + + return !oideq(oid, &real_oid) ? -1 : 0; +} + +int stream_object_signature(struct repository *r, const struct object_id *oid) +{ + struct object_id real_oid; + unsigned long size; enum object_type obj_type; struct git_istream *st; git_hash_ctx c; char hdr[MAX_HEADER_LEN]; int hdrlen; - if (buf) { - hash_object_file(r->hash_algo, buf, size, type, real_oid); - return !oideq(oid, real_oid) ? -1 : 0; - } - st = open_istream(r, oid, &obj_type, &size, NULL); if (!st) return -1; @@ -1105,9 +1108,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid, break; r->hash_algo->update_fn(&c, buf, readlen); } - r->hash_algo->final_oid_fn(real_oid, &c); + r->hash_algo->final_oid_fn(&real_oid, &c); close_istream(st); - return !oideq(oid, real_oid) ? -1 : 0; + return !oideq(oid, &real_oid) ? -1 : 0; } int git_open_cloexec(const char *name, int flags) @@ -2611,9 +2614,10 @@ int read_loose_object(const char *path, git_inflate_end(&stream); goto out; } - if (check_object_signature(the_repository, expected_oid, - *contents, *size, - oi->type_name->buf, real_oid) < 0) + hash_object_file(the_repository->hash_algo, + *contents, *size, oi->type_name->buf, + real_oid); + if (!oideq(expected_oid, real_oid)) goto out; } -- cgit v1.2.3 From 0ff7b4f976b78ab38313356b3e0582e5fa9a3bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:31 +0100 Subject: object API: rename hash_object_file_literally() to write_*() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before 0c3db67cc81 (hash-object --literally: fix buffer overrun with extra-long object type, 2015-05-04) the hash-object code being changed here called write_sha1_file() to both hash and write a loose object. Before that we'd use hash_sha1_file() to if "-w" wasn't provided, and otherwise call write_sha1_file(). Now we'll always call the same function for both writing. Let's rename it from hash_*_literally() to write_*_literally(). Even though the write_*() might not actually write if HASH_WRITE_OBJECT isn't in "flags", having it be more similar to write_object_file_flags() than hash_object_file(), but carrying a name that would suggest that it's a variant of the latter is confusing. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index f985492274..9e5b849693 100644 --- a/object-file.c +++ b/object-file.c @@ -2027,9 +2027,9 @@ int write_object_file_flags(const void *buf, unsigned long len, return write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags); } -int hash_object_file_literally(const void *buf, unsigned long len, - const char *type, struct object_id *oid, - unsigned flags) +int write_object_file_literally(const void *buf, unsigned long len, + const char *type, struct object_id *oid, + unsigned flags) { char *header; int hdrlen, status = 0; -- cgit v1.2.3 From 44439c1c5827480f68b37c3cc38f257eaeb3ed2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:32 +0100 Subject: object-file API: have hash_object_file() take "enum object_type" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the hash_object_file() function to take an "enum object_type". Since a preceding commit all of its callers are passing either "{commit,tree,blob,tag}_type", or the result of a call to type_name(), the parse_object() caller that would pass NULL is now using stream_object_signature(). Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 9e5b849693..b1cb78c441 100644 --- a/object-file.c +++ b/object-file.c @@ -1067,7 +1067,8 @@ int format_object_header(char *str, size_t size, enum object_type type, } int check_object_signature(struct repository *r, const struct object_id *oid, - void *buf, unsigned long size, const char *type) + void *buf, unsigned long size, + enum object_type type) { struct object_id real_oid; @@ -1676,7 +1677,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type, { struct cached_object *co; - hash_object_file(the_hash_algo, buf, len, type_name(type), oid); + hash_object_file(the_hash_algo, buf, len, type, oid); if (has_object_file_with_flags(oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) || find_cached_object(oid)) return 0; @@ -1850,15 +1851,23 @@ static int write_buffer(int fd, const void *buf, size_t len) return 0; } -void hash_object_file(const struct git_hash_algo *algo, const void *buf, - unsigned long len, const char *type, - struct object_id *oid) +static void hash_object_file_literally(const struct git_hash_algo *algo, + const void *buf, unsigned long len, + const char *type, struct object_id *oid) { char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); + write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); } +void hash_object_file(const struct git_hash_algo *algo, const void *buf, + unsigned long len, enum object_type type, + struct object_id *oid) +{ + hash_object_file_literally(algo, buf, len, type_name(type), oid); +} + /* Finalize a file on disk, and close it. */ static void close_loose_object(int fd) { @@ -2161,9 +2170,7 @@ static int index_mem(struct index_state *istate, if (write_object) ret = write_object_file(buf, size, type, oid); else - hash_object_file(the_hash_algo, buf, size, type_name(type), - oid); - + hash_object_file(the_hash_algo, buf, size, type, oid); if (re_allocated) free(buf); return ret; @@ -2189,8 +2196,8 @@ static int index_stream_convert_blob(struct index_state *istate, ret = write_object_file(sbuf.buf, sbuf.len, OBJ_BLOB, oid); else - hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, - type_name(OBJ_BLOB), oid); + hash_object_file(the_hash_algo, sbuf.buf, sbuf.len, OBJ_BLOB, + oid); strbuf_release(&sbuf); return ret; } @@ -2309,7 +2316,7 @@ int index_path(struct index_state *istate, struct object_id *oid, return error_errno("readlink(\"%s\")", path); if (!(flags & HASH_WRITE_OBJECT)) hash_object_file(the_hash_algo, sb.buf, sb.len, - blob_type, oid); + OBJ_BLOB, oid); else if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid)) rc = error(_("%s: failed to insert into database"), path); strbuf_release(&sb); @@ -2614,9 +2621,9 @@ int read_loose_object(const char *path, git_inflate_end(&stream); goto out; } - hash_object_file(the_repository->hash_algo, - *contents, *size, oi->type_name->buf, - real_oid); + hash_object_file_literally(the_repository->hash_algo, + *contents, *size, + oi->type_name->buf, real_oid); if (!oideq(expected_oid, real_oid)) goto out; } -- cgit v1.2.3 From 2bbb28a3ee2f7252de02f5d0db4da79090b4f8fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:33 +0100 Subject: object-file.c: add a literal version of write_object_file_prepare() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split off a *_literally() variant of the write_object_file_prepare() function. To do this create a new "hash_object_body()" static helper. We now defer the type_name() call until the very last moment in format_object_header() for those callers that aren't "hash-object --literally". Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index b1cb78c441..c75c12dd0b 100644 --- a/object-file.c +++ b/object-file.c @@ -1784,21 +1784,40 @@ void *read_object_with_reference(struct repository *r, } } +static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c, + const void *buf, unsigned long len, + struct object_id *oid, + char *hdr, int *hdrlen) +{ + algo->init_fn(c); + algo->update_fn(c, hdr, *hdrlen); + algo->update_fn(c, buf, len); + algo->final_oid_fn(oid, c); +} + static void write_object_file_prepare(const struct git_hash_algo *algo, const void *buf, unsigned long len, - const char *type, struct object_id *oid, + enum object_type type, struct object_id *oid, char *hdr, int *hdrlen) { git_hash_ctx c; /* Generate the header */ - *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len); + *hdrlen = format_object_header(hdr, *hdrlen, type, len); /* Sha1.. */ - algo->init_fn(&c); - algo->update_fn(&c, hdr, *hdrlen); - algo->update_fn(&c, buf, len); - algo->final_oid_fn(oid, &c); + hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); +} + +static void write_object_file_prepare_literally(const struct git_hash_algo *algo, + const void *buf, unsigned long len, + const char *type, struct object_id *oid, + char *hdr, int *hdrlen) +{ + git_hash_ctx c; + + *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len); + hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); } /* @@ -1858,7 +1877,7 @@ static void hash_object_file_literally(const struct git_hash_algo *algo, char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); - write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); + write_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen); } void hash_object_file(const struct git_hash_algo *algo, const void *buf, @@ -2029,7 +2048,7 @@ int write_object_file_flags(const void *buf, unsigned long len, /* Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. */ - write_object_file_prepare(the_hash_algo, buf, len, type_name(type), oid, hdr, + write_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr, &hdrlen); if (freshen_packed_object(oid) || freshen_loose_object(oid)) return 0; @@ -2046,8 +2065,8 @@ int write_object_file_literally(const void *buf, unsigned long len, /* type string, SP, %lu of the length plus NUL must fit this */ hdrlen = strlen(type) + MAX_HEADER_LEN; header = xmalloc(hdrlen); - write_object_file_prepare(the_hash_algo, buf, len, type, oid, header, - &hdrlen); + write_object_file_prepare_literally(the_hash_algo, buf, len, type, + oid, header, &hdrlen); if (!(flags & HASH_WRITE_OBJECT)) goto cleanup; -- cgit v1.2.3 From 6aea6baeb3ece6c832dbdf1deed09f41aebf85c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Sat, 5 Feb 2022 00:48:34 +0100 Subject: object-file API: pass an enum to read_object_with_reference() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the read_object_with_reference() function to take an "enum object_type". It was not prepared to handle an arbitrary "const char *type", as it was itself calling type_from_string(). Let's change the only caller that passes in user data to use type_from_string(), and convert the rest to use e.g. "OBJ_TREE" instead of "tree_type". The "cat-file" caller is not on the codepath that handles"--allow-unknown", so the type_from_string() there is safe. Its use of type_from_string() doesn't functionally differ from that of the pre-image. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- object-file.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index c75c12dd0b..6cbdb836cb 100644 --- a/object-file.c +++ b/object-file.c @@ -1737,16 +1737,15 @@ void *read_object_file_extended(struct repository *r, void *read_object_with_reference(struct repository *r, const struct object_id *oid, - const char *required_type_name, + enum object_type required_type, unsigned long *size, struct object_id *actual_oid_return) { - enum object_type type, required_type; + enum object_type type; void *buffer; unsigned long isize; struct object_id actual_oid; - required_type = type_from_string(required_type_name); oidcpy(&actual_oid, oid); while (1) { int ref_length = -1; -- cgit v1.2.3