{"thread":{"id":"48349","subject":"[PATCH 00/41] object_id part 13","startedAt":"2018-04-23T23:40:07Z","lastAt":"2018-05-04T01:29:56Z","messageCount":76,"participants":["brian m. carlson","SZEDER Gábor","Simon Ruderich","Martin Ågren","Junio C Hamano","Duy Nguyen"],"isPatch":true,"patchVersion":1,"patchTotal":41},"messages":[{"id":"345525","messageId":"20180423233951.276447-1-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":null,"subject":"[PATCH 00/41] object_id part 13","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:10Z","receivedAt":"2018-04-23T23:40:07Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"This is the thirteenth series of patches to convert to struct object_id\nand the_hash_algo.\n\nThe series adds an oidread function to read object IDs from a buffer,\nremoves unused structure members (which therefore don't require\nconversion), converts various functions to struct object_id, and\nimproves usage of the_hash_algo.  It also makes empty_blob_oid and\nempty_tree_oid static, exposed only through the hash algorithm\nabstraction, and updates all the hard-coded instances of the empty blob\nand empty tree object IDs in scripts (excepting the testsuite).\n\nOutside of the testsuite, these are the only changes required to use a\ndifferent 160-bit hash algorithm.  To get the testsuite working will\nrequire two additional sets of patches, one of which I will send out\nsoon.\n\nI expect part 14 to be the last (or next to it) of the object_id series.\nI'm starting work on testing the codebase with a 256-bit hash[0], and I\nexpect that part 14 (or possibly a 15) will include the final pieces\nnecessary to make it pass the testsuite with a 256-bit hash (sans\nmulti-hash support).\n\n[0] I can synthesize blobs, trees, and commits, but things are currently\ntotally broken, which is, I suppose, to be expected.\n\nbrian m. carlson (41):\n  cache: add a function to read an object ID from a buffer\n  server-info: remove unused members from struct pack_info\n  Remove unused member in struct object_context\n  packfile: remove unused member from struct pack_entry\n  packfile: convert has_sha1_pack to object_id\n  sha1_file: convert freshen functions to object_id\n  packfile: convert find_pack_entry to object_id\n  packfile: abstract away hash constant values\n  pack-objects: abstract away hash algorithm\n  pack-redundant: abstract away hash algorithm\n  tree-walk: avoid hard-coded 20 constant\n  tree-walk: convert get_tree_entry_follow_symlinks to object_id\n  fsck: convert static functions to struct object_id\n  submodule-config: convert structures to object_id\n  split-index: convert struct split_index to object_id\n  Update struct index_state to use struct object_id\n  pack-redundant: convert linked lists to use struct object_id\n  index-pack: abstract away hash function constant\n  commit: convert uses of get_sha1_hex to get_oid_hex\n  dir: convert struct untracked_cache_dir to object_id\n  http: eliminate hard-coded constants\n  revision: replace use of hard-coded constants\n  upload-pack: replace use of several hard-coded constants\n  diff: specify abbreviation size in terms of the_hash_algo\n  builtin/receive-pack: avoid hard-coded constants for push certs\n  builtin/am: convert uses of EMPTY_TREE_SHA1_BIN to the_hash_algo\n  builtin/merge: switch tree functions to use object_id\n  merge: convert empty tree constant to the_hash_algo\n  sequencer: convert one use of EMPTY_TREE_SHA1_HEX\n  submodule: convert several uses of EMPTY_TREE_SHA1_HEX\n  wt-status: convert two uses of EMPTY_TREE_SHA1_HEX\n  builtin/receive-pack: convert one use of EMPTY_TREE_SHA1_HEX\n  builtin/reset: convert use of EMPTY_TREE_SHA1_BIN\n  sha1_file: convert cached object code to struct object_id\n  cache-tree: use is_empty_tree_oid\n  sequencer: use the_hash_algo for empty tree object ID\n  dir: use the_hash_algo for empty blob object ID\n  sha1_file: only expose empty object constants through git_hash_algo\n  Update shell scripts to compute empty tree object ID\n  add--interactive: compute the empty tree value\n  merge-one-file: compute empty blob object ID\n\n builtin/am.c                         |  8 +--\n builtin/count-objects.c              |  2 +-\n builtin/fsck.c                       |  2 +-\n builtin/index-pack.c                 |  3 +-\n builtin/merge.c                      | 14 ++---\n builtin/pack-objects.c               | 32 +++++------\n builtin/pack-redundant.c             | 62 ++++++++++++----------\n builtin/prune-packed.c               |  2 +-\n builtin/receive-pack.c               |  8 +--\n builtin/reset.c                      |  2 +-\n builtin/rev-parse.c                  |  4 +-\n cache-tree.c                         |  4 +-\n cache.h                              | 25 +++------\n commit.c                             |  4 +-\n diff.c                               | 20 ++++---\n dir.c                                | 25 ++++-----\n dir.h                                |  5 +-\n fsck.c                               | 20 +++----\n git-add--interactive.perl            | 11 +++-\n git-filter-branch.sh                 |  4 +-\n git-merge-one-file.sh                |  2 +-\n git-rebase--interactive.sh           |  4 +-\n http.c                               | 11 ++--\n merge.c                              |  5 +-\n packfile.c                           | 79 +++++++++++++++-------------\n packfile.h                           |  4 +-\n read-cache.c                         | 34 ++++++------\n resolve-undo.c                       |  2 +-\n revision.c                           |  7 +--\n sequencer.c                          |  5 +-\n server-info.c                        |  3 --\n sha1_file.c                          | 69 +++++++++++++-----------\n sha1_name.c                          |  5 +-\n split-index.c                        | 10 ++--\n split-index.h                        |  4 +-\n submodule-config.c                   | 66 +++++++++++------------\n submodule-config.h                   |  7 +--\n submodule.c                          |  6 +--\n t/helper/test-dump-split-index.c     |  4 +-\n t/helper/test-dump-untracked-cache.c |  2 +-\n templates/hooks--pre-commit.sample   |  2 +-\n tree-walk.c                          | 18 +++----\n tree-walk.h                          |  2 +-\n unpack-trees.c                       |  2 +-\n upload-pack.c                        | 18 +++----\n wt-status.c                          |  6 ++-\n 46 files changed, 333 insertions(+), 301 deletions(-)\n\n"},{"id":"345526","messageId":"20180423233951.276447-2-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 01/41] cache: add a function to read an object ID from a buffer","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:11Z","receivedAt":"2018-04-23T23:40:10Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"In various places throughout the codebase, we need to read data into a\nstruct object_id from a pack or other unsigned char buffer.  Add an\ninline function that does this based on the current hash algorithm in\nuse, and use it in several places.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n cache-tree.c   | 2 +-\n cache.h        | 5 +++++\n resolve-undo.c | 2 +-\n 3 files changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 6a555f4d43..8c7e1258a4 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -523,7 +523,7 @@ static struct cache_tree *read_one(const char **buffer, unsigned long *size_p)\n \tif (0 <= it->entry_count) {\n \t\tif (size < rawsz)\n \t\t\tgoto free_return;\n-\t\tmemcpy(it->oid.hash, (const unsigned char*)buf, rawsz);\n+\t\toidread(&it->oid, (const unsigned char *)buf);\n \t\tbuf += rawsz;\n \t\tsize -= rawsz;\n \t}\ndiff --git a/cache.h b/cache.h\nindex bbaf5c349a..4bca177cf3 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1008,6 +1008,11 @@ static inline void oidclr(struct object_id *oid)\n \tmemset(oid->hash, 0, GIT_MAX_RAWSZ);\n }\n \n+static inline void oidread(struct object_id *oid, const unsigned char *hash)\n+{\n+\tmemcpy(oid->hash, hash, the_hash_algo->rawsz);\n+}\n+\n \n #define EMPTY_TREE_SHA1_HEX \\\n \t\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"\ndiff --git a/resolve-undo.c b/resolve-undo.c\nindex aed95b4b35..fc5b3b83d9 100644\n--- a/resolve-undo.c\n+++ b/resolve-undo.c\n@@ -90,7 +90,7 @@ struct string_list *resolve_undo_read(const char *data, unsigned long size)\n \t\t\t\tcontinue;\n \t\t\tif (size < rawsz)\n \t\t\t\tgoto error;\n-\t\t\tmemcpy(ui->oid[i].hash, (const unsigned char *)data, rawsz);\n+\t\t\toidread(&ui->oid[i], (const unsigned char *)data);\n \t\t\tsize -= rawsz;\n \t\t\tdata += rawsz;\n \t\t}\n"},{"id":"345527","messageId":"20180423233951.276447-3-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 02/41] server-info: remove unused members from struct pack_info","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:12Z","receivedAt":"2018-04-23T23:40:13Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"The head member of struct pack_info is completely unused and the\nnr_heads member is used only in one place, which is an assignment.\nSince these structure members are not useful, remove them.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n server-info.c | 3 ---\n 1 file changed, 3 deletions(-)\n\ndiff --git a/server-info.c b/server-info.c\nindex 83460ec0d6..828ec5e538 100644\n--- a/server-info.c\n+++ b/server-info.c\n@@ -92,8 +92,6 @@ static struct pack_info {\n \tint old_num;\n \tint new_num;\n \tint nr_alloc;\n-\tint nr_heads;\n-\tunsigned char (*head)[20];\n } **info;\n static int num_pack;\n static const char *objdir;\n@@ -228,7 +226,6 @@ static void init_pack_info(const char *infofile, int force)\n \tfor (i = 0; i < num_pack; i++) {\n \t\tif (stale) {\n \t\t\tinfo[i]->old_num = -1;\n-\t\t\tinfo[i]->nr_heads = 0;\n \t\t}\n \t}\n \n"},{"id":"345528","messageId":"20180423233951.276447-4-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 03/41] Remove unused member in struct object_context","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:13Z","receivedAt":"2018-04-23T23:40:16Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"The tree member of struct object_context is unused except in one place\nwhere we write to it.  Since there are no users of this member, remove\nit.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n cache.h     | 1 -\n sha1_name.c | 1 -\n 2 files changed, 2 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 4bca177cf3..11a989319d 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1306,7 +1306,6 @@ static inline int hex2chr(const char *s)\n #define FALLBACK_DEFAULT_ABBREV 7\n \n struct object_context {\n-\tunsigned char tree[20];\n \tunsigned mode;\n \t/*\n \t * symlink_path is only used by get_tree_entry_follow_symlinks,\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 5b93bf8da3..7043652a24 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -1698,7 +1698,6 @@ static int get_oid_with_context_1(const char *name,\n \t\t\t\t\t\t\t\t   name, len);\n \t\t\t\t}\n \t\t\t}\n-\t\t\thashcpy(oc->tree, tree_oid.hash);\n \t\t\tif (flags & GET_OID_RECORD_PATH)\n \t\t\t\toc->path = xstrdup(filename);\n \n"},{"id":"345529","messageId":"20180423233951.276447-5-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 04/41] packfile: remove unused member from struct pack_entry","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:14Z","receivedAt":"2018-04-23T23:40:18Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"The sha1 member in struct pack_entry is unused except for one instance\nin which we store a value in it.  Since nobody ever reads this value,\ndon't bother to compute it and remove the member from struct pack_entry.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n cache.h    | 1 -\n packfile.c | 1 -\n 2 files changed, 2 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 11a989319d..dd1a9c6094 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1572,7 +1572,6 @@ struct pack_window {\n \n struct pack_entry {\n \toff_t offset;\n-\tunsigned char sha1[20];\n \tstruct packed_git *p;\n };\n \ndiff --git a/packfile.c b/packfile.c\nindex 0bc67d0e00..5c219d0229 100644\n--- a/packfile.c\n+++ b/packfile.c\n@@ -1833,7 +1833,6 @@ static int fill_pack_entry(const unsigned char *sha1,\n \t\treturn 0;\n \te->offset = offset;\n \te->p = p;\n-\thashcpy(e->sha1, sha1);\n \treturn 1;\n }\n \n"},{"id":"345530","messageId":"20180423233951.276447-7-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 06/41] sha1_file: convert freshen functions to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:16Z","receivedAt":"2018-04-23T23:40:20Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert the various functions for freshening objects and\nhas_loose_object_nonlocal to use struct object_id.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/pack-objects.c |  2 +-\n cache.h                |  2 +-\n sha1_file.c            | 36 ++++++++++++++++++------------------\n 3 files changed, 20 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 4bdae5a1d8..907e112331 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -1012,7 +1012,7 @@ static int want_object_in_pack(const struct object_id *oid,\n \tint want;\n \tstruct list_head *pos;\n \n-\tif (!exclude && local && has_loose_object_nonlocal(oid->hash))\n+\tif (!exclude && local && has_loose_object_nonlocal(oid))\n \t\treturn 0;\n \n \t/*\ndiff --git a/cache.h b/cache.h\nindex dd1a9c6094..e03a0d4d23 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1275,7 +1275,7 @@ extern int has_object_file_with_flags(const struct object_id *oid, int flags);\n  * with the specified name.  This function does not respect replace\n  * references.\n  */\n-extern int has_loose_object_nonlocal(const unsigned char *sha1);\n+extern int has_loose_object_nonlocal(const struct object_id *oid);\n \n extern void assert_oid_type(const struct object_id *oid, enum object_type expect);\n \ndiff --git a/sha1_file.c b/sha1_file.c\nindex 77ccaab928..1617e25495 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -709,42 +709,42 @@ int check_and_freshen_file(const char *fn, int freshen)\n \treturn 1;\n }\n \n-static int check_and_freshen_local(const unsigned char *sha1, int freshen)\n+static int check_and_freshen_local(const struct object_id *oid, int freshen)\n {\n \tstatic struct strbuf buf = STRBUF_INIT;\n \n \tstrbuf_reset(&buf);\n-\tsha1_file_name(the_repository, &buf, sha1);\n+\tsha1_file_name(the_repository, &buf, oid->hash);\n \n \treturn check_and_freshen_file(buf.buf, freshen);\n }\n \n-static int check_and_freshen_nonlocal(const unsigned char *sha1, int freshen)\n+static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen)\n {\n \tstruct alternate_object_database *alt;\n \tprepare_alt_odb(the_repository);\n \tfor (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) {\n-\t\tconst char *path = alt_sha1_path(alt, sha1);\n+\t\tconst char *path = alt_sha1_path(alt, oid->hash);\n \t\tif (check_and_freshen_file(path, freshen))\n \t\t\treturn 1;\n \t}\n \treturn 0;\n }\n \n-static int check_and_freshen(const unsigned char *sha1, int freshen)\n+static int check_and_freshen(const struct object_id *oid, int freshen)\n {\n-\treturn check_and_freshen_local(sha1, freshen) ||\n-\t       check_and_freshen_nonlocal(sha1, freshen);\n+\treturn check_and_freshen_local(oid, freshen) ||\n+\t       check_and_freshen_nonlocal(oid, freshen);\n }\n \n-int has_loose_object_nonlocal(const unsigned char *sha1)\n+int has_loose_object_nonlocal(const struct object_id *oid)\n {\n-\treturn check_and_freshen_nonlocal(sha1, 0);\n+\treturn check_and_freshen_nonlocal(oid, 0);\n }\n \n-static int has_loose_object(const unsigned char *sha1)\n+static int has_loose_object(const struct object_id *oid)\n {\n-\treturn check_and_freshen(sha1, 0);\n+\treturn check_and_freshen(oid, 0);\n }\n \n static void mmap_limit_check(size_t length)\n@@ -1661,15 +1661,15 @@ static int write_loose_object(const struct object_id *oid, char *hdr,\n \treturn finalize_object_file(tmp_file.buf, filename.buf);\n }\n \n-static int freshen_loose_object(const unsigned char *sha1)\n+static int freshen_loose_object(const struct object_id *oid)\n {\n-\treturn check_and_freshen(sha1, 1);\n+\treturn check_and_freshen(oid, 1);\n }\n \n-static int freshen_packed_object(const unsigned char *sha1)\n+static int freshen_packed_object(const struct object_id *oid)\n {\n \tstruct pack_entry e;\n-\tif (!find_pack_entry(the_repository, sha1, &e))\n+\tif (!find_pack_entry(the_repository, oid->hash, &e))\n \t\treturn 0;\n \tif (e.p->freshened)\n \t\treturn 1;\n@@ -1689,7 +1689,7 @@ int write_object_file(const void *buf, unsigned long len, const char *type,\n \t * it out into .git/objects/??/?{38} file.\n \t */\n \twrite_object_file_prepare(buf, len, type, oid, hdr, &hdrlen);\n-\tif (freshen_packed_object(oid->hash) || freshen_loose_object(oid->hash))\n+\tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n \t\treturn 0;\n \treturn write_loose_object(oid, hdr, hdrlen, buf, len, 0);\n }\n@@ -1708,7 +1708,7 @@ int hash_object_file_literally(const void *buf, unsigned long len,\n \n \tif (!(flags & HASH_WRITE_OBJECT))\n \t\tgoto cleanup;\n-\tif (freshen_packed_object(oid->hash) || freshen_loose_object(oid->hash))\n+\tif (freshen_packed_object(oid) || freshen_loose_object(oid))\n \t\tgoto cleanup;\n \tstatus = write_loose_object(oid, header, hdrlen, buf, len, 0);\n \n@@ -1726,7 +1726,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)\n \tint hdrlen;\n \tint ret;\n \n-\tif (has_loose_object(oid->hash))\n+\tif (has_loose_object(oid))\n \t\treturn 0;\n \tbuf = read_object(oid->hash, &type, &len);\n \tif (!buf)\n"},{"id":"345531","messageId":"20180423233951.276447-8-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 07/41] packfile: convert find_pack_entry to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:17Z","receivedAt":"2018-04-23T23:40:22Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert find_pack_entry and the static function fill_pack_entry to take\npointers to struct object_id.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n packfile.c  | 12 ++++++------\n packfile.h  |  2 +-\n sha1_file.c |  6 +++---\n 3 files changed, 10 insertions(+), 10 deletions(-)\n\ndiff --git a/packfile.c b/packfile.c\nindex e65f943664..84acd405e0 100644\n--- a/packfile.c\n+++ b/packfile.c\n@@ -1805,7 +1805,7 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,\n \n }\n \n-static int fill_pack_entry(const unsigned char *sha1,\n+static int fill_pack_entry(const struct object_id *oid,\n \t\t\t   struct pack_entry *e,\n \t\t\t   struct packed_git *p)\n {\n@@ -1814,11 +1814,11 @@ static int fill_pack_entry(const unsigned char *sha1,\n \tif (p->num_bad_objects) {\n \t\tunsigned i;\n \t\tfor (i = 0; i < p->num_bad_objects; i++)\n-\t\t\tif (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))\n+\t\t\tif (!hashcmp(oid->hash, p->bad_object_sha1 + 20 * i))\n \t\t\t\treturn 0;\n \t}\n \n-\toffset = find_pack_entry_one(sha1, p);\n+\toffset = find_pack_entry_one(oid->hash, p);\n \tif (!offset)\n \t\treturn 0;\n \n@@ -1836,7 +1836,7 @@ static int fill_pack_entry(const unsigned char *sha1,\n \treturn 1;\n }\n \n-int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack_entry *e)\n+int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e)\n {\n \tstruct list_head *pos;\n \n@@ -1846,7 +1846,7 @@ int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack\n \n \tlist_for_each(pos, &r->objects->packed_git_mru) {\n \t\tstruct packed_git *p = list_entry(pos, struct packed_git, mru);\n-\t\tif (fill_pack_entry(sha1, e, p)) {\n+\t\tif (fill_pack_entry(oid, e, p)) {\n \t\t\tlist_move(&p->mru, &r->objects->packed_git_mru);\n \t\t\treturn 1;\n \t\t}\n@@ -1857,7 +1857,7 @@ int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack\n int has_object_pack(const struct object_id *oid)\n {\n \tstruct pack_entry e;\n-\treturn find_pack_entry(the_repository, oid->hash, &e);\n+\treturn find_pack_entry(the_repository, oid, &e);\n }\n \n int has_pack_index(const unsigned char *sha1)\ndiff --git a/packfile.h b/packfile.h\nindex 14ca34bcbd..782029ed07 100644\n--- a/packfile.h\n+++ b/packfile.h\n@@ -134,7 +134,7 @@ extern const struct packed_git *has_packed_and_bad(const unsigned char *sha1);\n  * Iff a pack file in the given repository contains the object named by sha1,\n  * return true and store its location to e.\n  */\n-extern int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack_entry *e);\n+extern int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e);\n \n extern int has_object_pack(const struct object_id *oid);\n \ndiff --git a/sha1_file.c b/sha1_file.c\nindex 1617e25495..4328c61285 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1268,7 +1268,7 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi\n \t}\n \n \twhile (1) {\n-\t\tif (find_pack_entry(the_repository, real->hash, &e))\n+\t\tif (find_pack_entry(the_repository, real, &e))\n \t\t\tbreak;\n \n \t\tif (flags & OBJECT_INFO_IGNORE_LOOSE)\n@@ -1281,7 +1281,7 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi\n \t\t/* Not a loose object; someone else may have just packed it. */\n \t\tif (!(flags & OBJECT_INFO_QUICK)) {\n \t\t\treprepare_packed_git(the_repository);\n-\t\t\tif (find_pack_entry(the_repository, real->hash, &e))\n+\t\t\tif (find_pack_entry(the_repository, real, &e))\n \t\t\t\tbreak;\n \t\t}\n \n@@ -1669,7 +1669,7 @@ static int freshen_loose_object(const struct object_id *oid)\n static int freshen_packed_object(const struct object_id *oid)\n {\n \tstruct pack_entry e;\n-\tif (!find_pack_entry(the_repository, oid->hash, &e))\n+\tif (!find_pack_entry(the_repository, oid, &e))\n \t\treturn 0;\n \tif (e.p->freshened)\n \t\treturn 1;\n"},{"id":"345532","messageId":"20180423233951.276447-10-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 09/41] pack-objects: abstract away hash algorithm","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:19Z","receivedAt":"2018-04-23T23:40:27Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Instead of using hard-coded instances of the constant 20, use\nthe_hash_algo to look up the correct constant.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/pack-objects.c | 30 ++++++++++++++++--------------\n 1 file changed, 16 insertions(+), 14 deletions(-)\n\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 907e112331..f014523613 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -264,6 +264,7 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent\n \tenum object_type type;\n \tvoid *buf;\n \tstruct git_istream *st = NULL;\n+\tconst unsigned hashsz = the_hash_algo->rawsz;\n \n \tif (!usable_delta) {\n \t\tif (entry->type == OBJ_BLOB &&\n@@ -320,7 +321,7 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent\n \t\tdheader[pos] = ofs & 127;\n \t\twhile (ofs >>= 7)\n \t\t\tdheader[--pos] = 128 | (--ofs & 127);\n-\t\tif (limit && hdrlen + sizeof(dheader) - pos + datalen + 20 >= limit) {\n+\t\tif (limit && hdrlen + sizeof(dheader) - pos + datalen + hashsz >= limit) {\n \t\t\tif (st)\n \t\t\t\tclose_istream(st);\n \t\t\tfree(buf);\n@@ -332,19 +333,19 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent\n \t} else if (type == OBJ_REF_DELTA) {\n \t\t/*\n \t\t * Deltas with a base reference contain\n-\t\t * an additional 20 bytes for the base sha1.\n+\t\t * additional bytes for the base object ID.\n \t\t */\n-\t\tif (limit && hdrlen + 20 + datalen + 20 >= limit) {\n+\t\tif (limit && hdrlen + hashsz + datalen + hashsz >= limit) {\n \t\t\tif (st)\n \t\t\t\tclose_istream(st);\n \t\t\tfree(buf);\n \t\t\treturn 0;\n \t\t}\n \t\thashwrite(f, header, hdrlen);\n-\t\thashwrite(f, entry->delta->idx.oid.hash, 20);\n-\t\thdrlen += 20;\n+\t\thashwrite(f, entry->delta->idx.oid.hash, hashsz);\n+\t\thdrlen += hashsz;\n \t} else {\n-\t\tif (limit && hdrlen + datalen + 20 >= limit) {\n+\t\tif (limit && hdrlen + datalen + hashsz >= limit) {\n \t\t\tif (st)\n \t\t\t\tclose_istream(st);\n \t\t\tfree(buf);\n@@ -376,6 +377,7 @@ static off_t write_reuse_object(struct hashfile *f, struct object_entry *entry,\n \tunsigned char header[MAX_PACK_OBJECT_HEADER],\n \t\t      dheader[MAX_PACK_OBJECT_HEADER];\n \tunsigned hdrlen;\n+\tconst unsigned hashsz = the_hash_algo->rawsz;\n \n \tif (entry->delta)\n \t\ttype = (allow_ofs_delta && entry->delta->idx.offset) ?\n@@ -411,7 +413,7 @@ static off_t write_reuse_object(struct hashfile *f, struct object_entry *entry,\n \t\tdheader[pos] = ofs & 127;\n \t\twhile (ofs >>= 7)\n \t\t\tdheader[--pos] = 128 | (--ofs & 127);\n-\t\tif (limit && hdrlen + sizeof(dheader) - pos + datalen + 20 >= limit) {\n+\t\tif (limit && hdrlen + sizeof(dheader) - pos + datalen + hashsz >= limit) {\n \t\t\tunuse_pack(&w_curs);\n \t\t\treturn 0;\n \t\t}\n@@ -420,16 +422,16 @@ static off_t write_reuse_object(struct hashfile *f, struct object_entry *entry,\n \t\thdrlen += sizeof(dheader) - pos;\n \t\treused_delta++;\n \t} else if (type == OBJ_REF_DELTA) {\n-\t\tif (limit && hdrlen + 20 + datalen + 20 >= limit) {\n+\t\tif (limit && hdrlen + hashsz + datalen + hashsz >= limit) {\n \t\t\tunuse_pack(&w_curs);\n \t\t\treturn 0;\n \t\t}\n \t\thashwrite(f, header, hdrlen);\n-\t\thashwrite(f, entry->delta->idx.oid.hash, 20);\n-\t\thdrlen += 20;\n+\t\thashwrite(f, entry->delta->idx.oid.hash, hashsz);\n+\t\thdrlen += hashsz;\n \t\treused_delta++;\n \t} else {\n-\t\tif (limit && hdrlen + datalen + 20 >= limit) {\n+\t\tif (limit && hdrlen + datalen + hashsz >= limit) {\n \t\t\tunuse_pack(&w_curs);\n \t\t\treturn 0;\n \t\t}\n@@ -752,7 +754,7 @@ static off_t write_reused_pack(struct hashfile *f)\n \t\tdie_errno(\"unable to seek in reused packfile\");\n \n \tif (reuse_packfile_offset < 0)\n-\t\treuse_packfile_offset = reuse_packfile->pack_size - 20;\n+\t\treuse_packfile_offset = reuse_packfile->pack_size - the_hash_algo->rawsz;\n \n \ttotal = to_write = reuse_packfile_offset - sizeof(struct pack_header);\n \n@@ -1438,7 +1440,7 @@ static void check_object(struct object_entry *entry)\n \t\t\tif (reuse_delta && !entry->preferred_base)\n \t\t\t\tbase_ref = use_pack(p, &w_curs,\n \t\t\t\t\t\tentry->in_pack_offset + used, NULL);\n-\t\t\tentry->in_pack_header_size = used + 20;\n+\t\t\tentry->in_pack_header_size = used + the_hash_algo->rawsz;\n \t\t\tbreak;\n \t\tcase OBJ_OFS_DELTA:\n \t\t\tbuf = use_pack(p, &w_curs,\n@@ -1850,7 +1852,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,\n \t/* Now some size filtering heuristics. */\n \ttrg_size = trg_entry->size;\n \tif (!trg_entry->delta) {\n-\t\tmax_size = trg_size/2 - 20;\n+\t\tmax_size = trg_size/2 - the_hash_algo->rawsz;\n \t\tref_depth = 1;\n \t} else {\n \t\tmax_size = trg_entry->delta_size;\n"},{"id":"345533","messageId":"20180423233951.276447-18-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 17/41] pack-redundant: convert linked lists to use struct object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:27Z","receivedAt":"2018-04-23T23:40:31Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert struct llist_item and the rest of the linked list code to use\nstruct object_id.  Add a use of GIT_MAX_HEXSZ to avoid a dependency on a\nhard-coded constant.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/pack-redundant.c | 50 +++++++++++++++++++++-------------------\n 1 file changed, 26 insertions(+), 24 deletions(-)\n\ndiff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c\nindex 0fe1ff3cb7..0494dceff7 100644\n--- a/builtin/pack-redundant.c\n+++ b/builtin/pack-redundant.c\n@@ -20,7 +20,7 @@ static int load_all_packs, verbose, alt_odb;\n \n struct llist_item {\n \tstruct llist_item *next;\n-\tconst unsigned char *sha1;\n+\tconst struct object_id *oid;\n };\n static struct llist {\n \tstruct llist_item *front;\n@@ -90,14 +90,14 @@ static struct llist * llist_copy(struct llist *list)\n \t\treturn ret;\n \n \tnew_item = ret->front = llist_item_get();\n-\tnew_item->sha1 = list->front->sha1;\n+\tnew_item->oid = list->front->oid;\n \n \told_item = list->front->next;\n \twhile (old_item) {\n \t\tprev = new_item;\n \t\tnew_item = llist_item_get();\n \t\tprev->next = new_item;\n-\t\tnew_item->sha1 = old_item->sha1;\n+\t\tnew_item->oid = old_item->oid;\n \t\told_item = old_item->next;\n \t}\n \tnew_item->next = NULL;\n@@ -108,10 +108,10 @@ static struct llist * llist_copy(struct llist *list)\n \n static inline struct llist_item *llist_insert(struct llist *list,\n \t\t\t\t\t      struct llist_item *after,\n-\t\t\t\t\t       const unsigned char *sha1)\n+\t\t\t\t\t      const struct object_id *oid)\n {\n \tstruct llist_item *new_item = llist_item_get();\n-\tnew_item->sha1 = sha1;\n+\tnew_item->oid = oid;\n \tnew_item->next = NULL;\n \n \tif (after != NULL) {\n@@ -131,21 +131,21 @@ static inline struct llist_item *llist_insert(struct llist *list,\n }\n \n static inline struct llist_item *llist_insert_back(struct llist *list,\n-\t\t\t\t\t\t   const unsigned char *sha1)\n+\t\t\t\t\t\t   const struct object_id *oid)\n {\n-\treturn llist_insert(list, list->back, sha1);\n+\treturn llist_insert(list, list->back, oid);\n }\n \n static inline struct llist_item *llist_insert_sorted_unique(struct llist *list,\n-\t\t\tconst unsigned char *sha1, struct llist_item *hint)\n+\t\t\tconst struct object_id *oid, struct llist_item *hint)\n {\n \tstruct llist_item *prev = NULL, *l;\n \n \tl = (hint == NULL) ? list->front : hint;\n \twhile (l) {\n-\t\tint cmp = hashcmp(l->sha1, sha1);\n+\t\tint cmp = oidcmp(l->oid, oid);\n \t\tif (cmp > 0) { /* we insert before this entry */\n-\t\t\treturn llist_insert(list, prev, sha1);\n+\t\t\treturn llist_insert(list, prev, oid);\n \t\t}\n \t\tif (!cmp) { /* already exists */\n \t\t\treturn l;\n@@ -154,11 +154,11 @@ static inline struct llist_item *llist_insert_sorted_unique(struct llist *list,\n \t\tl = l->next;\n \t}\n \t/* insert at the end */\n-\treturn llist_insert_back(list, sha1);\n+\treturn llist_insert_back(list, oid);\n }\n \n /* returns a pointer to an item in front of sha1 */\n-static inline struct llist_item * llist_sorted_remove(struct llist *list, const unsigned char *sha1, struct llist_item *hint)\n+static inline struct llist_item * llist_sorted_remove(struct llist *list, const struct object_id *oid, struct llist_item *hint)\n {\n \tstruct llist_item *prev, *l;\n \n@@ -166,7 +166,7 @@ static inline struct llist_item * llist_sorted_remove(struct llist *list, const\n \tl = (hint == NULL) ? list->front : hint;\n \tprev = NULL;\n \twhile (l) {\n-\t\tint cmp = hashcmp(l->sha1, sha1);\n+\t\tint cmp = oidcmp(l->oid, oid);\n \t\tif (cmp > 0) /* not in list, since sorted */\n \t\t\treturn prev;\n \t\tif (!cmp) { /* found */\n@@ -201,7 +201,7 @@ static void llist_sorted_difference_inplace(struct llist *A,\n \tb = B->front;\n \n \twhile (b) {\n-\t\thint = llist_sorted_remove(A, b->sha1, hint);\n+\t\thint = llist_sorted_remove(A, b->oid, hint);\n \t\tb = b->next;\n \t}\n }\n@@ -268,9 +268,11 @@ static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)\n \t\t/* cmp ~ p1 - p2 */\n \t\tif (cmp == 0) {\n \t\t\tp1_hint = llist_sorted_remove(p1->unique_objects,\n-\t\t\t\t\tp1_base + p1_off, p1_hint);\n+\t\t\t\t\t(const struct object_id *)(p1_base + p1_off),\n+\t\t\t\t\tp1_hint);\n \t\t\tp2_hint = llist_sorted_remove(p2->unique_objects,\n-\t\t\t\t\tp1_base + p1_off, p2_hint);\n+\t\t\t\t\t(const struct object_id *)(p1_base + p1_off),\n+\t\t\t\t\tp2_hint);\n \t\t\tp1_off += p1_step;\n \t\t\tp2_off += p2_step;\n \t\t\tcontinue;\n@@ -501,7 +503,7 @@ static void load_all_objects(void)\n \t\tl = pl->all_objects->front;\n \t\twhile (l) {\n \t\t\thint = llist_insert_sorted_unique(all_objects,\n-\t\t\t\t\t\t\t  l->sha1, hint);\n+\t\t\t\t\t\t\t  l->oid, hint);\n \t\t\tl = l->next;\n \t\t}\n \t\tpl = pl->next;\n@@ -562,7 +564,7 @@ static struct pack_list * add_pack(struct packed_git *p)\n \tbase += 256 * 4 + ((p->index_version < 2) ? 4 : 8);\n \tstep = the_hash_algo->rawsz + ((p->index_version < 2) ? 4 : 0);\n \twhile (off < p->num_objects * step) {\n-\t\tllist_insert_back(l.all_objects, base + off);\n+\t\tllist_insert_back(l.all_objects, (const struct object_id *)(base + off));\n \t\toff += step;\n \t}\n \t/* this list will be pruned in cmp_two_packs later */\n@@ -603,8 +605,8 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix)\n \tint i;\n \tstruct pack_list *min, *red, *pl;\n \tstruct llist *ignore;\n-\tunsigned char *sha1;\n-\tchar buf[42]; /* 40 byte sha1 + \\n + \\0 */\n+\tstruct object_id *oid;\n+\tchar buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \\n + \\0 */\n \n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage(pack_redundant_usage);\n@@ -652,10 +654,10 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix)\n \tllist_init(&ignore);\n \tif (!isatty(0)) {\n \t\twhile (fgets(buf, sizeof(buf), stdin)) {\n-\t\t\tsha1 = xmalloc(20);\n-\t\t\tif (get_sha1_hex(buf, sha1))\n-\t\t\t\tdie(\"Bad sha1 on stdin: %s\", buf);\n-\t\t\tllist_insert_sorted_unique(ignore, sha1, NULL);\n+\t\t\toid = xmalloc(sizeof(*oid));\n+\t\t\tif (get_oid_hex(buf, oid))\n+\t\t\t\tdie(\"Bad object ID on stdin: %s\", buf);\n+\t\t\tllist_insert_sorted_unique(ignore, oid, NULL);\n \t\t}\n \t}\n \tllist_sorted_difference_inplace(all_objects, ignore);\n"},{"id":"345534","messageId":"20180423233951.276447-17-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 16/41] Update struct index_state to use struct object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:26Z","receivedAt":"2018-04-23T23:40:34Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Adjust struct index_state to use struct object_id instead of unsigned\nchar [20].\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n cache.h                          |  2 +-\n read-cache.c                     | 16 ++++++++--------\n t/helper/test-dump-split-index.c |  2 +-\n unpack-trees.c                   |  2 +-\n 4 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex e03a0d4d23..9ad1dd2ddc 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -324,7 +324,7 @@ struct index_state {\n \t\t drop_cache_tree : 1;\n \tstruct hashmap name_hash;\n \tstruct hashmap dir_hash;\n-\tunsigned char sha1[20];\n+\tstruct object_id oid;\n \tstruct untracked_cache *untracked;\n \tuint64_t fsmonitor_last_update;\n \tstruct ewah_bitmap *fsmonitor_dirty;\ndiff --git a/read-cache.c b/read-cache.c\nindex f47666b975..9dbaeeec43 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1806,7 +1806,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \tif (verify_hdr(hdr, mmap_size) < 0)\n \t\tgoto unmap;\n \n-\thashcpy(istate->sha1, (const unsigned char *)hdr + mmap_size - the_hash_algo->rawsz);\n+\thashcpy(istate->oid.hash, (const unsigned char *)hdr + mmap_size - the_hash_algo->rawsz);\n \tistate->version = ntohl(hdr->hdr_version);\n \tistate->cache_nr = ntohl(hdr->hdr_entries);\n \tistate->cache_alloc = alloc_nr(istate->cache_nr);\n@@ -1902,10 +1902,10 @@ int read_index_from(struct index_state *istate, const char *path,\n \tbase_oid_hex = oid_to_hex(&split_index->base_oid);\n \tbase_path = xstrfmt(\"%s/sharedindex.%s\", gitdir, base_oid_hex);\n \tret = do_read_index(split_index->base, base_path, 1);\n-\tif (hashcmp(split_index->base_oid.hash, split_index->base->sha1))\n+\tif (oidcmp(&split_index->base_oid, &split_index->base->oid))\n \t\tdie(\"broken index, expect %s in %s, got %s\",\n \t\t    base_oid_hex, base_path,\n-\t\t    sha1_to_hex(split_index->base->sha1));\n+\t\t    oid_to_hex(&split_index->base->oid));\n \n \tfreshen_shared_index(base_path, 0);\n \tmerge_base_index(istate);\n@@ -2194,7 +2194,7 @@ static int verify_index_from(const struct index_state *istate, const char *path)\n \tif (n != the_hash_algo->rawsz)\n \t\tgoto out;\n \n-\tif (hashcmp(istate->sha1, hash))\n+\tif (hashcmp(istate->oid.hash, hash))\n \t\tgoto out;\n \n \tclose(fd);\n@@ -2373,7 +2373,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,\n \t\t\treturn -1;\n \t}\n \n-\tif (ce_flush(&c, newfd, istate->sha1))\n+\tif (ce_flush(&c, newfd, istate->oid.hash))\n \t\treturn -1;\n \tif (close_tempfile_gently(tempfile)) {\n \t\terror(_(\"could not close '%s'\"), tempfile->filename.buf);\n@@ -2497,10 +2497,10 @@ static int write_shared_index(struct index_state *istate,\n \t\treturn ret;\n \t}\n \tret = rename_tempfile(temp,\n-\t\t\t      git_path(\"sharedindex.%s\", sha1_to_hex(si->base->sha1)));\n+\t\t\t      git_path(\"sharedindex.%s\", oid_to_hex(&si->base->oid)));\n \tif (!ret) {\n-\t\thashcpy(si->base_oid.hash, si->base->sha1);\n-\t\tclean_shared_index_files(sha1_to_hex(si->base->sha1));\n+\t\toidcpy(&si->base_oid, &si->base->oid);\n+\t\tclean_shared_index_files(oid_to_hex(&si->base->oid));\n \t}\n \n \treturn ret;\ndiff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c\nindex 754e9bb624..63c689d6ee 100644\n--- a/t/helper/test-dump-split-index.c\n+++ b/t/helper/test-dump-split-index.c\n@@ -14,7 +14,7 @@ int cmd__dump_split_index(int ac, const char **av)\n \tint i;\n \n \tdo_read_index(&the_index, av[1], 1);\n-\tprintf(\"own %s\\n\", sha1_to_hex(the_index.sha1));\n+\tprintf(\"own %s\\n\", oid_to_hex(&the_index.oid));\n \tsi = the_index.split_index;\n \tif (!si) {\n \t\tprintf(\"not a split index\\n\");\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex e73745051e..038ef7b926 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1287,7 +1287,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options\n \to->result.split_index = o->src_index->split_index;\n \tif (o->result.split_index)\n \t\to->result.split_index->refcount++;\n-\thashcpy(o->result.sha1, o->src_index->sha1);\n+\toidcpy(&o->result.oid, &o->src_index->oid);\n \to->merge_size = len;\n \tmark_all_ce_unused(o->src_index);\n \n"},{"id":"345535","messageId":"20180423233951.276447-23-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 22/41] revision: replace use of hard-coded constants","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:32Z","receivedAt":"2018-04-23T23:40:36Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Replace two uses of the hard-coded constant 40 with references to\nthe_hash_algo.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n revision.c | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex ce0e7b71f2..daf7fe6ff4 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1751,6 +1751,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \tconst char *arg = argv[0];\n \tconst char *optarg;\n \tint argcount;\n+\tconst unsigned hexsz = the_hash_algo->hexsz;\n \n \t/* pseudo revision arguments */\n \tif (!strcmp(arg, \"--all\") || !strcmp(arg, \"--branches\") ||\n@@ -2038,8 +2039,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->abbrev = strtoul(optarg, NULL, 10);\n \t\tif (revs->abbrev < MINIMUM_ABBREV)\n \t\t\trevs->abbrev = MINIMUM_ABBREV;\n-\t\telse if (revs->abbrev > 40)\n-\t\t\trevs->abbrev = 40;\n+\t\telse if (revs->abbrev > hexsz)\n+\t\t\trevs->abbrev = hexsz;\n \t} else if (!strcmp(arg, \"--abbrev-commit\")) {\n \t\trevs->abbrev_commit = 1;\n \t\trevs->abbrev_commit_given = 1;\n"},{"id":"345536","messageId":"20180423233951.276447-22-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 21/41] http: eliminate hard-coded constants","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:31Z","receivedAt":"2018-04-23T23:40:43Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Use the_hash_algo to find the right size for parsing pack names.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n http.c | 11 ++++++-----\n 1 file changed, 6 insertions(+), 5 deletions(-)\n\ndiff --git a/http.c b/http.c\nindex 3034d10b68..ec70676748 100644\n--- a/http.c\n+++ b/http.c\n@@ -2047,7 +2047,8 @@ int http_get_info_packs(const char *base_url, struct packed_git **packs_head)\n \tint ret = 0, i = 0;\n \tchar *url, *data;\n \tstruct strbuf buf = STRBUF_INIT;\n-\tunsigned char sha1[20];\n+\tunsigned char hash[GIT_MAX_RAWSZ];\n+\tconst unsigned hexsz = the_hash_algo->hexsz;\n \n \tend_url_with_slash(&buf, base_url);\n \tstrbuf_addstr(&buf, \"objects/info/packs\");\n@@ -2063,11 +2064,11 @@ int http_get_info_packs(const char *base_url, struct packed_git **packs_head)\n \t\tswitch (data[i]) {\n \t\tcase 'P':\n \t\t\ti++;\n-\t\t\tif (i + 52 <= buf.len &&\n+\t\t\tif (i + hexsz + 12 <= buf.len &&\n \t\t\t    starts_with(data + i, \" pack-\") &&\n-\t\t\t    starts_with(data + i + 46, \".pack\\n\")) {\n-\t\t\t\tget_sha1_hex(data + i + 6, sha1);\n-\t\t\t\tfetch_and_setup_pack_index(packs_head, sha1,\n+\t\t\t    starts_with(data + i + hexsz + 6, \".pack\\n\")) {\n+\t\t\t\tget_sha1_hex(data + i + 6, hash);\n+\t\t\t\tfetch_and_setup_pack_index(packs_head, hash,\n \t\t\t\t\t\t      base_url);\n \t\t\t\ti += 51;\n \t\t\t\tbreak;\n"},{"id":"345537","messageId":"20180423233951.276447-21-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 20/41] dir: convert struct untracked_cache_dir to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:30Z","receivedAt":"2018-04-23T23:40:44Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert the exclude_sha1 member of struct untracked_cache_dir and rename\nit to exclude_oid.  Eliminate several hard-coded integral constants, and\nupdate a function name that referred to SHA-1.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n dir.c                                | 23 ++++++++++++-----------\n dir.h                                |  5 +++--\n t/helper/test-dump-untracked-cache.c |  2 +-\n 3 files changed, 16 insertions(+), 14 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex 63a917be45..06f4c4a8bf 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1240,11 +1240,11 @@ static void prep_exclude(struct dir_struct *dir,\n \t\t    (!untracked || !untracked->valid ||\n \t\t     /*\n \t\t      * .. and .gitignore does not exist before\n-\t\t      * (i.e. null exclude_sha1). Then we can skip\n+\t\t      * (i.e. null exclude_oid). Then we can skip\n \t\t      * loading .gitignore, which would result in\n \t\t      * ENOENT anyway.\n \t\t      */\n-\t\t     !is_null_sha1(untracked->exclude_sha1))) {\n+\t\t     !is_null_oid(&untracked->exclude_oid))) {\n \t\t\t/*\n \t\t\t * dir->basebuf gets reused by the traversal, but we\n \t\t\t * need fname to remain unchanged to ensure the src\n@@ -1275,9 +1275,9 @@ static void prep_exclude(struct dir_struct *dir,\n \t\t * order, though, if you do that.\n \t\t */\n \t\tif (untracked &&\n-\t\t    hashcmp(oid_stat.oid.hash, untracked->exclude_sha1)) {\n+\t\t    oidcmp(&oid_stat.oid, &untracked->exclude_oid)) {\n \t\t\tinvalidate_gitignore(dir->untracked, untracked);\n-\t\t\thashcpy(untracked->exclude_sha1, oid_stat.oid.hash);\n+\t\t\toidcpy(&untracked->exclude_oid, &oid_stat.oid);\n \t\t}\n \t\tdir->exclude_stack = stk;\n \t\tcurrent = stk->baselen;\n@@ -2622,9 +2622,10 @@ static void write_one_dir(struct untracked_cache_dir *untracked,\n \t\tstat_data_to_disk(&stat_data, &untracked->stat_data);\n \t\tstrbuf_add(&wd->sb_stat, &stat_data, sizeof(stat_data));\n \t}\n-\tif (!is_null_sha1(untracked->exclude_sha1)) {\n+\tif (!is_null_oid(&untracked->exclude_oid)) {\n \t\tewah_set(wd->sha1_valid, i);\n-\t\tstrbuf_add(&wd->sb_sha1, untracked->exclude_sha1, 20);\n+\t\tstrbuf_add(&wd->sb_sha1, untracked->exclude_oid.hash,\n+\t\t\t   the_hash_algo->rawsz);\n \t}\n \n \tintlen = encode_varint(untracked->untracked_nr, intbuf);\n@@ -2825,16 +2826,16 @@ static void read_stat(size_t pos, void *cb)\n \tud->valid = 1;\n }\n \n-static void read_sha1(size_t pos, void *cb)\n+static void read_oid(size_t pos, void *cb)\n {\n \tstruct read_data *rd = cb;\n \tstruct untracked_cache_dir *ud = rd->ucd[pos];\n-\tif (rd->data + 20 > rd->end) {\n+\tif (rd->data + the_hash_algo->rawsz > rd->end) {\n \t\trd->data = rd->end + 1;\n \t\treturn;\n \t}\n-\thashcpy(ud->exclude_sha1, rd->data);\n-\trd->data += 20;\n+\thashcpy(ud->exclude_oid.hash, rd->data);\n+\trd->data += the_hash_algo->rawsz;\n }\n \n static void load_oid_stat(struct oid_stat *oid_stat, const unsigned char *data,\n@@ -2917,7 +2918,7 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tewah_each_bit(rd.check_only, set_check_only, &rd);\n \trd.data = next + len;\n \tewah_each_bit(rd.valid, read_stat, &rd);\n-\tewah_each_bit(rd.sha1_valid, read_sha1, &rd);\n+\tewah_each_bit(rd.sha1_valid, read_oid, &rd);\n \tnext = rd.data;\n \n done:\ndiff --git a/dir.h b/dir.h\nindex b0758b82a2..de66be9f4e 100644\n--- a/dir.h\n+++ b/dir.h\n@@ -3,6 +3,7 @@\n \n /* See Documentation/technical/api-directory-listing.txt */\n \n+#include \"cache.h\"\n #include \"strbuf.h\"\n \n struct dir_entry {\n@@ -118,8 +119,8 @@ struct untracked_cache_dir {\n \t/* all data except 'dirs' in this struct are good */\n \tunsigned int valid : 1;\n \tunsigned int recurse : 1;\n-\t/* null SHA-1 means this directory does not have .gitignore */\n-\tunsigned char exclude_sha1[20];\n+\t/* null object ID means this directory does not have .gitignore */\n+\tstruct object_id exclude_oid;\n \tchar name[FLEX_ARRAY];\n };\n \ndiff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c\nindex d7c55c2355..bd92fb305a 100644\n--- a/t/helper/test-dump-untracked-cache.c\n+++ b/t/helper/test-dump-untracked-cache.c\n@@ -23,7 +23,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base)\n \tlen = base->len;\n \tstrbuf_addf(base, \"%s/\", ucd->name);\n \tprintf(\"%s %s\", base->buf,\n-\t       sha1_to_hex(ucd->exclude_sha1));\n+\t       oid_to_hex(&ucd->exclude_oid));\n \tif (ucd->recurse)\n \t\tfputs(\" recurse\", stdout);\n \tif (ucd->check_only)\n"},{"id":"345538","messageId":"20180423233951.276447-26-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 25/41] builtin/receive-pack: avoid hard-coded constants for push certs","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:35Z","receivedAt":"2018-04-23T23:40:47Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Use the GIT_SHA1_RAWSZ and GIT_SHA1_HEXSZ macros instead of hard-coding\nthe constants 20 and 40.  Switch one use of 20 with a format specifier\nfor a hex value to use the hex constant instead, as the original appears\nto have been a typo.\n\nAt this point, avoid converting the hard-coded use of SHA-1 to use\nthe_hash_algo.  SHA-1, even if not collision resistant, is secure in the\ncontext in which it is used here, and the hash algorithm of the repo\nneed not match what is used here.  When we adopt a new hash algorithm,\nwe can simply adopt the new algorithm wholesale here, as the nonce is\nopaque and its length and validity are entirely controlled by the\nserver.  Consequently, defer updating this code until that point.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/receive-pack.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex c4272fbc96..5f35596c14 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -454,21 +454,21 @@ static void hmac_sha1(unsigned char *out,\n \t/* RFC 2104 2. (6) & (7) */\n \tgit_SHA1_Init(&ctx);\n \tgit_SHA1_Update(&ctx, k_opad, sizeof(k_opad));\n-\tgit_SHA1_Update(&ctx, out, 20);\n+\tgit_SHA1_Update(&ctx, out, GIT_SHA1_RAWSZ);\n \tgit_SHA1_Final(out, &ctx);\n }\n \n static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n-\tunsigned char sha1[20];\n+\tunsigned char sha1[GIT_SHA1_RAWSZ];\n \n \tstrbuf_addf(&buf, \"%s:%\"PRItime, path, stamp);\n \thmac_sha1(sha1, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));;\n \tstrbuf_release(&buf);\n \n \t/* RFC 2104 5. HMAC-SHA1-80 */\n-\tstrbuf_addf(&buf, \"%\"PRItime\"-%.*s\", stamp, 20, sha1_to_hex(sha1));\n+\tstrbuf_addf(&buf, \"%\"PRItime\"-%.*s\", stamp, GIT_SHA1_HEXSZ, sha1_to_hex(sha1));\n \treturn strbuf_detach(&buf, NULL);\n }\n \n"},{"id":"345539","messageId":"20180423233951.276447-29-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 28/41] merge: convert empty tree constant to the_hash_algo","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:38Z","receivedAt":"2018-04-23T23:40:50Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"To avoid dependency on a particular hash algorithm, convert a use of\nEMPTY_TREE_SHA1_HEX to use the_hash_algo->empty_tree instead.  Since\nboth branches now use oid_to_hex, condense the if statement into a\nternary.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n merge.c | 5 +----\n 1 file changed, 1 insertion(+), 4 deletions(-)\n\ndiff --git a/merge.c b/merge.c\nindex f06a4773d4..5186cb6156 100644\n--- a/merge.c\n+++ b/merge.c\n@@ -11,10 +11,7 @@\n \n static const char *merge_argument(struct commit *commit)\n {\n-\tif (commit)\n-\t\treturn oid_to_hex(&commit->object.oid);\n-\telse\n-\t\treturn EMPTY_TREE_SHA1_HEX;\n+\treturn oid_to_hex(commit ? &commit->object.oid : the_hash_algo->empty_tree);\n }\n \n int index_has_changes(struct strbuf *sb)\n"},{"id":"345540","messageId":"20180423233951.276447-37-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 36/41] sequencer: use the_hash_algo for empty tree object ID","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:46Z","receivedAt":"2018-04-23T23:40:55Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"To ensure that we are hash algorithm agnostic, use the_hash_algo to look\nup the object ID for the empty tree instead of using the empty_tree_oid\nvariable.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n sequencer.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex b879593486..12c1e1cdbb 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1119,7 +1119,7 @@ static int try_to_commit(struct strbuf *msg, const char *author,\n \n \tif (!(flags & ALLOW_EMPTY) && !oidcmp(current_head ?\n \t\t\t\t\t      &current_head->tree->object.oid :\n-\t\t\t\t\t      &empty_tree_oid, &tree)) {\n+\t\t\t\t\t      the_hash_algo->empty_tree, &tree)) {\n \t\tres = 1; /* run 'git commit' to display error message */\n \t\tgoto out;\n \t}\n"},{"id":"345541","messageId":"20180423233951.276447-35-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 34/41] sha1_file: convert cached object code to struct object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:44Z","receivedAt":"2018-04-23T23:40:57Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert the code that looks up cached objects to use struct object_id.\nAdjust the lookup for empty trees to use the_hash_algo.  Note that we\ndon't need to be concerned about the hard-coded object ID in the\nempty_tree object since we never use it.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n sha1_file.c | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 4328c61285..11c840f89c 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -107,7 +107,7 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n  * application).\n  */\n static struct cached_object {\n-\tunsigned char sha1[20];\n+\tstruct object_id oid;\n \tenum object_type type;\n \tvoid *buf;\n \tunsigned long size;\n@@ -115,22 +115,22 @@ static struct cached_object {\n static int cached_object_nr, cached_object_alloc;\n \n static struct cached_object empty_tree = {\n-\tEMPTY_TREE_SHA1_BIN_LITERAL,\n+\t{ EMPTY_TREE_SHA1_BIN_LITERAL },\n \tOBJ_TREE,\n \t\"\",\n \t0\n };\n \n-static struct cached_object *find_cached_object(const unsigned char *sha1)\n+static struct cached_object *find_cached_object(const struct object_id *oid)\n {\n \tint i;\n \tstruct cached_object *co = cached_objects;\n \n \tfor (i = 0; i < cached_object_nr; i++, co++) {\n-\t\tif (!hashcmp(co->sha1, sha1))\n+\t\tif (!oidcmp(&co->oid, oid))\n \t\t\treturn co;\n \t}\n-\tif (!hashcmp(sha1, empty_tree.sha1))\n+\tif (!oidcmp(oid, the_hash_algo->empty_tree))\n \t\treturn &empty_tree;\n \treturn NULL;\n }\n@@ -1248,7 +1248,7 @@ int oid_object_info_extended(const struct object_id *oid, struct object_info *oi\n \t\toi = &blank_oi;\n \n \tif (!(flags & OBJECT_INFO_SKIP_CACHED)) {\n-\t\tstruct cached_object *co = find_cached_object(real->hash);\n+\t\tstruct cached_object *co = find_cached_object(real);\n \t\tif (co) {\n \t\t\tif (oi->typep)\n \t\t\t\t*(oi->typep) = co->type;\n@@ -1357,7 +1357,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,\n \tstruct cached_object *co;\n \n \thash_object_file(buf, len, type_name(type), oid);\n-\tif (has_sha1_file(oid->hash) || find_cached_object(oid->hash))\n+\tif (has_sha1_file(oid->hash) || find_cached_object(oid))\n \t\treturn 0;\n \tALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc);\n \tco = &cached_objects[cached_object_nr++];\n@@ -1365,7 +1365,7 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type,\n \tco->type = type;\n \tco->buf = xmalloc(len);\n \tmemcpy(co->buf, buf, len);\n-\thashcpy(co->sha1, oid->hash);\n+\toidcpy(&co->oid, oid);\n \treturn 0;\n }\n \n"},{"id":"345542","messageId":"20180423233951.276447-31-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 30/41] submodule: convert several uses of EMPTY_TREE_SHA1_HEX","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:40Z","receivedAt":"2018-04-23T23:40:59Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert several uses of EMPTY_TREE_SHA1_HEX to use oid_to_hex and\nthe_hash_algo to avoid a dependency on a given hash algorithm.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n submodule.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/submodule.c b/submodule.c\nindex 9a50168b23..22a96b7af0 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -1567,7 +1567,7 @@ static void submodule_reset_index(const char *path)\n \t\t\t\t   get_super_prefix_or_empty(), path);\n \targv_array_pushl(&cp.args, \"read-tree\", \"-u\", \"--reset\", NULL);\n \n-\targv_array_push(&cp.args, EMPTY_TREE_SHA1_HEX);\n+\targv_array_push(&cp.args, oid_to_hex(the_hash_algo->empty_tree));\n \n \tif (run_command(&cp))\n \t\tdie(\"could not reset submodule index\");\n@@ -1659,9 +1659,9 @@ int submodule_move_head(const char *path,\n \t\targv_array_push(&cp.args, \"-m\");\n \n \tif (!(flags & SUBMODULE_MOVE_HEAD_FORCE))\n-\t\targv_array_push(&cp.args, old_head ? old_head : EMPTY_TREE_SHA1_HEX);\n+\t\targv_array_push(&cp.args, old_head ? old_head : oid_to_hex(the_hash_algo->empty_tree));\n \n-\targv_array_push(&cp.args, new_head ? new_head : EMPTY_TREE_SHA1_HEX);\n+\targv_array_push(&cp.args, new_head ? new_head : oid_to_hex(the_hash_algo->empty_tree));\n \n \tif (run_command(&cp)) {\n \t\tret = -1;\n"},{"id":"345543","messageId":"20180423233951.276447-41-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 40/41] add--interactive: compute the empty tree value","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:50Z","receivedAt":"2018-04-23T23:41:02Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"The interactive add script hard-codes the object ID of the empty tree.\nTo avoid any problems when changing hashes, compute this value when used\nand cache it for any future uses.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n git-add--interactive.perl | 11 +++++++++--\n 1 file changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex c1f52e457f..36f38ced90 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -205,8 +205,15 @@ my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'))\n \t}\n }\n \n-sub get_empty_tree {\n-\treturn '4b825dc642cb6eb9a060e54bf8d69288fbee4904';\n+{\n+\tmy $empty_tree;\n+\tsub get_empty_tree {\n+\t\treturn $empty_tree if defined $empty_tree;\n+\n+\t\t$empty_tree = run_cmd_pipe(qw(git hash-object -t tree /dev/null));\n+\t\tchomp $empty_tree;\n+\t\treturn $empty_tree;\n+\t}\n }\n \n sub get_diff_reference {\n"},{"id":"345544","messageId":"20180423233951.276447-40-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 39/41] Update shell scripts to compute empty tree object ID","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:49Z","receivedAt":"2018-04-23T23:41:05Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Several of our shell scripts hard-code the object ID of the empty tree.\nTo avoid any problems when changing hashes, compute this value on\nstartup of the script.  For performance, store the value in a variable\nand reuse it throughout the life of the script.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n git-filter-branch.sh               | 4 +++-\n git-rebase--interactive.sh         | 4 +++-\n templates/hooks--pre-commit.sample | 2 +-\n 3 files changed, 7 insertions(+), 3 deletions(-)\n\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex 64f21547c1..ccceaf19a7 100755\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -11,6 +11,8 @@\n # The following functions will also be available in the commit filter:\n \n functions=$(cat << \\EOF\n+EMPTY_TREE=$(git hash-object -t tree /dev/null)\n+\n warn () {\n \techo \"$*\" >&2\n }\n@@ -46,7 +48,7 @@ git_commit_non_empty_tree()\n {\n \tif test $# = 3 && test \"$1\" = $(git rev-parse \"$3^{tree}\"); then\n \t\tmap \"$3\"\n-\telif test $# = 1 && test \"$1\" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904; then\n+\telif test $# = 1 && test \"$1\" = $EMPTY_TREE; then\n \t\t:\n \telse\n \t\tgit commit-tree \"$@\"\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 50323fc273..cc873d630d 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -81,6 +81,8 @@ rewritten_pending=\"$state_dir\"/rewritten-pending\n # and leaves CR at the end instead.\n cr=$(printf \"\\015\")\n \n+empty_tree=$(git hash-object -t tree /dev/null)\n+\n strategy_args=${strategy:+--strategy=$strategy}\n test -n \"$strategy_opts\" &&\n eval '\n@@ -238,7 +240,7 @@ is_empty_commit() {\n \t\tdie \"$(eval_gettext \"\\$sha1: not a commit that can be picked\")\"\n \t}\n \tptree=$(git rev-parse -q --verify \"$1\"^^{tree} 2>/dev/null) ||\n-\t\tptree=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+\t\tptree=$empty_tree\n \ttest \"$tree\" = \"$ptree\"\n }\n \ndiff --git a/templates/hooks--pre-commit.sample b/templates/hooks--pre-commit.sample\nindex 68d62d5446..6a75641638 100755\n--- a/templates/hooks--pre-commit.sample\n+++ b/templates/hooks--pre-commit.sample\n@@ -12,7 +12,7 @@ then\n \tagainst=HEAD\n else\n \t# Initial commit: diff against an empty tree object\n-\tagainst=4b825dc642cb6eb9a060e54bf8d69288fbee4904\n+\tagainst=$(git hash-object -t tree /dev/null)\n fi\n \n # If you want to allow non-ASCII filenames set this variable to true.\n"},{"id":"345545","messageId":"20180423233951.276447-39-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 38/41] sha1_file: only expose empty object constants through git_hash_algo","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:48Z","receivedAt":"2018-04-23T23:41:07Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"There really isn't any case in which we want to expose the constants for\nempty trees and blobs outside of using the hash algorithm abstraction.\nMake these constants static and stop exposing the defines in cache.h.\nRemove the constants which are no longer in use.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n cache.h     | 16 ----------------\n sha1_file.c | 13 +++++++++++--\n 2 files changed, 11 insertions(+), 18 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 9ad1dd2ddc..c5b041019b 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1013,22 +1013,6 @@ static inline void oidread(struct object_id *oid, const unsigned char *hash)\n \tmemcpy(oid->hash, hash, the_hash_algo->rawsz);\n }\n \n-\n-#define EMPTY_TREE_SHA1_HEX \\\n-\t\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"\n-#define EMPTY_TREE_SHA1_BIN_LITERAL \\\n-\t \"\\x4b\\x82\\x5d\\xc6\\x42\\xcb\\x6e\\xb9\\xa0\\x60\" \\\n-\t \"\\xe5\\x4b\\xf8\\xd6\\x92\\x88\\xfb\\xee\\x49\\x04\"\n-extern const struct object_id empty_tree_oid;\n-#define EMPTY_TREE_SHA1_BIN (empty_tree_oid.hash)\n-\n-#define EMPTY_BLOB_SHA1_HEX \\\n-\t\"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391\"\n-#define EMPTY_BLOB_SHA1_BIN_LITERAL \\\n-\t\"\\xe6\\x9d\\xe2\\x9b\\xb2\\xd1\\xd6\\x43\\x4b\\x8b\" \\\n-\t\"\\x29\\xae\\x77\\x5a\\xd8\\xc2\\xe4\\x8c\\x53\\x91\"\n-extern const struct object_id empty_blob_oid;\n-\n static inline int is_empty_blob_sha1(const unsigned char *sha1)\n {\n \treturn !hashcmp(sha1, the_hash_algo->empty_blob->hash);\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 11c840f89c..794753bd54 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -35,12 +35,21 @@\n /* The maximum size for an object header. */\n #define MAX_HEADER_LEN 32\n \n+\n+#define EMPTY_TREE_SHA1_BIN_LITERAL \\\n+\t \"\\x4b\\x82\\x5d\\xc6\\x42\\xcb\\x6e\\xb9\\xa0\\x60\" \\\n+\t \"\\xe5\\x4b\\xf8\\xd6\\x92\\x88\\xfb\\xee\\x49\\x04\"\n+\n+#define EMPTY_BLOB_SHA1_BIN_LITERAL \\\n+\t\"\\xe6\\x9d\\xe2\\x9b\\xb2\\xd1\\xd6\\x43\\x4b\\x8b\" \\\n+\t\"\\x29\\xae\\x77\\x5a\\xd8\\xc2\\xe4\\x8c\\x53\\x91\"\n+\n const unsigned char null_sha1[GIT_MAX_RAWSZ];\n const struct object_id null_oid;\n-const struct object_id empty_tree_oid = {\n+static const struct object_id empty_tree_oid = {\n \tEMPTY_TREE_SHA1_BIN_LITERAL\n };\n-const struct object_id empty_blob_oid = {\n+static const struct object_id empty_blob_oid = {\n \tEMPTY_BLOB_SHA1_BIN_LITERAL\n };\n \n"},{"id":"345546","messageId":"20180423233951.276447-38-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 37/41] dir: use the_hash_algo for empty blob object ID","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:47Z","receivedAt":"2018-04-23T23:41:09Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"To ensure that we are hash algorithm agnostic, use the_hash_algo to look\nup the object ID for the empty blob instead of using the empty_tree_oid\nvariable.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n dir.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/dir.c b/dir.c\nindex 06f4c4a8bf..e879c34c2e 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -828,7 +828,7 @@ static int add_excludes(const char *fname, const char *base, int baselen,\n \t\tif (size == 0) {\n \t\t\tif (oid_stat) {\n \t\t\t\tfill_stat_data(&oid_stat->stat, &st);\n-\t\t\t\toidcpy(&oid_stat->oid, &empty_blob_oid);\n+\t\t\t\toidcpy(&oid_stat->oid, the_hash_algo->empty_blob);\n \t\t\t\toid_stat->valid = 1;\n \t\t\t}\n \t\t\tclose(fd);\n"},{"id":"345548","messageId":"20180423233951.276447-42-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 41/41] merge-one-file: compute empty blob object ID","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:51Z","receivedAt":"2018-04-23T23:41:17Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"This script hard-codes the object ID of the empty tree.  To avoid any\nproblems when changing hashes, compute this value by calling git\nhash-object.\n---\n git-merge-one-file.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/git-merge-one-file.sh b/git-merge-one-file.sh\nindex 9879c59395..f6d9852d2f 100755\n--- a/git-merge-one-file.sh\n+++ b/git-merge-one-file.sh\n@@ -120,7 +120,7 @@ case \"${1:-.}${2:-.}${3:-.}\" in\n \tcase \"$1\" in\n \t'')\n \t\techo \"Added $4 in both, but differently.\"\n-\t\torig=$(git unpack-file e69de29bb2d1d6434b8b29ae775ad8c2e48c5391)\n+\t\torig=$(git unpack-file $(git hash-object /dev/null))\n \t\t;;\n \t*)\n \t\techo \"Auto-merging $4\"\n"},{"id":"345549","messageId":"20180423233951.276447-36-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 35/41] cache-tree: use is_empty_tree_oid","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:45Z","receivedAt":"2018-04-23T23:41:19Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"When comparing an object ID against that of the empty tree, use the\nis_empty_tree_oid function to ensure that we abstract over the hash\nalgorithm properly.  In addition, this is more readable than a plain\noidcmp.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n cache-tree.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 8c7e1258a4..25663825b5 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -385,7 +385,7 @@ static int update_one(struct cache_tree *it,\n \t\t/*\n \t\t * \"sub\" can be an empty tree if all subentries are i-t-a.\n \t\t */\n-\t\tif (contains_ita && !oidcmp(oid, &empty_tree_oid))\n+\t\tif (contains_ita && is_empty_tree_oid(oid))\n \t\t\tcontinue;\n \n \t\tstrbuf_grow(&buffer, entlen + 100);\n"},{"id":"345550","messageId":"20180423233951.276447-34-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 33/41] builtin/reset: convert use of EMPTY_TREE_SHA1_BIN","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:43Z","receivedAt":"2018-04-23T23:41:20Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert the last use of EMPTY_TREE_SHA1_BIN to use a direct copy from\nthe_hash_algo->empty_tree to avoid a dependency on a given hash\nalgorithm.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/reset.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 7f1c3f02a3..a862c70fab 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -314,7 +314,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \tunborn = !strcmp(rev, \"HEAD\") && get_oid(\"HEAD\", &oid);\n \tif (unborn) {\n \t\t/* reset on unborn branch: treat as reset to empty tree */\n-\t\thashcpy(oid.hash, EMPTY_TREE_SHA1_BIN);\n+\t\toidcpy(&oid, the_hash_algo->empty_tree);\n \t} else if (!pathspec.nr) {\n \t\tstruct commit *commit;\n \t\tif (get_oid_committish(rev, &oid))\n"},{"id":"345551","messageId":"20180423233951.276447-32-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 31/41] wt-status: convert two uses of EMPTY_TREE_SHA1_HEX","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:41Z","receivedAt":"2018-04-23T23:41:24Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert two uses of EMPTY_TREE_SHA1_HEX to use oid_to_hex_r and\nthe_hash_algo to avoid a dependency on a given hash algorithm.  Use\noid_to_hex_r in preference to oid_to_hex because the buffer needs to\nlast through several function calls which might exhaust the limit of\nfour static buffers.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n wt-status.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 50815e5faf..857724bd60 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -600,10 +600,11 @@ static void wt_status_collect_changes_index(struct wt_status *s)\n {\n \tstruct rev_info rev;\n \tstruct setup_revision_opt opt;\n+\tchar hex[GIT_MAX_HEXSZ + 1];\n \n \tinit_revisions(&rev, NULL);\n \tmemset(&opt, 0, sizeof(opt));\n-\topt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;\n+\topt.def = s->is_initial ? oid_to_hex_r(hex, the_hash_algo->empty_tree) : s->reference;\n \tsetup_revisions(0, NULL, &rev, &opt);\n \n \trev.diffopt.flags.override_submodule_config = 1;\n@@ -975,13 +976,14 @@ static void wt_longstatus_print_verbose(struct wt_status *s)\n \tstruct setup_revision_opt opt;\n \tint dirty_submodules;\n \tconst char *c = color(WT_STATUS_HEADER, s);\n+\tchar hex[GIT_MAX_HEXSZ + 1];\n \n \tinit_revisions(&rev, NULL);\n \trev.diffopt.flags.allow_textconv = 1;\n \trev.diffopt.ita_invisible_in_index = 1;\n \n \tmemset(&opt, 0, sizeof(opt));\n-\topt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;\n+\topt.def = s->is_initial ? oid_to_hex_r(hex, the_hash_algo->empty_tree) : s->reference;\n \tsetup_revisions(0, NULL, &rev, &opt);\n \n \trev.diffopt.output_format |= DIFF_FORMAT_PATCH;\n"},{"id":"345552","messageId":"20180423233951.276447-33-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 32/41] builtin/receive-pack: convert one use of EMPTY_TREE_SHA1_HEX","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:42Z","receivedAt":"2018-04-23T23:41:26Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert one use of EMPTY_TREE_SHA1_HEX to use oid_to_hex and\nthe_hash_algo to avoid a dependency on a given hash algorithm.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/receive-pack.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 5f35596c14..c31ceb30c2 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -968,7 +968,7 @@ static const char *push_to_deploy(unsigned char *sha1,\n \t\treturn \"Working directory has unstaged changes\";\n \n \t/* diff-index with either HEAD or an empty tree */\n-\tdiff_index[4] = head_has_history() ? \"HEAD\" : EMPTY_TREE_SHA1_HEX;\n+\tdiff_index[4] = head_has_history() ? \"HEAD\" : oid_to_hex(the_hash_algo->empty_tree);\n \n \tchild_process_init(&child);\n \tchild.argv = diff_index;\n"},{"id":"345553","messageId":"20180423233951.276447-30-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 29/41] sequencer: convert one use of EMPTY_TREE_SHA1_HEX","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:39Z","receivedAt":"2018-04-23T23:41:33Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert one use of EMPTY_TREE_SHA1_HEX to use oid_to_hex and\nthe_hash_algo to avoid a dependency on a given hash algorithm.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n sequencer.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 667f35ebdf..b879593486 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1480,7 +1480,8 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,\n \t\tunborn = get_oid(\"HEAD\", &head);\n \t\tif (unborn)\n \t\t\toidcpy(&head, the_hash_algo->empty_tree);\n-\t\tif (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : \"HEAD\",\n+\t\tif (index_differs_from(unborn ?\n+\t\t\t\t       oid_to_hex(the_hash_algo->empty_tree) : \"HEAD\",\n \t\t\t\t       NULL, 0))\n \t\t\treturn error_dirty_index(opts);\n \t}\n"},{"id":"345554","messageId":"20180423233951.276447-28-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 27/41] builtin/merge: switch tree functions to use object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:37Z","receivedAt":"2018-04-23T23:41:38Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"The read_empty and reset_hard functions are static and their callers\nhave already changed to use struct object_id, so convert them as well.\nTo avoid dependency on the hash algorithm in use, switch from using\nEMPTY_TREE_SHA1_HEX to using oid_to_hex with the_hash_algo.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/merge.c | 14 +++++++-------\n 1 file changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 9db5a2cf16..8d75ebe64b 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -280,7 +280,7 @@ static int save_state(struct object_id *stash)\n \treturn rc;\n }\n \n-static void read_empty(unsigned const char *sha1, int verbose)\n+static void read_empty(const struct object_id *oid, int verbose)\n {\n \tint i = 0;\n \tconst char *args[7];\n@@ -290,15 +290,15 @@ static void read_empty(unsigned const char *sha1, int verbose)\n \t\targs[i++] = \"-v\";\n \targs[i++] = \"-m\";\n \targs[i++] = \"-u\";\n-\targs[i++] = EMPTY_TREE_SHA1_HEX;\n-\targs[i++] = sha1_to_hex(sha1);\n+\targs[i++] = oid_to_hex(the_hash_algo->empty_tree);\n+\targs[i++] = oid_to_hex(oid);\n \targs[i] = NULL;\n \n \tif (run_command_v_opt(args, RUN_GIT_CMD))\n \t\tdie(_(\"read-tree failed\"));\n }\n \n-static void reset_hard(unsigned const char *sha1, int verbose)\n+static void reset_hard(const struct object_id *oid, int verbose)\n {\n \tint i = 0;\n \tconst char *args[6];\n@@ -308,7 +308,7 @@ static void reset_hard(unsigned const char *sha1, int verbose)\n \t\targs[i++] = \"-v\";\n \targs[i++] = \"--reset\";\n \targs[i++] = \"-u\";\n-\targs[i++] = sha1_to_hex(sha1);\n+\targs[i++] = oid_to_hex(oid);\n \targs[i] = NULL;\n \n \tif (run_command_v_opt(args, RUN_GIT_CMD))\n@@ -324,7 +324,7 @@ static void restore_state(const struct object_id *head,\n \tif (is_null_oid(stash))\n \t\treturn;\n \n-\treset_hard(head->hash, 1);\n+\treset_hard(head, 1);\n \n \targs[2] = oid_to_hex(stash);\n \n@@ -1297,7 +1297,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tif (remoteheads->next)\n \t\t\tdie(_(\"Can merge only exactly one commit into empty head\"));\n \t\tremote_head_oid = &remoteheads->item->object.oid;\n-\t\tread_empty(remote_head_oid->hash, 0);\n+\t\tread_empty(remote_head_oid, 0);\n \t\tupdate_ref(\"initial pull\", \"HEAD\", remote_head_oid, NULL, 0,\n \t\t\t   UPDATE_REFS_DIE_ON_ERR);\n \t\tgoto done;\n"},{"id":"345555","messageId":"20180423233951.276447-24-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 23/41] upload-pack: replace use of several hard-coded constants","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:33Z","receivedAt":"2018-04-23T23:41:41Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Update several uses of hard-coded 40-based constants to use either\nthe_hash_algo or GIT_MAX_HEXSZ, as appropriate.  Replace a combined use\nof oid_to_hex and memcpy with oid_to_hex_r, which not only avoids the\nneed for a constant, but is more efficient.  Make use of parse_oid_hex\nto eliminate the need for constants and simplify the code at the same\ntime.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n upload-pack.c | 18 +++++++++---------\n 1 file changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/upload-pack.c b/upload-pack.c\nindex 4a82602be5..0858527c5b 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -450,7 +450,7 @@ static int get_common_commits(void)\n \t\t\t\tbreak;\n \t\t\tdefault:\n \t\t\t\tgot_common = 1;\n-\t\t\t\tmemcpy(last_hex, oid_to_hex(&oid), 41);\n+\t\t\t\toid_to_hex_r(last_hex, &oid);\n \t\t\t\tif (multi_ack == 2)\n \t\t\t\t\tpacket_write_fmt(1, \"ACK %s common\\n\", last_hex);\n \t\t\t\telse if (multi_ack)\n@@ -492,7 +492,7 @@ static int do_reachable_revlist(struct child_process *cmd,\n \t\t\"rev-list\", \"--stdin\", NULL,\n \t};\n \tstruct object *o;\n-\tchar namebuf[42]; /* ^ + SHA-1 + LF */\n+\tchar namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + SHA-1 + LF */\n \tint i;\n \n \tcmd->argv = argv;\n@@ -561,15 +561,17 @@ static int get_reachable_list(struct object_array *src,\n \tstruct child_process cmd = CHILD_PROCESS_INIT;\n \tint i;\n \tstruct object *o;\n-\tchar namebuf[42]; /* ^ + SHA-1 + LF */\n+\tchar namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + SHA-1 + LF */\n+\tconst unsigned hexsz = the_hash_algo->hexsz;\n \n \tif (do_reachable_revlist(&cmd, src, reachable) < 0)\n \t\treturn -1;\n \n-\twhile ((i = read_in_full(cmd.out, namebuf, 41)) == 41) {\n+\twhile ((i = read_in_full(cmd.out, namebuf, hexsz + 1)) == hexsz + 1) {\n \t\tstruct object_id sha1;\n+\t\tconst char *p;\n \n-\t\tif (namebuf[40] != '\\n' || get_oid_hex(namebuf, &sha1))\n+\t\tif (parse_oid_hex(namebuf, &sha1, &p) || *p != '\\n')\n \t\t\tbreak;\n \n \t\to = lookup_object(sha1.hash);\n@@ -820,11 +822,9 @@ static void receive_needs(void)\n \t\t\tcontinue;\n \t\t}\n \t\tif (!skip_prefix(line, \"want \", &arg) ||\n-\t\t    get_oid_hex(arg, &oid_buf))\n+\t\t    parse_oid_hex(arg, &oid_buf, &features))\n \t\t\tdie(\"git upload-pack: protocol error, \"\n-\t\t\t    \"expected to get sha, not '%s'\", line);\n-\n-\t\tfeatures = arg + 40;\n+\t\t\t    \"expected to get object ID, not '%s'\", line);\n \n \t\tif (parse_feature_request(features, \"deepen-relative\"))\n \t\t\tdeepen_relative = 1;\n"},{"id":"345556","messageId":"20180423233951.276447-27-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 26/41] builtin/am: convert uses of EMPTY_TREE_SHA1_BIN to the_hash_algo","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:36Z","receivedAt":"2018-04-23T23:41:46Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert several uses of EMPTY_TREE_SHA1_BIN to use the_hash_algo\nand struct object_id instead.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/am.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 9c82603f70..f445fcb593 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1542,7 +1542,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa\n \tchar *their_tree_name;\n \n \tif (get_oid(\"HEAD\", &our_tree) < 0)\n-\t\thashcpy(our_tree.hash, EMPTY_TREE_SHA1_BIN);\n+\t\toidcpy(&our_tree, the_hash_algo->empty_tree);\n \n \tif (build_fake_ancestor(state, index_path))\n \t\treturn error(\"could not build fake ancestor\");\n@@ -2042,7 +2042,7 @@ static void am_skip(struct am_state *state)\n \tam_rerere_clear();\n \n \tif (get_oid(\"HEAD\", &head))\n-\t\thashcpy(head.hash, EMPTY_TREE_SHA1_BIN);\n+\t\toidcpy(&head, the_hash_algo->empty_tree);\n \n \tif (clean_index(&head, &head))\n \t\tdie(_(\"failed to clean index\"));\n@@ -2105,11 +2105,11 @@ static void am_abort(struct am_state *state)\n \tcurr_branch = resolve_refdup(\"HEAD\", 0, &curr_head, NULL);\n \thas_curr_head = curr_branch && !is_null_oid(&curr_head);\n \tif (!has_curr_head)\n-\t\thashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN);\n+\t\toidcpy(&curr_head, the_hash_algo->empty_tree);\n \n \thas_orig_head = !get_oid(\"ORIG_HEAD\", &orig_head);\n \tif (!has_orig_head)\n-\t\thashcpy(orig_head.hash, EMPTY_TREE_SHA1_BIN);\n+\t\toidcpy(&orig_head, the_hash_algo->empty_tree);\n \n \tclean_index(&curr_head, &orig_head);\n \n"},{"id":"345557","messageId":"20180423233951.276447-14-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 13/41] fsck: convert static functions to struct object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:23Z","receivedAt":"2018-04-23T23:41:52Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert two static functions to use struct object_id and parse_oid_hex,\ninstead of relying on harcoded 20 and 40-based constants.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n fsck.c | 20 +++++++++++---------\n 1 file changed, 11 insertions(+), 9 deletions(-)\n\ndiff --git a/fsck.c b/fsck.c\nindex 9218c2a643..768011f812 100644\n--- a/fsck.c\n+++ b/fsck.c\n@@ -711,30 +711,31 @@ static int fsck_ident(const char **ident, struct object *obj, struct fsck_option\n static int fsck_commit_buffer(struct commit *commit, const char *buffer,\n \tunsigned long size, struct fsck_options *options)\n {\n-\tunsigned char tree_sha1[20], sha1[20];\n+\tstruct object_id tree_oid, oid;\n \tstruct commit_graft *graft;\n \tunsigned parent_count, parent_line_count = 0, author_count;\n \tint err;\n \tconst char *buffer_begin = buffer;\n+\tconst char *p;\n \n \tif (verify_headers(buffer, size, &commit->object, options))\n \t\treturn -1;\n \n \tif (!skip_prefix(buffer, \"tree \", &buffer))\n \t\treturn report(options, &commit->object, FSCK_MSG_MISSING_TREE, \"invalid format - expected 'tree' line\");\n-\tif (get_sha1_hex(buffer, tree_sha1) || buffer[40] != '\\n') {\n+\tif (parse_oid_hex(buffer, &tree_oid, &p) || *p != '\\n') {\n \t\terr = report(options, &commit->object, FSCK_MSG_BAD_TREE_SHA1, \"invalid 'tree' line format - bad sha1\");\n \t\tif (err)\n \t\t\treturn err;\n \t}\n-\tbuffer += 41;\n+\tbuffer = p + 1;\n \twhile (skip_prefix(buffer, \"parent \", &buffer)) {\n-\t\tif (get_sha1_hex(buffer, sha1) || buffer[40] != '\\n') {\n+\t\tif (parse_oid_hex(buffer, &oid, &p) || *p != '\\n') {\n \t\t\terr = report(options, &commit->object, FSCK_MSG_BAD_PARENT_SHA1, \"invalid 'parent' line format - bad sha1\");\n \t\t\tif (err)\n \t\t\t\treturn err;\n \t\t}\n-\t\tbuffer += 41;\n+\t\tbuffer = p + 1;\n \t\tparent_line_count++;\n \t}\n \tgraft = lookup_commit_graft(&commit->object.oid);\n@@ -773,7 +774,7 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer,\n \tif (err)\n \t\treturn err;\n \tif (!commit->tree) {\n-\t\terr = report(options, &commit->object, FSCK_MSG_BAD_TREE, \"could not load commit's tree %s\", sha1_to_hex(tree_sha1));\n+\t\terr = report(options, &commit->object, FSCK_MSG_BAD_TREE, \"could not load commit's tree %s\", oid_to_hex(&tree_oid));\n \t\tif (err)\n \t\t\treturn err;\n \t}\n@@ -799,11 +800,12 @@ static int fsck_commit(struct commit *commit, const char *data,\n static int fsck_tag_buffer(struct tag *tag, const char *data,\n \tunsigned long size, struct fsck_options *options)\n {\n-\tunsigned char sha1[20];\n+\tstruct object_id oid;\n \tint ret = 0;\n \tconst char *buffer;\n \tchar *to_free = NULL, *eol;\n \tstruct strbuf sb = STRBUF_INIT;\n+\tconst char *p;\n \n \tif (data)\n \t\tbuffer = data;\n@@ -834,12 +836,12 @@ static int fsck_tag_buffer(struct tag *tag, const char *data,\n \t\tret = report(options, &tag->object, FSCK_MSG_MISSING_OBJECT, \"invalid format - expected 'object' line\");\n \t\tgoto done;\n \t}\n-\tif (get_sha1_hex(buffer, sha1) || buffer[40] != '\\n') {\n+\tif (parse_oid_hex(buffer, &oid, &p) || *p != '\\n') {\n \t\tret = report(options, &tag->object, FSCK_MSG_BAD_OBJECT_SHA1, \"invalid 'object' line format - bad sha1\");\n \t\tif (ret)\n \t\t\tgoto done;\n \t}\n-\tbuffer += 41;\n+\tbuffer = p + 1;\n \n \tif (!skip_prefix(buffer, \"type \", &buffer)) {\n \t\tret = report(options, &tag->object, FSCK_MSG_MISSING_TYPE_ENTRY, \"invalid format - expected 'type' line\");\n"},{"id":"345558","messageId":"20180423233951.276447-25-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 24/41] diff: specify abbreviation size in terms of the_hash_algo","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:34Z","receivedAt":"2018-04-23T23:41:55Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Instead of using hard-coded 40 constants, refer to the_hash_algo for the\ncurrent hash size.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n diff.c | 18 ++++++++++++------\n 1 file changed, 12 insertions(+), 6 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 314c57e3c0..b1666b9b2d 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -3897,13 +3897,14 @@ static void fill_metainfo(struct strbuf *msg,\n \t\t*must_show_header = 0;\n \t}\n \tif (one && two && oidcmp(&one->oid, &two->oid)) {\n-\t\tint abbrev = o->flags.full_index ? 40 : DEFAULT_ABBREV;\n+\t\tconst unsigned hexsz = the_hash_algo->hexsz;\n+\t\tint abbrev = o->flags.full_index ? hexsz : DEFAULT_ABBREV;\n \n \t\tif (o->flags.binary) {\n \t\t\tmmfile_t mf;\n \t\t\tif ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) ||\n \t\t\t    (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))\n-\t\t\t\tabbrev = 40;\n+\t\t\t\tabbrev = hexsz;\n \t\t}\n \t\tstrbuf_addf(msg, \"%s%sindex %s..%s\", line_prefix, set,\n \t\t\t    diff_abbrev_oid(&one->oid, abbrev),\n@@ -4138,6 +4139,11 @@ void diff_setup_done(struct diff_options *options)\n \t\t\t      DIFF_FORMAT_NAME_STATUS |\n \t\t\t      DIFF_FORMAT_CHECKDIFF |\n \t\t\t      DIFF_FORMAT_NO_OUTPUT;\n+\t/*\n+\t * This must be signed because we're comparing against a potentially\n+\t * negative value.\n+\t */\n+\tconst int hexsz = the_hash_algo->hexsz;\n \n \tif (options->set_default)\n \t\toptions->set_default(options);\n@@ -4218,8 +4224,8 @@ void diff_setup_done(struct diff_options *options)\n \t\t\t */\n \t\t\tread_cache();\n \t}\n-\tif (40 < options->abbrev)\n-\t\toptions->abbrev = 40; /* full */\n+\tif (hexsz < options->abbrev)\n+\t\toptions->abbrev = hexsz; /* full */\n \n \t/*\n \t * It does not make sense to show the first hit we happened\n@@ -4797,8 +4803,8 @@ int diff_opt_parse(struct diff_options *options,\n \t\toptions->abbrev = strtoul(arg, NULL, 10);\n \t\tif (options->abbrev < MINIMUM_ABBREV)\n \t\t\toptions->abbrev = MINIMUM_ABBREV;\n-\t\telse if (40 < options->abbrev)\n-\t\t\toptions->abbrev = 40;\n+\t\telse if (the_hash_algo->hexsz < options->abbrev)\n+\t\t\toptions->abbrev = the_hash_algo->hexsz;\n \t}\n \telse if ((argcount = parse_long_opt(\"src-prefix\", av, &optarg))) {\n \t\toptions->a_prefix = optarg;\n"},{"id":"345559","messageId":"20180423233951.276447-20-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 19/41] commit: convert uses of get_sha1_hex to get_oid_hex","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:29Z","receivedAt":"2018-04-23T23:41:56Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n commit.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/commit.c b/commit.c\nindex ca474a7c11..9617f85caa 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -331,7 +331,7 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s\n \tif (tail <= bufptr + tree_entry_len + 1 || memcmp(bufptr, \"tree \", 5) ||\n \t\t\tbufptr[tree_entry_len] != '\\n')\n \t\treturn error(\"bogus commit object %s\", oid_to_hex(&item->object.oid));\n-\tif (get_sha1_hex(bufptr + 5, parent.hash) < 0)\n+\tif (get_oid_hex(bufptr + 5, &parent) < 0)\n \t\treturn error(\"bad tree pointer in commit %s\",\n \t\t\t     oid_to_hex(&item->object.oid));\n \titem->tree = lookup_tree(&parent);\n@@ -343,7 +343,7 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s\n \t\tstruct commit *new_parent;\n \n \t\tif (tail <= bufptr + parent_entry_len + 1 ||\n-\t\t    get_sha1_hex(bufptr + 7, parent.hash) ||\n+\t\t    get_oid_hex(bufptr + 7, &parent) ||\n \t\t    bufptr[parent_entry_len] != '\\n')\n \t\t\treturn error(\"bad parents in commit %s\", oid_to_hex(&item->object.oid));\n \t\tbufptr += parent_entry_len + 1;\n"},{"id":"345560","messageId":"20180423233951.276447-6-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 05/41] packfile: convert has_sha1_pack to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:15Z","receivedAt":"2018-04-23T23:42:00Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert this function to take a pointer to struct object_id and rename\nit has_object_pack for consistency with has_object_file.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/count-objects.c | 2 +-\n builtin/fsck.c          | 2 +-\n builtin/prune-packed.c  | 2 +-\n diff.c                  | 2 +-\n packfile.c              | 4 ++--\n packfile.h              | 2 +-\n revision.c              | 2 +-\n 7 files changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/count-objects.c b/builtin/count-objects.c\nindex b054713e1a..d51e2ce1ec 100644\n--- a/builtin/count-objects.c\n+++ b/builtin/count-objects.c\n@@ -66,7 +66,7 @@ static int count_loose(const struct object_id *oid, const char *path, void *data\n \telse {\n \t\tloose_size += on_disk_bytes(st);\n \t\tloose++;\n-\t\tif (verbose && has_sha1_pack(oid->hash))\n+\t\tif (verbose && has_object_pack(oid))\n \t\t\tpacked_loose++;\n \t}\n \treturn 0;\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 087360a675..3eb82ac44f 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -227,7 +227,7 @@ static void check_reachable_object(struct object *obj)\n \tif (!(obj->flags & HAS_OBJ)) {\n \t\tif (is_promisor_object(&obj->oid))\n \t\t\treturn;\n-\t\tif (has_sha1_pack(obj->oid.hash))\n+\t\tif (has_object_pack(&obj->oid))\n \t\t\treturn; /* it is in pack - forget about it */\n \t\tprintf(\"missing %s %s\\n\", printable_type(obj),\n \t\t\tdescribe_object(obj));\ndiff --git a/builtin/prune-packed.c b/builtin/prune-packed.c\nindex 419238171d..4ff525e50f 100644\n--- a/builtin/prune-packed.c\n+++ b/builtin/prune-packed.c\n@@ -25,7 +25,7 @@ static int prune_object(const struct object_id *oid, const char *path,\n {\n \tint *opts = data;\n \n-\tif (!has_sha1_pack(oid->hash))\n+\tif (!has_object_pack(oid))\n \t\treturn 0;\n \n \tif (*opts & PRUNE_PACKED_DRY_RUN)\ndiff --git a/diff.c b/diff.c\nindex 1289df4b1f..314c57e3c0 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -3472,7 +3472,7 @@ static int reuse_worktree_file(const char *name, const struct object_id *oid, in\n \t * objects however would tend to be slower as they need\n \t * to be individually opened and inflated.\n \t */\n-\tif (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(oid->hash))\n+\tif (!FAST_WORKING_DIRECTORY && !want_file && has_object_pack(oid))\n \t\treturn 0;\n \n \t/*\ndiff --git a/packfile.c b/packfile.c\nindex 5c219d0229..e65f943664 100644\n--- a/packfile.c\n+++ b/packfile.c\n@@ -1854,10 +1854,10 @@ int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack\n \treturn 0;\n }\n \n-int has_sha1_pack(const unsigned char *sha1)\n+int has_object_pack(const struct object_id *oid)\n {\n \tstruct pack_entry e;\n-\treturn find_pack_entry(the_repository, sha1, &e);\n+\treturn find_pack_entry(the_repository, oid->hash, &e);\n }\n \n int has_pack_index(const unsigned char *sha1)\ndiff --git a/packfile.h b/packfile.h\nindex a92c0b241c..14ca34bcbd 100644\n--- a/packfile.h\n+++ b/packfile.h\n@@ -136,7 +136,7 @@ extern const struct packed_git *has_packed_and_bad(const unsigned char *sha1);\n  */\n extern int find_pack_entry(struct repository *r, const unsigned char *sha1, struct pack_entry *e);\n \n-extern int has_sha1_pack(const unsigned char *sha1);\n+extern int has_object_pack(const struct object_id *oid);\n \n extern int has_pack_index(const unsigned char *sha1);\n \ndiff --git a/revision.c b/revision.c\nindex b42c836d7a..ce0e7b71f2 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -3086,7 +3086,7 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi\n {\n \tif (commit->object.flags & SHOWN)\n \t\treturn commit_ignore;\n-\tif (revs->unpacked && has_sha1_pack(commit->object.oid.hash))\n+\tif (revs->unpacked && has_object_pack(&commit->object.oid))\n \t\treturn commit_ignore;\n \tif (commit->object.flags & UNINTERESTING)\n \t\treturn commit_ignore;\n"},{"id":"345561","messageId":"20180423233951.276447-19-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 18/41] index-pack: abstract away hash function constant","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:28Z","receivedAt":"2018-04-23T23:42:01Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"The code for reading certain pack v2 offsets had a hard-coded 5\nrepresenting the number of uint32_t words that we needed to skip over.\nSpecify this value in terms of a value from the_hash_algo.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/index-pack.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex d81473e722..c1f94a7da6 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -1543,12 +1543,13 @@ static void read_v2_anomalous_offsets(struct packed_git *p,\n {\n \tconst uint32_t *idx1, *idx2;\n \tuint32_t i;\n+\tconst uint32_t hashwords = the_hash_algo->rawsz / sizeof(uint32_t);\n \n \t/* The address of the 4-byte offset table */\n \tidx1 = (((const uint32_t *)p->index_data)\n \t\t+ 2 /* 8-byte header */\n \t\t+ 256 /* fan out */\n-\t\t+ 5 * p->num_objects /* 20-byte SHA-1 table */\n+\t\t+ hashwords * p->num_objects /* object ID table */\n \t\t+ p->num_objects /* CRC32 table */\n \t\t);\n \n"},{"id":"345562","messageId":"20180423233951.276447-16-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 15/41] split-index: convert struct split_index to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:25Z","receivedAt":"2018-04-23T23:42:04Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert the base_sha1 member of struct split_index to use struct\nobject_id and rename it base_oid.  Include cache.h to make the structure\nvisible.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/rev-parse.c              |  4 ++--\n read-cache.c                     | 22 +++++++++++-----------\n split-index.c                    | 10 +++++-----\n split-index.h                    |  4 +++-\n t/helper/test-dump-split-index.c |  2 +-\n 5 files changed, 22 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 36b2087782..55c0b90441 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -887,8 +887,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tif (read_cache() < 0)\n \t\t\t\t\tdie(_(\"Could not read the index\"));\n \t\t\t\tif (the_index.split_index) {\n-\t\t\t\t\tconst unsigned char *sha1 = the_index.split_index->base_sha1;\n-\t\t\t\t\tconst char *path = git_path(\"sharedindex.%s\", sha1_to_hex(sha1));\n+\t\t\t\t\tconst struct object_id *oid = &the_index.split_index->base_oid;\n+\t\t\t\t\tconst char *path = git_path(\"sharedindex.%s\", oid_to_hex(oid));\n \t\t\t\t\tstrbuf_reset(&buf);\n \t\t\t\t\tputs(relative_path(path, prefix, &buf));\n \t\t\t\t}\ndiff --git a/read-cache.c b/read-cache.c\nindex 10f1c6bb8a..f47666b975 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1878,7 +1878,7 @@ int read_index_from(struct index_state *istate, const char *path,\n \tuint64_t start = getnanotime();\n \tstruct split_index *split_index;\n \tint ret;\n-\tchar *base_sha1_hex;\n+\tchar *base_oid_hex;\n \tchar *base_path;\n \n \t/* istate->initialized covers both .git/index and .git/sharedindex.xxx */\n@@ -1889,7 +1889,7 @@ int read_index_from(struct index_state *istate, const char *path,\n \ttrace_performance_since(start, \"read cache %s\", path);\n \n \tsplit_index = istate->split_index;\n-\tif (!split_index || is_null_sha1(split_index->base_sha1)) {\n+\tif (!split_index || is_null_oid(&split_index->base_oid)) {\n \t\tpost_read_index_from(istate);\n \t\treturn ret;\n \t}\n@@ -1899,12 +1899,12 @@ int read_index_from(struct index_state *istate, const char *path,\n \telse\n \t\tsplit_index->base = xcalloc(1, sizeof(*split_index->base));\n \n-\tbase_sha1_hex = sha1_to_hex(split_index->base_sha1);\n-\tbase_path = xstrfmt(\"%s/sharedindex.%s\", gitdir, base_sha1_hex);\n+\tbase_oid_hex = oid_to_hex(&split_index->base_oid);\n+\tbase_path = xstrfmt(\"%s/sharedindex.%s\", gitdir, base_oid_hex);\n \tret = do_read_index(split_index->base, base_path, 1);\n-\tif (hashcmp(split_index->base_sha1, split_index->base->sha1))\n+\tif (hashcmp(split_index->base_oid.hash, split_index->base->sha1))\n \t\tdie(\"broken index, expect %s in %s, got %s\",\n-\t\t    base_sha1_hex, base_path,\n+\t\t    base_oid_hex, base_path,\n \t\t    sha1_to_hex(split_index->base->sha1));\n \n \tfreshen_shared_index(base_path, 0);\n@@ -2499,7 +2499,7 @@ static int write_shared_index(struct index_state *istate,\n \tret = rename_tempfile(temp,\n \t\t\t      git_path(\"sharedindex.%s\", sha1_to_hex(si->base->sha1)));\n \tif (!ret) {\n-\t\thashcpy(si->base_sha1, si->base->sha1);\n+\t\thashcpy(si->base_oid.hash, si->base->sha1);\n \t\tclean_shared_index_files(sha1_to_hex(si->base->sha1));\n \t}\n \n@@ -2554,13 +2554,13 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,\n \tif (!si || alternate_index_output ||\n \t    (istate->cache_changed & ~EXTMASK)) {\n \t\tif (si)\n-\t\t\thashclr(si->base_sha1);\n+\t\t\toidclr(&si->base_oid);\n \t\tret = do_write_locked_index(istate, lock, flags);\n \t\tgoto out;\n \t}\n \n \tif (getenv(\"GIT_TEST_SPLIT_INDEX\")) {\n-\t\tint v = si->base_sha1[0];\n+\t\tint v = si->base_oid.hash[0];\n \t\tif ((v & 15) < 6)\n \t\t\tistate->cache_changed |= SPLIT_INDEX_ORDERED;\n \t}\n@@ -2575,7 +2575,7 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,\n \n \t\ttemp = mks_tempfile(git_path(\"sharedindex_XXXXXX\"));\n \t\tif (!temp) {\n-\t\t\thashclr(si->base_sha1);\n+\t\t\toidclr(&si->base_oid);\n \t\t\tret = do_write_locked_index(istate, lock, flags);\n \t\t\tgoto out;\n \t\t}\n@@ -2595,7 +2595,7 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,\n \t/* Freshen the shared index only if the split-index was written */\n \tif (!ret && !new_shared_index) {\n \t\tconst char *shared_index = git_path(\"sharedindex.%s\",\n-\t\t\t\t\t\t    sha1_to_hex(si->base_sha1));\n+\t\t\t\t\t\t    oid_to_hex(&si->base_oid));\n \t\tfreshen_shared_index(shared_index, 1);\n \t}\n \ndiff --git a/split-index.c b/split-index.c\nindex 3eb8ff1b43..660c75f31f 100644\n--- a/split-index.c\n+++ b/split-index.c\n@@ -18,12 +18,12 @@ int read_link_extension(struct index_state *istate,\n \tstruct split_index *si;\n \tint ret;\n \n-\tif (sz < 20)\n+\tif (sz < the_hash_algo->rawsz)\n \t\treturn error(\"corrupt link extension (too short)\");\n \tsi = init_split_index(istate);\n-\thashcpy(si->base_sha1, data);\n-\tdata += 20;\n-\tsz -= 20;\n+\thashcpy(si->base_oid.hash, data);\n+\tdata += the_hash_algo->rawsz;\n+\tsz -= the_hash_algo->rawsz;\n \tif (!sz)\n \t\treturn 0;\n \tsi->delete_bitmap = ewah_new();\n@@ -45,7 +45,7 @@ int write_link_extension(struct strbuf *sb,\n \t\t\t struct index_state *istate)\n {\n \tstruct split_index *si = istate->split_index;\n-\tstrbuf_add(sb, si->base_sha1, 20);\n+\tstrbuf_add(sb, si->base_oid.hash, the_hash_algo->rawsz);\n \tif (!si->delete_bitmap && !si->replace_bitmap)\n \t\treturn 0;\n \tewah_serialize_strbuf(si->delete_bitmap, sb);\ndiff --git a/split-index.h b/split-index.h\nindex 43d66826eb..7a435ca2c9 100644\n--- a/split-index.h\n+++ b/split-index.h\n@@ -1,12 +1,14 @@\n #ifndef SPLIT_INDEX_H\n #define SPLIT_INDEX_H\n \n+#include \"cache.h\"\n+\n struct index_state;\n struct strbuf;\n struct ewah_bitmap;\n \n struct split_index {\n-\tunsigned char base_sha1[20];\n+\tstruct object_id base_oid;\n \tstruct index_state *base;\n \tstruct ewah_bitmap *delete_bitmap;\n \tstruct ewah_bitmap *replace_bitmap;\ndiff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c\nindex 4e2fdb5e30..754e9bb624 100644\n--- a/t/helper/test-dump-split-index.c\n+++ b/t/helper/test-dump-split-index.c\n@@ -20,7 +20,7 @@ int cmd__dump_split_index(int ac, const char **av)\n \t\tprintf(\"not a split index\\n\");\n \t\treturn 0;\n \t}\n-\tprintf(\"base %s\\n\", sha1_to_hex(si->base_sha1));\n+\tprintf(\"base %s\\n\", oid_to_hex(&si->base_oid));\n \tfor (i = 0; i < the_index.cache_nr; i++) {\n \t\tstruct cache_entry *ce = the_index.cache[i];\n \t\tprintf(\"%06o %s %d\\t%s\\n\", ce->ce_mode,\n"},{"id":"345563","messageId":"20180423233951.276447-15-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 14/41] submodule-config: convert structures to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:24Z","receivedAt":"2018-04-23T23:42:07Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Convert struct submodule and struct parse_config_parameter to use struct\nobject_id.  Adjust the functions which take members of these structures\nas arguments to also use struct object_id.  Include cache.h into\nsubmodule-config.h to make struct object_id visible.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n submodule-config.c | 66 +++++++++++++++++++++++-----------------------\n submodule-config.h |  7 ++---\n 2 files changed, 37 insertions(+), 36 deletions(-)\n\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 3f2075764f..5537c88727 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -44,7 +44,7 @@ static int config_path_cmp(const void *unused_cmp_data,\n \tconst struct submodule_entry *b = entry_or_key;\n \n \treturn strcmp(a->config->path, b->config->path) ||\n-\t       hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);\n+\t       oidcmp(&a->config->gitmodules_oid, &b->config->gitmodules_oid);\n }\n \n static int config_name_cmp(const void *unused_cmp_data,\n@@ -56,7 +56,7 @@ static int config_name_cmp(const void *unused_cmp_data,\n \tconst struct submodule_entry *b = entry_or_key;\n \n \treturn strcmp(a->config->name, b->config->name) ||\n-\t       hashcmp(a->config->gitmodules_sha1, b->config->gitmodules_sha1);\n+\t       oidcmp(&a->config->gitmodules_oid, &b->config->gitmodules_oid);\n }\n \n static struct submodule_cache *submodule_cache_alloc(void)\n@@ -109,17 +109,17 @@ void submodule_cache_free(struct submodule_cache *cache)\n \tfree(cache);\n }\n \n-static unsigned int hash_sha1_string(const unsigned char *sha1,\n-\t\t\t\t     const char *string)\n+static unsigned int hash_oid_string(const struct object_id *oid,\n+\t\t\t\t    const char *string)\n {\n-\treturn memhash(sha1, 20) + strhash(string);\n+\treturn memhash(oid->hash, the_hash_algo->rawsz) + strhash(string);\n }\n \n static void cache_put_path(struct submodule_cache *cache,\n \t\t\t   struct submodule *submodule)\n {\n-\tunsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,\n-\t\t\t\t\t     submodule->path);\n+\tunsigned int hash = hash_oid_string(&submodule->gitmodules_oid,\n+\t\t\t\t\t    submodule->path);\n \tstruct submodule_entry *e = xmalloc(sizeof(*e));\n \thashmap_entry_init(e, hash);\n \te->config = submodule;\n@@ -129,8 +129,8 @@ static void cache_put_path(struct submodule_cache *cache,\n static void cache_remove_path(struct submodule_cache *cache,\n \t\t\t      struct submodule *submodule)\n {\n-\tunsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,\n-\t\t\t\t\t     submodule->path);\n+\tunsigned int hash = hash_oid_string(&submodule->gitmodules_oid,\n+\t\t\t\t\t    submodule->path);\n \tstruct submodule_entry e;\n \tstruct submodule_entry *removed;\n \thashmap_entry_init(&e, hash);\n@@ -142,8 +142,8 @@ static void cache_remove_path(struct submodule_cache *cache,\n static void cache_add(struct submodule_cache *cache,\n \t\t      struct submodule *submodule)\n {\n-\tunsigned int hash = hash_sha1_string(submodule->gitmodules_sha1,\n-\t\t\t\t\t     submodule->name);\n+\tunsigned int hash = hash_oid_string(&submodule->gitmodules_oid,\n+\t\t\t\t\t    submodule->name);\n \tstruct submodule_entry *e = xmalloc(sizeof(*e));\n \thashmap_entry_init(e, hash);\n \te->config = submodule;\n@@ -151,14 +151,14 @@ static void cache_add(struct submodule_cache *cache,\n }\n \n static const struct submodule *cache_lookup_path(struct submodule_cache *cache,\n-\t\tconst unsigned char *gitmodules_sha1, const char *path)\n+\t\tconst struct object_id *gitmodules_oid, const char *path)\n {\n \tstruct submodule_entry *entry;\n-\tunsigned int hash = hash_sha1_string(gitmodules_sha1, path);\n+\tunsigned int hash = hash_oid_string(gitmodules_oid, path);\n \tstruct submodule_entry key;\n \tstruct submodule key_config;\n \n-\thashcpy(key_config.gitmodules_sha1, gitmodules_sha1);\n+\toidcpy(&key_config.gitmodules_oid, gitmodules_oid);\n \tkey_config.path = path;\n \n \thashmap_entry_init(&key, hash);\n@@ -171,14 +171,14 @@ static const struct submodule *cache_lookup_path(struct submodule_cache *cache,\n }\n \n static struct submodule *cache_lookup_name(struct submodule_cache *cache,\n-\t\tconst unsigned char *gitmodules_sha1, const char *name)\n+\t\tconst struct object_id *gitmodules_oid, const char *name)\n {\n \tstruct submodule_entry *entry;\n-\tunsigned int hash = hash_sha1_string(gitmodules_sha1, name);\n+\tunsigned int hash = hash_oid_string(gitmodules_oid, name);\n \tstruct submodule_entry key;\n \tstruct submodule key_config;\n \n-\thashcpy(key_config.gitmodules_sha1, gitmodules_sha1);\n+\toidcpy(&key_config.gitmodules_oid, gitmodules_oid);\n \tkey_config.name = name;\n \n \thashmap_entry_init(&key, hash);\n@@ -207,12 +207,12 @@ static int name_and_item_from_var(const char *var, struct strbuf *name,\n }\n \n static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,\n-\t\tconst unsigned char *gitmodules_sha1, const char *name)\n+\t\tconst struct object_id *gitmodules_oid, const char *name)\n {\n \tstruct submodule *submodule;\n \tstruct strbuf name_buf = STRBUF_INIT;\n \n-\tsubmodule = cache_lookup_name(cache, gitmodules_sha1, name);\n+\tsubmodule = cache_lookup_name(cache, gitmodules_oid, name);\n \tif (submodule)\n \t\treturn submodule;\n \n@@ -230,7 +230,7 @@ static struct submodule *lookup_or_create_by_name(struct submodule_cache *cache,\n \tsubmodule->branch = NULL;\n \tsubmodule->recommend_shallow = -1;\n \n-\thashcpy(submodule->gitmodules_sha1, gitmodules_sha1);\n+\toidcpy(&submodule->gitmodules_oid, gitmodules_oid);\n \n \tcache_add(cache, submodule);\n \n@@ -341,12 +341,12 @@ int parse_push_recurse_submodules_arg(const char *opt, const char *arg)\n \treturn parse_push_recurse(opt, arg, 1);\n }\n \n-static void warn_multiple_config(const unsigned char *treeish_name,\n+static void warn_multiple_config(const struct object_id *treeish_name,\n \t\t\t\t const char *name, const char *option)\n {\n \tconst char *commit_string = \"WORKTREE\";\n \tif (treeish_name)\n-\t\tcommit_string = sha1_to_hex(treeish_name);\n+\t\tcommit_string = oid_to_hex(treeish_name);\n \twarning(\"%s:.gitmodules, multiple configurations found for \"\n \t\t\t\"'submodule.%s.%s'. Skipping second one!\",\n \t\t\tcommit_string, name, option);\n@@ -354,8 +354,8 @@ static void warn_multiple_config(const unsigned char *treeish_name,\n \n struct parse_config_parameter {\n \tstruct submodule_cache *cache;\n-\tconst unsigned char *treeish_name;\n-\tconst unsigned char *gitmodules_sha1;\n+\tconst struct object_id *treeish_name;\n+\tconst struct object_id *gitmodules_oid;\n \tint overwrite;\n };\n \n@@ -371,7 +371,7 @@ static int parse_config(const char *var, const char *value, void *data)\n \t\treturn 0;\n \n \tsubmodule = lookup_or_create_by_name(me->cache,\n-\t\t\t\t\t     me->gitmodules_sha1,\n+\t\t\t\t\t     me->gitmodules_oid,\n \t\t\t\t\t     name.buf);\n \n \tif (!strcmp(item.buf, \"path\")) {\n@@ -389,7 +389,7 @@ static int parse_config(const char *var, const char *value, void *data)\n \t\t}\n \t} else if (!strcmp(item.buf, \"fetchrecursesubmodules\")) {\n \t\t/* when parsing worktree configurations we can die early */\n-\t\tint die_on_error = is_null_sha1(me->gitmodules_sha1);\n+\t\tint die_on_error = is_null_oid(me->gitmodules_oid);\n \t\tif (!me->overwrite &&\n \t\t    submodule->fetch_recurse != RECURSE_SUBMODULES_NONE)\n \t\t\twarn_multiple_config(me->treeish_name, submodule->name,\n@@ -511,10 +511,10 @@ static const struct submodule *config_from(struct submodule_cache *cache,\n \n \tswitch (lookup_type) {\n \tcase lookup_name:\n-\t\tsubmodule = cache_lookup_name(cache, oid.hash, key);\n+\t\tsubmodule = cache_lookup_name(cache, &oid, key);\n \t\tbreak;\n \tcase lookup_path:\n-\t\tsubmodule = cache_lookup_path(cache, oid.hash, key);\n+\t\tsubmodule = cache_lookup_path(cache, &oid, key);\n \t\tbreak;\n \t}\n \tif (submodule)\n@@ -526,8 +526,8 @@ static const struct submodule *config_from(struct submodule_cache *cache,\n \n \t/* fill the submodule config into the cache */\n \tparameter.cache = cache;\n-\tparameter.treeish_name = treeish_name->hash;\n-\tparameter.gitmodules_sha1 = oid.hash;\n+\tparameter.treeish_name = treeish_name;\n+\tparameter.gitmodules_oid = &oid;\n \tparameter.overwrite = 0;\n \tgit_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,\n \t\t\tconfig, config_size, &parameter);\n@@ -536,9 +536,9 @@ static const struct submodule *config_from(struct submodule_cache *cache,\n \n \tswitch (lookup_type) {\n \tcase lookup_name:\n-\t\treturn cache_lookup_name(cache, oid.hash, key);\n+\t\treturn cache_lookup_name(cache, &oid, key);\n \tcase lookup_path:\n-\t\treturn cache_lookup_path(cache, oid.hash, key);\n+\t\treturn cache_lookup_path(cache, &oid, key);\n \tdefault:\n \t\treturn NULL;\n \t}\n@@ -567,7 +567,7 @@ static int gitmodules_cb(const char *var, const char *value, void *data)\n \n \tparameter.cache = repo->submodule_cache;\n \tparameter.treeish_name = NULL;\n-\tparameter.gitmodules_sha1 = null_sha1;\n+\tparameter.gitmodules_oid = &null_oid;\n \tparameter.overwrite = 1;\n \n \treturn parse_config(var, value, &parameter);\ndiff --git a/submodule-config.h b/submodule-config.h\nindex a5503a5d17..11729fbc74 100644\n--- a/submodule-config.h\n+++ b/submodule-config.h\n@@ -1,6 +1,7 @@\n #ifndef SUBMODULE_CONFIG_CACHE_H\n #define SUBMODULE_CONFIG_CACHE_H\n \n+#include \"cache.h\"\n #include \"hashmap.h\"\n #include \"submodule.h\"\n #include \"strbuf.h\"\n@@ -17,13 +18,13 @@ struct submodule {\n \tconst char *ignore;\n \tconst char *branch;\n \tstruct submodule_update_strategy update_strategy;\n-\t/* the sha1 blob id of the responsible .gitmodules file */\n-\tunsigned char gitmodules_sha1[20];\n+\t/* the object id of the responsible .gitmodules file */\n+\tstruct object_id gitmodules_oid;\n \tint recommend_shallow;\n };\n \n #define SUBMODULE_INIT { NULL, NULL, NULL, RECURSE_SUBMODULES_NONE, \\\n-\tNULL, NULL, SUBMODULE_UPDATE_STRATEGY_INIT, {0}, -1 };\n+\tNULL, NULL, SUBMODULE_UPDATE_STRATEGY_INIT, { { 0 } }, -1 };\n \n struct submodule_cache;\n struct repository;\n"},{"id":"345564","messageId":"20180423233951.276447-13-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 12/41] tree-walk: convert get_tree_entry_follow_symlinks to object_id","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:22Z","receivedAt":"2018-04-23T23:42:10Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Since the only caller of this function already uses struct object_id,\nupdate get_tree_entry_follow_symlinks to use it in parameters and\ninternally.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n sha1_name.c |  4 ++--\n tree-walk.c | 16 ++++++++--------\n tree-walk.h |  2 +-\n 3 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 7043652a24..7c2d08a202 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -1685,8 +1685,8 @@ static int get_oid_with_context_1(const char *name,\n \t\t\tif (new_filename)\n \t\t\t\tfilename = new_filename;\n \t\t\tif (flags & GET_OID_FOLLOW_SYMLINKS) {\n-\t\t\t\tret = get_tree_entry_follow_symlinks(tree_oid.hash,\n-\t\t\t\t\tfilename, oid->hash, &oc->symlink_path,\n+\t\t\t\tret = get_tree_entry_follow_symlinks(&tree_oid,\n+\t\t\t\t\tfilename, oid, &oc->symlink_path,\n \t\t\t\t\t&oc->mode);\n \t\t\t} else {\n \t\t\t\tret = get_tree_entry(&tree_oid, filename, oid,\ndiff --git a/tree-walk.c b/tree-walk.c\nindex 27797c5406..8f5090862b 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -488,7 +488,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)\n struct dir_state {\n \tvoid *tree;\n \tunsigned long size;\n-\tunsigned char sha1[20];\n+\tstruct object_id oid;\n };\n \n static int find_tree_entry(struct tree_desc *t, const char *name, struct object_id *result, unsigned *mode)\n@@ -576,7 +576,7 @@ int get_tree_entry(const struct object_id *tree_oid, const char *name, struct ob\n  * See the code for enum follow_symlink_result for a description of\n  * the return values.\n  */\n-enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_sha1, const char *name, unsigned char *result, struct strbuf *result_path, unsigned *mode)\n+enum follow_symlinks_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode)\n {\n \tint retval = MISSING_OBJECT;\n \tstruct dir_state *parents = NULL;\n@@ -589,7 +589,7 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s\n \n \tinit_tree_desc(&t, NULL, 0UL);\n \tstrbuf_addstr(&namebuf, name);\n-\thashcpy(current_tree_oid.hash, tree_sha1);\n+\toidcpy(&current_tree_oid, tree_oid);\n \n \twhile (1) {\n \t\tint find_result;\n@@ -609,11 +609,11 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s\n \t\t\tALLOC_GROW(parents, parents_nr + 1, parents_alloc);\n \t\t\tparents[parents_nr].tree = tree;\n \t\t\tparents[parents_nr].size = size;\n-\t\t\thashcpy(parents[parents_nr].sha1, root.hash);\n+\t\t\toidcpy(&parents[parents_nr].oid, &root);\n \t\t\tparents_nr++;\n \n \t\t\tif (namebuf.buf[0] == '\\0') {\n-\t\t\t\thashcpy(result, root.hash);\n+\t\t\t\toidcpy(result, &root);\n \t\t\t\tretval = FOUND;\n \t\t\t\tgoto done;\n \t\t\t}\n@@ -663,7 +663,7 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s\n \n \t\t/* We could end up here via a symlink to dir/.. */\n \t\tif (namebuf.buf[0] == '\\0') {\n-\t\t\thashcpy(result, parents[parents_nr - 1].sha1);\n+\t\t\toidcpy(result, &parents[parents_nr - 1].oid);\n \t\t\tretval = FOUND;\n \t\t\tgoto done;\n \t\t}\n@@ -677,7 +677,7 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s\n \n \t\tif (S_ISDIR(*mode)) {\n \t\t\tif (!remainder) {\n-\t\t\t\thashcpy(result, current_tree_oid.hash);\n+\t\t\t\toidcpy(result, &current_tree_oid);\n \t\t\t\tretval = FOUND;\n \t\t\t\tgoto done;\n \t\t\t}\n@@ -687,7 +687,7 @@ enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_s\n \t\t\t\t      1 + first_slash - namebuf.buf);\n \t\t} else if (S_ISREG(*mode)) {\n \t\t\tif (!remainder) {\n-\t\t\t\thashcpy(result, current_tree_oid.hash);\n+\t\t\t\toidcpy(result, &current_tree_oid);\n \t\t\t\tretval = FOUND;\n \t\t\t} else {\n \t\t\t\tretval = NOT_DIR;\ndiff --git a/tree-walk.h b/tree-walk.h\nindex 4617deeb0e..805f58f00f 100644\n--- a/tree-walk.h\n+++ b/tree-walk.h\n@@ -64,7 +64,7 @@ enum follow_symlinks_result {\n \t\t       */\n };\n \n-enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_sha1, const char *name, unsigned char *result, struct strbuf *result_path, unsigned *mode);\n+enum follow_symlinks_result get_tree_entry_follow_symlinks(struct object_id *tree_oid, const char *name, struct object_id *result, struct strbuf *result_path, unsigned *mode);\n \n struct traverse_info {\n \tconst char *traverse_path;\n"},{"id":"345565","messageId":"20180423233951.276447-12-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 11/41] tree-walk: avoid hard-coded 20 constant","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:21Z","receivedAt":"2018-04-23T23:42:11Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Use the_hash_algo to look up the length of our current hash instead of\nhard-coding the value 20.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n tree-walk.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/tree-walk.c b/tree-walk.c\nindex e11b3063af..27797c5406 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -105,7 +105,7 @@ static void entry_extract(struct tree_desc *t, struct name_entry *a)\n static int update_tree_entry_internal(struct tree_desc *desc, struct strbuf *err)\n {\n \tconst void *buf = desc->buffer;\n-\tconst unsigned char *end = desc->entry.oid->hash + 20;\n+\tconst unsigned char *end = desc->entry.oid->hash + the_hash_algo->rawsz;\n \tunsigned long size = desc->size;\n \tunsigned long len = end - (const unsigned char *)buf;\n \n"},{"id":"345566","messageId":"20180423233951.276447-11-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 10/41] pack-redundant: abstract away hash algorithm","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:20Z","receivedAt":"2018-04-23T23:42:18Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Instead of using hard-coded instances of the constant 20, use\nthe_hash_algo to look up the correct constant.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/pack-redundant.c | 12 +++++++-----\n 1 file changed, 7 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c\nindex 354478a127..0fe1ff3cb7 100644\n--- a/builtin/pack-redundant.c\n+++ b/builtin/pack-redundant.c\n@@ -252,13 +252,14 @@ static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)\n \tunsigned long p1_off = 0, p2_off = 0, p1_step, p2_step;\n \tconst unsigned char *p1_base, *p2_base;\n \tstruct llist_item *p1_hint = NULL, *p2_hint = NULL;\n+\tconst unsigned int hashsz = the_hash_algo->rawsz;\n \n \tp1_base = p1->pack->index_data;\n \tp2_base = p2->pack->index_data;\n \tp1_base += 256 * 4 + ((p1->pack->index_version < 2) ? 4 : 8);\n \tp2_base += 256 * 4 + ((p2->pack->index_version < 2) ? 4 : 8);\n-\tp1_step = (p1->pack->index_version < 2) ? 24 : 20;\n-\tp2_step = (p2->pack->index_version < 2) ? 24 : 20;\n+\tp1_step = hashsz + ((p1->pack->index_version < 2) ? 4 : 0);\n+\tp2_step = hashsz + ((p2->pack->index_version < 2) ? 4 : 0);\n \n \twhile (p1_off < p1->pack->num_objects * p1_step &&\n \t       p2_off < p2->pack->num_objects * p2_step)\n@@ -359,13 +360,14 @@ static size_t sizeof_union(struct packed_git *p1, struct packed_git *p2)\n \tsize_t ret = 0;\n \tunsigned long p1_off = 0, p2_off = 0, p1_step, p2_step;\n \tconst unsigned char *p1_base, *p2_base;\n+\tconst unsigned int hashsz = the_hash_algo->rawsz;\n \n \tp1_base = p1->index_data;\n \tp2_base = p2->index_data;\n \tp1_base += 256 * 4 + ((p1->index_version < 2) ? 4 : 8);\n \tp2_base += 256 * 4 + ((p2->index_version < 2) ? 4 : 8);\n-\tp1_step = (p1->index_version < 2) ? 24 : 20;\n-\tp2_step = (p2->index_version < 2) ? 24 : 20;\n+\tp1_step = hashsz + ((p1->index_version < 2) ? 4 : 0);\n+\tp2_step = hashsz + ((p2->index_version < 2) ? 4 : 0);\n \n \twhile (p1_off < p1->num_objects * p1_step &&\n \t       p2_off < p2->num_objects * p2_step)\n@@ -558,7 +560,7 @@ static struct pack_list * add_pack(struct packed_git *p)\n \n \tbase = p->index_data;\n \tbase += 256 * 4 + ((p->index_version < 2) ? 4 : 8);\n-\tstep = (p->index_version < 2) ? 24 : 20;\n+\tstep = the_hash_algo->rawsz + ((p->index_version < 2) ? 4 : 0);\n \twhile (off < p->num_objects * step) {\n \t\tllist_insert_back(l.all_objects, base + off);\n \t\toff += step;\n"},{"id":"345567","messageId":"20180423233951.276447-9-sandals@crustytoothpaste.net","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"[PATCH 08/41] packfile: abstract away hash constant values","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-23T23:39:18Z","receivedAt":"2018-04-23T23:42:22Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"There are several instances of the constant 20 and 20-based values in\nthe packfile code.  Abstract away dependence on SHA-1 by using the\nvalues from the_hash_algo instead.\n\nUse unsigned values for temporary constants to provide the compiler with\nmore information about what kinds of values it should expect.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n packfile.c | 66 ++++++++++++++++++++++++++++++------------------------\n 1 file changed, 37 insertions(+), 29 deletions(-)\n\ndiff --git a/packfile.c b/packfile.c\nindex 84acd405e0..b7bc4eab17 100644\n--- a/packfile.c\n+++ b/packfile.c\n@@ -84,6 +84,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)\n \tuint32_t version, nr, i, *index;\n \tint fd = git_open(path);\n \tstruct stat st;\n+\tconst unsigned int hashsz = the_hash_algo->rawsz;\n \n \tif (fd < 0)\n \t\treturn -1;\n@@ -92,7 +93,7 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)\n \t\treturn -1;\n \t}\n \tidx_size = xsize_t(st.st_size);\n-\tif (idx_size < 4 * 256 + 20 + 20) {\n+\tif (idx_size < 4 * 256 + hashsz + hashsz) {\n \t\tclose(fd);\n \t\treturn error(\"index file %s is too small\", path);\n \t}\n@@ -129,11 +130,11 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)\n \t\t/*\n \t\t * Total size:\n \t\t *  - 256 index entries 4 bytes each\n-\t\t *  - 24-byte entries * nr (20-byte sha1 + 4-byte offset)\n-\t\t *  - 20-byte SHA1 of the packfile\n-\t\t *  - 20-byte SHA1 file checksum\n+\t\t *  - 24-byte entries * nr (object ID + 4-byte offset)\n+\t\t *  - hash of the packfile\n+\t\t *  - file checksum\n \t\t */\n-\t\tif (idx_size != 4*256 + nr * 24 + 20 + 20) {\n+\t\tif (idx_size != 4*256 + nr * (hashsz + 4) + hashsz + hashsz) {\n \t\t\tmunmap(idx_map, idx_size);\n \t\t\treturn error(\"wrong index v1 file size in %s\", path);\n \t\t}\n@@ -142,16 +143,16 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)\n \t\t * Minimum size:\n \t\t *  - 8 bytes of header\n \t\t *  - 256 index entries 4 bytes each\n-\t\t *  - 20-byte sha1 entry * nr\n+\t\t *  - object ID entry * nr\n \t\t *  - 4-byte crc entry * nr\n \t\t *  - 4-byte offset entry * nr\n-\t\t *  - 20-byte SHA1 of the packfile\n-\t\t *  - 20-byte SHA1 file checksum\n+\t\t *  - hash of the packfile\n+\t\t *  - file checksum\n \t\t * And after the 4-byte offset table might be a\n \t\t * variable sized table containing 8-byte entries\n \t\t * for offsets larger than 2^31.\n \t\t */\n-\t\tunsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;\n+\t\tunsigned long min_size = 8 + 4*256 + nr*(hashsz + 4 + 4) + hashsz + hashsz;\n \t\tunsigned long max_size = min_size;\n \t\tif (nr)\n \t\t\tmax_size += (nr - 1)*8;\n@@ -444,10 +445,11 @@ static int open_packed_git_1(struct packed_git *p)\n {\n \tstruct stat st;\n \tstruct pack_header hdr;\n-\tunsigned char sha1[20];\n-\tunsigned char *idx_sha1;\n+\tunsigned char hash[GIT_MAX_RAWSZ];\n+\tunsigned char *idx_hash;\n \tlong fd_flag;\n \tssize_t read_result;\n+\tconst unsigned hashsz = the_hash_algo->rawsz;\n \n \tif (!p->index_data && open_pack_index(p))\n \t\treturn error(\"packfile %s index unavailable\", p->pack_name);\n@@ -507,15 +509,15 @@ static int open_packed_git_1(struct packed_git *p)\n \t\t\t     \" while index indicates %\"PRIu32\" objects\",\n \t\t\t     p->pack_name, ntohl(hdr.hdr_entries),\n \t\t\t     p->num_objects);\n-\tif (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)\n+\tif (lseek(p->pack_fd, p->pack_size - hashsz, SEEK_SET) == -1)\n \t\treturn error(\"end of packfile %s is unavailable\", p->pack_name);\n-\tread_result = read_in_full(p->pack_fd, sha1, sizeof(sha1));\n+\tread_result = read_in_full(p->pack_fd, hash, hashsz);\n \tif (read_result < 0)\n \t\treturn error_errno(\"error reading from %s\", p->pack_name);\n-\tif (read_result != sizeof(sha1))\n+\tif (read_result != hashsz)\n \t\treturn error(\"packfile %s signature is unavailable\", p->pack_name);\n-\tidx_sha1 = ((unsigned char *)p->index_data) + p->index_size - 40;\n-\tif (hashcmp(sha1, idx_sha1))\n+\tidx_hash = ((unsigned char *)p->index_data) + p->index_size - hashsz * 2;\n+\tif (hashcmp(hash, idx_hash))\n \t\treturn error(\"packfile %s does not match index\", p->pack_name);\n \treturn 0;\n }\n@@ -530,7 +532,7 @@ static int open_packed_git(struct packed_git *p)\n \n static int in_window(struct pack_window *win, off_t offset)\n {\n-\t/* We must promise at least 20 bytes (one hash) after the\n+\t/* We must promise at least one full hash after the\n \t * offset is available from this window, otherwise the offset\n \t * is not actually in this window and a different window (which\n \t * has that one hash excess) must be used.  This is to support\n@@ -538,7 +540,7 @@ static int in_window(struct pack_window *win, off_t offset)\n \t */\n \toff_t win_off = win->offset;\n \treturn win_off <= offset\n-\t\t&& (offset + 20) <= (win_off + win->len);\n+\t\t&& (offset + the_hash_algo->rawsz) <= (win_off + win->len);\n }\n \n unsigned char *use_pack(struct packed_git *p,\n@@ -555,7 +557,7 @@ unsigned char *use_pack(struct packed_git *p,\n \t */\n \tif (!p->pack_size && p->pack_fd == -1 && open_packed_git(p))\n \t\tdie(\"packfile %s cannot be accessed\", p->pack_name);\n-\tif (offset > (p->pack_size - 20))\n+\tif (offset > (p->pack_size - the_hash_algo->rawsz))\n \t\tdie(\"offset beyond end of packfile (truncated pack?)\");\n \tif (offset < 0)\n \t\tdie(_(\"offset before end of packfile (broken .idx?)\"));\n@@ -675,7 +677,8 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local)\n \tp->pack_size = st.st_size;\n \tp->pack_local = local;\n \tp->mtime = st.st_mtime;\n-\tif (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))\n+\tif (path_len < the_hash_algo->hexsz ||\n+\t    get_sha1_hex(path + path_len - the_hash_algo->hexsz, p->sha1))\n \t\thashclr(p->sha1);\n \treturn p;\n }\n@@ -1028,7 +1031,8 @@ const struct packed_git *has_packed_and_bad(const unsigned char *sha1)\n \n \tfor (p = the_repository->objects->packed_git; p; p = p->next)\n \t\tfor (i = 0; i < p->num_bad_objects; i++)\n-\t\t\tif (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))\n+\t\t\tif (!hashcmp(sha1,\n+\t\t\t\t     p->bad_object_sha1 + the_hash_algo->rawsz * i))\n \t\t\t\treturn p;\n \treturn NULL;\n }\n@@ -1066,7 +1070,7 @@ static off_t get_delta_base(struct packed_git *p,\n \t} else if (type == OBJ_REF_DELTA) {\n \t\t/* The base entry _must_ be in the same pack */\n \t\tbase_offset = find_pack_entry_one(base_info, p);\n-\t\t*curpos += 20;\n+\t\t*curpos += the_hash_algo->rawsz;\n \t} else\n \t\tdie(\"I am totally screwed\");\n \treturn base_offset;\n@@ -1671,6 +1675,7 @@ int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32\n {\n \tconst unsigned char *index_fanout = p->index_data;\n \tconst unsigned char *index_lookup;\n+\tconst unsigned int hashsz = the_hash_algo->rawsz;\n \tint index_lookup_width;\n \n \tif (!index_fanout)\n@@ -1678,10 +1683,10 @@ int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32\n \n \tindex_lookup = index_fanout + 4 * 256;\n \tif (p->index_version == 1) {\n-\t\tindex_lookup_width = 24;\n+\t\tindex_lookup_width = hashsz + 4;\n \t\tindex_lookup += 4;\n \t} else {\n-\t\tindex_lookup_width = 20;\n+\t\tindex_lookup_width = hashsz;\n \t\tindex_fanout += 8;\n \t\tindex_lookup += 8;\n \t}\n@@ -1694,6 +1699,7 @@ const unsigned char *nth_packed_object_sha1(struct packed_git *p,\n \t\t\t\t\t    uint32_t n)\n {\n \tconst unsigned char *index = p->index_data;\n+\tconst unsigned int hashsz = the_hash_algo->rawsz;\n \tif (!index) {\n \t\tif (open_pack_index(p))\n \t\t\treturn NULL;\n@@ -1703,10 +1709,10 @@ const unsigned char *nth_packed_object_sha1(struct packed_git *p,\n \t\treturn NULL;\n \tindex += 4 * 256;\n \tif (p->index_version == 1) {\n-\t\treturn index + 24 * n + 4;\n+\t\treturn index + (hashsz + 4) * n + 4;\n \t} else {\n \t\tindex += 8;\n-\t\treturn index + 20 * n;\n+\t\treturn index + hashsz * n;\n \t}\n }\n \n@@ -1738,12 +1744,13 @@ void check_pack_index_ptr(const struct packed_git *p, const void *vptr)\n off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)\n {\n \tconst unsigned char *index = p->index_data;\n+\tconst unsigned int hashsz = the_hash_algo->rawsz;\n \tindex += 4 * 256;\n \tif (p->index_version == 1) {\n-\t\treturn ntohl(*((uint32_t *)(index + 24 * n)));\n+\t\treturn ntohl(*((uint32_t *)(index + (hashsz + 4) * n)));\n \t} else {\n \t\tuint32_t off;\n-\t\tindex += 8 + p->num_objects * (20 + 4);\n+\t\tindex += 8 + p->num_objects * (hashsz + 4);\n \t\toff = ntohl(*((uint32_t *)(index + 4 * n)));\n \t\tif (!(off & 0x80000000))\n \t\t\treturn off;\n@@ -1814,7 +1821,8 @@ static int fill_pack_entry(const struct object_id *oid,\n \tif (p->num_bad_objects) {\n \t\tunsigned i;\n \t\tfor (i = 0; i < p->num_bad_objects; i++)\n-\t\t\tif (!hashcmp(oid->hash, p->bad_object_sha1 + 20 * i))\n+\t\t\tif (!hashcmp(oid->hash,\n+\t\t\t\t     p->bad_object_sha1 + the_hash_algo->rawsz * i))\n \t\t\t\treturn 0;\n \t}\n \n"},{"id":"345589","messageId":"20180424010055.13183-1-szeder.dev@gmail.com","threadId":"48349","inReplyTo":"20180423233951.276447-42-sandals@crustytoothpaste.net","subject":"Re: [PATCH 41/41] merge-one-file: compute empty blob object ID","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2018-04-24T01:00:55Z","receivedAt":"2018-04-24T01:01:06Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"> This script hard-codes the object ID of the empty tree.  To avoid any\n\ns/tree/blob/\n\n> problems when changing hashes, compute this value by calling git\n> hash-object.\n\nMissing signoff.\n\n> ---\n>  git-merge-one-file.sh | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n> \n> diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh\n> index 9879c59395..f6d9852d2f 100755\n> --- a/git-merge-one-file.sh\n> +++ b/git-merge-one-file.sh\n> @@ -120,7 +120,7 @@ case \"${1:-.}${2:-.}${3:-.}\" in\n>  \tcase \"$1\" in\n>  \t'')\n>  \t\techo \"Added $4 in both, but differently.\"\n> -\t\torig=$(git unpack-file e69de29bb2d1d6434b8b29ae775ad8c2e48c5391)\n> +\t\torig=$(git unpack-file $(git hash-object /dev/null))\n>  \t\t;;\n>  \t*)\n>  \t\techo \"Auto-merging $4\"\n> \n"},{"id":"345590","messageId":"20180424010339.GC245996@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"20180424010055.13183-1-szeder.dev@gmail.com","subject":"Re: [PATCH 41/41] merge-one-file: compute empty blob object ID","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-24T01:03:39Z","receivedAt":"2018-04-24T01:04:12Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, Apr 24, 2018 at 03:00:55AM +0200, SZEDER Gábor wrote:\n> > This script hard-codes the object ID of the empty tree.  To avoid any\n> \n> s/tree/blob/\n> \n> > problems when changing hashes, compute this value by calling git\n> > hash-object.\n> \n> Missing signoff.\n\nThanks, will fix.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"345625","messageId":"20180424075337.GA24895@ruderich.org","threadId":"48349","inReplyTo":"20180423233951.276447-24-sandals@crustytoothpaste.net","subject":"Re: [PATCH 23/41] upload-pack: replace use of several hard-coded constants","fromName":"Simon Ruderich","fromEmail":"simon@ruderich.org","sentAt":"2018-04-24T07:53:37Z","receivedAt":"2018-04-24T07:53:42Z","isPatch":true,"sender":{"key":"simon@ruderich.org","avatar":"https://avatars.githubusercontent.com/u/390994?v=4"},"body":"On Mon, Apr 23, 2018 at 11:39:33PM +0000, brian m. carlson wrote:\n> [snip]\n>\n> diff --git a/upload-pack.c b/upload-pack.c\n> index 4a82602be5..0858527c5b 100644\n> --- a/upload-pack.c\n> +++ b/upload-pack.c\n> @@ -450,7 +450,7 @@ static int get_common_commits(void)\n>  \t\t\t\tbreak;\n>  \t\t\tdefault:\n>  \t\t\t\tgot_common = 1;\n> -\t\t\t\tmemcpy(last_hex, oid_to_hex(&oid), 41);\n> +\t\t\t\toid_to_hex_r(last_hex, &oid);\n>  \t\t\t\tif (multi_ack == 2)\n>  \t\t\t\t\tpacket_write_fmt(1, \"ACK %s common\\n\", last_hex);\n>  \t\t\t\telse if (multi_ack)\n> @@ -492,7 +492,7 @@ static int do_reachable_revlist(struct child_process *cmd,\n>  \t\t\"rev-list\", \"--stdin\", NULL,\n>  \t};\n>  \tstruct object *o;\n> -\tchar namebuf[42]; /* ^ + SHA-1 + LF */\n> +\tchar namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + SHA-1 + LF */\n\nI think this comment should be \"^ + hash as hex + LF\".\n\n> @@ -561,15 +561,17 @@ static int get_reachable_list(struct object_array *src,\n>  \tstruct child_process cmd = CHILD_PROCESS_INIT;\n>  \tint i;\n>  \tstruct object *o;\n> -\tchar namebuf[42]; /* ^ + SHA-1 + LF */\n> +\tchar namebuf[GIT_MAX_HEXSZ + 2]; /* ^ + SHA-1 + LF */\n> +\tconst unsigned hexsz = the_hash_algo->hexsz;\n\nDito.\n\nRegards\nSimon\n-- \n+ privacy is necessary\n+ using gnupg http://gnupg.org\n+ public key id: 0x92FEFDB7E44C32F9\n"},{"id":"345632","messageId":"CAN0heSqvKbSiuNWhHte_HHT-wcewEjm1qVvSoYbZcUKMLT74ig@mail.gmail.com","threadId":"48349","inReplyTo":"20180423233951.276447-2-sandals@crustytoothpaste.net","subject":"Re: [PATCH 01/41] cache: add a function to read an object ID from a buffer","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-04-24T09:39:50Z","receivedAt":"2018-04-24T09:39:55Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 24 April 2018 at 01:39, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> In various places throughout the codebase, we need to read data into a\n> struct object_id from a pack or other unsigned char buffer.  Add an\n> inline function that does this based on the current hash algorithm in\n> use, and use it in several places.\n\nMakes sense. Grepping for \"memcpy.*hash\" turns up a few instances that\nlook similar, but not quite, so we would *not* want to do this\nconversion there, e.g., hashmap.h and notes.c.\n\nMartin\n"},{"id":"345633","messageId":"CAN0heSroUKRz_gZSTbXxO0jkB-WWd45aykpjASrWt8aB=q0iPw@mail.gmail.com","threadId":"48349","inReplyTo":"20180423233951.276447-3-sandals@crustytoothpaste.net","subject":"Re: [PATCH 02/41] server-info: remove unused members from struct pack_info","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-04-24T09:41:36Z","receivedAt":"2018-04-24T09:41:40Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 24 April 2018 at 01:39, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> The head member of struct pack_info is completely unused and the\n> nr_heads member is used only in one place, which is an assignment.\n> Since these structure members are not useful, remove them.\n\nGood catch.\n\n> @@ -228,7 +226,6 @@ static void init_pack_info(const char *infofile, int force)\n>         for (i = 0; i < num_pack; i++) {\n>                 if (stale) {\n>                         info[i]->old_num = -1;\n> -                       info[i]->nr_heads = 0;\n>                 }\n>         }\n\nMinor nits: The braces could go. Not something you're introducing, but\nthe nesting of the `for` and the `if` looks odd. There used to be more\ninside this loop, which explains this.\n\nMartin\n"},{"id":"345634","messageId":"CAN0heSouHbAj8TbiROe=XRsBJ788Vi6P4a_Wvv=7OrdsXqQXHw@mail.gmail.com","threadId":"48349","inReplyTo":"20180423233951.276447-19-sandals@crustytoothpaste.net","subject":"Re: [PATCH 18/41] index-pack: abstract away hash function constant","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-04-24T09:50:16Z","receivedAt":"2018-04-24T09:50:20Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 24 April 2018 at 01:39, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> The code for reading certain pack v2 offsets had a hard-coded 5\n> representing the number of uint32_t words that we needed to skip over.\n> Specify this value in terms of a value from the_hash_algo.\n>\n> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> ---\n>  builtin/index-pack.c | 3 ++-\n>  1 file changed, 2 insertions(+), 1 deletion(-)\n>\n> diff --git a/builtin/index-pack.c b/builtin/index-pack.c\n> index d81473e722..c1f94a7da6 100644\n> --- a/builtin/index-pack.c\n> +++ b/builtin/index-pack.c\n> @@ -1543,12 +1543,13 @@ static void read_v2_anomalous_offsets(struct packed_git *p,\n>  {\n>         const uint32_t *idx1, *idx2;\n>         uint32_t i;\n> +       const uint32_t hashwords = the_hash_algo->rawsz / sizeof(uint32_t);\n\nShould we round up? Or just what should we do if a length is not\ndivisible by 4? (I am not aware of any such hash functions, but one\ncould exist for all I know.) Another question is whether such an\nindex-pack v2 will ever contain non-SHA-1 oids to begin with. I can't\nfind anything suggesting that it could, but this is unfamiliar code to\nme.\n\n>         /* The address of the 4-byte offset table */\n>         idx1 = (((const uint32_t *)p->index_data)\n>                 + 2 /* 8-byte header */\n>                 + 256 /* fan out */\n> -               + 5 * p->num_objects /* 20-byte SHA-1 table */\n> +               + hashwords * p->num_objects /* object ID table */\n>                 + p->num_objects /* CRC32 table */\n>                 );\n"},{"id":"345635","messageId":"CAN0heSoCsFYqDmwTRCzh2FGDnOghBqVBTCOa7yEw0jtQ3LxDbA@mail.gmail.com","threadId":"48349","inReplyTo":"20180423233951.276447-22-sandals@crustytoothpaste.net","subject":"Re: [PATCH 21/41] http: eliminate hard-coded constants","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-04-24T09:53:33Z","receivedAt":"2018-04-24T09:53:37Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 24 April 2018 at 01:39, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> Use the_hash_algo to find the right size for parsing pack names.\n>\n> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> ---\n>  http.c | 11 ++++++-----\n>  1 file changed, 6 insertions(+), 5 deletions(-)\n>\n> diff --git a/http.c b/http.c\n> index 3034d10b68..ec70676748 100644\n> --- a/http.c\n> +++ b/http.c\n> @@ -2047,7 +2047,8 @@ int http_get_info_packs(const char *base_url, struct packed_git **packs_head)\n>         int ret = 0, i = 0;\n>         char *url, *data;\n>         struct strbuf buf = STRBUF_INIT;\n> -       unsigned char sha1[20];\n> +       unsigned char hash[GIT_MAX_RAWSZ];\n> +       const unsigned hexsz = the_hash_algo->hexsz;\n>\n>         end_url_with_slash(&buf, base_url);\n>         strbuf_addstr(&buf, \"objects/info/packs\");\n> @@ -2063,11 +2064,11 @@ int http_get_info_packs(const char *base_url, struct packed_git **packs_head)\n>                 switch (data[i]) {\n>                 case 'P':\n>                         i++;\n> -                       if (i + 52 <= buf.len &&\n> +                       if (i + hexsz + 12 <= buf.len &&\n>                             starts_with(data + i, \" pack-\") &&\n> -                           starts_with(data + i + 46, \".pack\\n\")) {\n> -                               get_sha1_hex(data + i + 6, sha1);\n> -                               fetch_and_setup_pack_index(packs_head, sha1,\n> +                           starts_with(data + i + hexsz + 6, \".pack\\n\")) {\n> +                               get_sha1_hex(data + i + 6, hash);\n> +                               fetch_and_setup_pack_index(packs_head, hash,\n>                                                       base_url);\n>                                 i += 51;\n\ns/51/hexsz + 11/ ?\n"},{"id":"345636","messageId":"CAN0heSoU4wDAcfF_EGYSA4gjbpCgTyk0fGPsmPTwv65FfZCQcg@mail.gmail.com","threadId":"48349","inReplyTo":"20180423233951.276447-26-sandals@crustytoothpaste.net","subject":"Re: [PATCH 25/41] builtin/receive-pack: avoid hard-coded constants for push certs","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-04-24T09:58:17Z","receivedAt":"2018-04-24T09:58:24Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 24 April 2018 at 01:39, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> Use the GIT_SHA1_RAWSZ and GIT_SHA1_HEXSZ macros instead of hard-coding\n> the constants 20 and 40.  Switch one use of 20 with a format specifier\n> for a hex value to use the hex constant instead, as the original appears\n> to have been a typo.\n>\n> At this point, avoid converting the hard-coded use of SHA-1 to use\n> the_hash_algo.  SHA-1, even if not collision resistant, is secure in the\n> context in which it is used here, and the hash algorithm of the repo\n> need not match what is used here.  When we adopt a new hash algorithm,\n> we can simply adopt the new algorithm wholesale here, as the nonce is\n> opaque and its length and validity are entirely controlled by the\n> server.  Consequently, defer updating this code until that point.\n>\n> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> ---\n>  builtin/receive-pack.c | 6 +++---\n>  1 file changed, 3 insertions(+), 3 deletions(-)\n>\n> diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\n> index c4272fbc96..5f35596c14 100644\n> --- a/builtin/receive-pack.c\n> +++ b/builtin/receive-pack.c\n> @@ -454,21 +454,21 @@ static void hmac_sha1(unsigned char *out,\n>         /* RFC 2104 2. (6) & (7) */\n>         git_SHA1_Init(&ctx);\n>         git_SHA1_Update(&ctx, k_opad, sizeof(k_opad));\n> -       git_SHA1_Update(&ctx, out, 20);\n> +       git_SHA1_Update(&ctx, out, GIT_SHA1_RAWSZ);\n>         git_SHA1_Final(out, &ctx);\n>  }\n\nSince we do HMAC with SHA-1, we use the functions `git_SHA1_foo()`. Ok.\nBut then why not just use \"20\"? Isn't GIT_SHA1_RAWSZ coupled to the\nwhole hash transition thing? This use of \"20\" is not, IMHO, the \"length\nin bytes [...] of an object name\" (quoting cache.h).\n\n>  static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp)\n>  {\n>         struct strbuf buf = STRBUF_INIT;\n> -       unsigned char sha1[20];\n> +       unsigned char sha1[GIT_SHA1_RAWSZ];\n>\n>         strbuf_addf(&buf, \"%s:%\"PRItime, path, stamp);\n>         hmac_sha1(sha1, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));;\n>         strbuf_release(&buf);\n>\n>         /* RFC 2104 5. HMAC-SHA1-80 */\n> -       strbuf_addf(&buf, \"%\"PRItime\"-%.*s\", stamp, 20, sha1_to_hex(sha1));\n> +       strbuf_addf(&buf, \"%\"PRItime\"-%.*s\", stamp, GIT_SHA1_HEXSZ, sha1_to_hex(sha1));\n>         return strbuf_detach(&buf, NULL);\n>  }\n\nSame comment here.\n\nMartin\n"},{"id":"345637","messageId":"CAN0heSpoe7SgNZnYDHXS7ByMmh3TH+exaS40btK7pq21MZ3cEA@mail.gmail.com","threadId":"48349","inReplyTo":"20180423233951.276447-32-sandals@crustytoothpaste.net","subject":"Re: [PATCH 31/41] wt-status: convert two uses of EMPTY_TREE_SHA1_HEX","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-04-24T10:03:35Z","receivedAt":"2018-04-24T10:03:39Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 24 April 2018 at 01:39, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> Convert two uses of EMPTY_TREE_SHA1_HEX to use oid_to_hex_r and\n> the_hash_algo to avoid a dependency on a given hash algorithm.  Use\n> oid_to_hex_r in preference to oid_to_hex because the buffer needs to\n> last through several function calls which might exhaust the limit of\n> four static buffers.\n>\n> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> ---\n>  wt-status.c | 6 ++++--\n>  1 file changed, 4 insertions(+), 2 deletions(-)\n>\n> diff --git a/wt-status.c b/wt-status.c\n> index 50815e5faf..857724bd60 100644\n> --- a/wt-status.c\n> +++ b/wt-status.c\n> @@ -600,10 +600,11 @@ static void wt_status_collect_changes_index(struct wt_status *s)\n>  {\n>         struct rev_info rev;\n>         struct setup_revision_opt opt;\n> +       char hex[GIT_MAX_HEXSZ + 1];\n>\n>         init_revisions(&rev, NULL);\n>         memset(&opt, 0, sizeof(opt));\n> -       opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;\n> +       opt.def = s->is_initial ? oid_to_hex_r(hex, the_hash_algo->empty_tree) : s->reference;\n>         setup_revisions(0, NULL, &rev, &opt);\n>\n>         rev.diffopt.flags.override_submodule_config = 1;\n> @@ -975,13 +976,14 @@ static void wt_longstatus_print_verbose(struct wt_status *s)\n>         struct setup_revision_opt opt;\n>         int dirty_submodules;\n>         const char *c = color(WT_STATUS_HEADER, s);\n> +       char hex[GIT_MAX_HEXSZ + 1];\n>\n>         init_revisions(&rev, NULL);\n>         rev.diffopt.flags.allow_textconv = 1;\n>         rev.diffopt.ita_invisible_in_index = 1;\n>\n>         memset(&opt, 0, sizeof(opt));\n> -       opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;\n> +       opt.def = s->is_initial ? oid_to_hex_r(hex, the_hash_algo->empty_tree) : s->reference;\n>         setup_revisions(0, NULL, &rev, &opt);\n\nJust a thought: Maybe it would make sense to have a function\n`oid_hex_empty_tree()` or similar to replace the\noid_to_hex[_r](the_hash_algo->empty_tree) idiom. It would help avoid the\nbuffer here, but also get rid of a few instances of code peeking into\nthe_hash_algo. I dunno.\n\nI've been scanning this series semi-sloppily up to here, and left some\ncomments along the way.\n\nThank you for working on this.\n\nMartin\n"},{"id":"345713","messageId":"xmqqpo2o5fvw.fsf@gitster-ct.c.googlers.com","threadId":"48349","inReplyTo":"CAN0heSoCsFYqDmwTRCzh2FGDnOghBqVBTCOa7yEw0jtQ3LxDbA@mail.gmail.com","subject":"Re: [PATCH 21/41] http: eliminate hard-coded constants","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-24T23:44:19Z","receivedAt":"2018-04-24T23:44:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Martin Ågren <martin.agren@gmail.com> writes:\n\n>>                 switch (data[i]) {\n>>                 case 'P':\n>>                         i++;\n>> -                       if (i + 52 <= buf.len &&\n>> +                       if (i + hexsz + 12 <= buf.len &&\n>>                             starts_with(data + i, \" pack-\") &&\n>> -                           starts_with(data + i + 46, \".pack\\n\")) {\n>> -                               get_sha1_hex(data + i + 6, sha1);\n>> -                               fetch_and_setup_pack_index(packs_head, sha1,\n>> +                           starts_with(data + i + hexsz + 6, \".pack\\n\")) {\n>> +                               get_sha1_hex(data + i + 6, hash);\n>> +                               fetch_and_setup_pack_index(packs_head, hash,\n>>                                                       base_url);\n>>                                 i += 51;\n>\n> s/51/hexsz + 11/ ?\n\nQuite right.\n"},{"id":"345716","messageId":"20180424235150.GD245996@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"CAN0heSouHbAj8TbiROe=XRsBJ788Vi6P4a_Wvv=7OrdsXqQXHw@mail.gmail.com","subject":"Re: [PATCH 18/41] index-pack: abstract away hash function constant","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-24T23:51:50Z","receivedAt":"2018-04-24T23:52:00Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, Apr 24, 2018 at 11:50:16AM +0200, Martin Ågren wrote:\n> On 24 April 2018 at 01:39, brian m. carlson\n> <sandals@crustytoothpaste.net> wrote:\n> > The code for reading certain pack v2 offsets had a hard-coded 5\n> > representing the number of uint32_t words that we needed to skip over.\n> > Specify this value in terms of a value from the_hash_algo.\n> >\n> > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> > ---\n> >  builtin/index-pack.c | 3 ++-\n> >  1 file changed, 2 insertions(+), 1 deletion(-)\n> >\n> > diff --git a/builtin/index-pack.c b/builtin/index-pack.c\n> > index d81473e722..c1f94a7da6 100644\n> > --- a/builtin/index-pack.c\n> > +++ b/builtin/index-pack.c\n> > @@ -1543,12 +1543,13 @@ static void read_v2_anomalous_offsets(struct packed_git *p,\n> >  {\n> >         const uint32_t *idx1, *idx2;\n> >         uint32_t i;\n> > +       const uint32_t hashwords = the_hash_algo->rawsz / sizeof(uint32_t);\n> \n> Should we round up? Or just what should we do if a length is not\n> divisible by 4? (I am not aware of any such hash functions, but one\n> could exist for all I know.) Another question is whether such an\n> index-pack v2 will ever contain non-SHA-1 oids to begin with. I can't\n> find anything suggesting that it could, but this is unfamiliar code to\n> me.\n\nI opted not to simply because I know that our current hash is 20 bytes\nand the new one will be 32, and I know those are both divisible by 4.  I\nfeel confident that any future hash we choose will also be divisible by\n4, and the code is going to be complicated if it isn't.\n\nI agree that pack v2 is not going to have anything but SHA-1.  However,\nwriting all the code such that it's algorithm agnostic means that we can\ndo testing of new algorithms by wholesale replacing the algorithm with a\nnew one, which simplifies things considerably.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"345726","messageId":"20180425012949.GE245996@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"xmqqpo2o5fvw.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 21/41] http: eliminate hard-coded constants","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-25T01:29:50Z","receivedAt":"2018-04-25T01:29:59Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Wed, Apr 25, 2018 at 08:44:19AM +0900, Junio C Hamano wrote:\n> Martin Ågren <martin.agren@gmail.com> writes:\n> \n> >>                 switch (data[i]) {\n> >>                 case 'P':\n> >>                         i++;\n> >> -                       if (i + 52 <= buf.len &&\n> >> +                       if (i + hexsz + 12 <= buf.len &&\n> >>                             starts_with(data + i, \" pack-\") &&\n> >> -                           starts_with(data + i + 46, \".pack\\n\")) {\n> >> -                               get_sha1_hex(data + i + 6, sha1);\n> >> -                               fetch_and_setup_pack_index(packs_head, sha1,\n> >> +                           starts_with(data + i + hexsz + 6, \".pack\\n\")) {\n> >> +                               get_sha1_hex(data + i + 6, hash);\n> >> +                               fetch_and_setup_pack_index(packs_head, hash,\n> >>                                                       base_url);\n> >>                                 i += 51;\n> >\n> > s/51/hexsz + 11/ ?\n> \n> Quite right.\n\nGood point.  Will fix.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"345729","messageId":"20180425020013.GF245996@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"CAN0heSoU4wDAcfF_EGYSA4gjbpCgTyk0fGPsmPTwv65FfZCQcg@mail.gmail.com","subject":"Re: [PATCH 25/41] builtin/receive-pack: avoid hard-coded constants for push certs","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-25T02:00:13Z","receivedAt":"2018-04-25T02:00:24Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, Apr 24, 2018 at 11:58:17AM +0200, Martin Ågren wrote:\n> On 24 April 2018 at 01:39, brian m. carlson\n> > diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\n> > index c4272fbc96..5f35596c14 100644\n> > --- a/builtin/receive-pack.c\n> > +++ b/builtin/receive-pack.c\n> > @@ -454,21 +454,21 @@ static void hmac_sha1(unsigned char *out,\n> >         /* RFC 2104 2. (6) & (7) */\n> >         git_SHA1_Init(&ctx);\n> >         git_SHA1_Update(&ctx, k_opad, sizeof(k_opad));\n> > -       git_SHA1_Update(&ctx, out, 20);\n> > +       git_SHA1_Update(&ctx, out, GIT_SHA1_RAWSZ);\n> >         git_SHA1_Final(out, &ctx);\n> >  }\n> \n> Since we do HMAC with SHA-1, we use the functions `git_SHA1_foo()`. Ok.\n> But then why not just use \"20\"? Isn't GIT_SHA1_RAWSZ coupled to the\n> whole hash transition thing? This use of \"20\" is not, IMHO, the \"length\n> in bytes [...] of an object name\" (quoting cache.h).\n\nOriginally, GIT_SHA1_RAWSZ was a good stand-in for the hard-coded uses\nof 20 (and GIT_SHA1_HEXSZ for 40) for object IDs.  Recently, we've\nstarted moving toward using the_hash_algo for the object ID-specific\nhash values, so I've started using those constants only to identify\nSHA-1 specific items.\n\nIn this case, using the constant makes it more obvious that what we're\npassing is indeed an SHA-1 hash.  It also makes it easier to find all\nthe remaining instances of \"20\" in the codebase and analyze them\naccordingly.\n\nI agree that this isn't an object name strictly, but it's essentially\nequivalent.  If you feel strongly, I can leave this the way it is.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"345730","messageId":"CAN0heSotp4ebXWc6NRHOa2j7kQg4XsCo+8RNz786dPGyUTvb-w@mail.gmail.com","threadId":"48349","inReplyTo":"20180425020013.GF245996@genre.crustytoothpaste.net","subject":"Re: [PATCH 25/41] builtin/receive-pack: avoid hard-coded constants for push certs","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-04-25T05:06:04Z","receivedAt":"2018-04-25T05:06:09Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 25 April 2018 at 04:00, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> On Tue, Apr 24, 2018 at 11:58:17AM +0200, Martin Ågren wrote:\n>> On 24 April 2018 at 01:39, brian m. carlson\n>> > diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\n>> > index c4272fbc96..5f35596c14 100644\n>> > --- a/builtin/receive-pack.c\n>> > +++ b/builtin/receive-pack.c\n>> > @@ -454,21 +454,21 @@ static void hmac_sha1(unsigned char *out,\n>> >         /* RFC 2104 2. (6) & (7) */\n>> >         git_SHA1_Init(&ctx);\n>> >         git_SHA1_Update(&ctx, k_opad, sizeof(k_opad));\n>> > -       git_SHA1_Update(&ctx, out, 20);\n>> > +       git_SHA1_Update(&ctx, out, GIT_SHA1_RAWSZ);\n>> >         git_SHA1_Final(out, &ctx);\n>> >  }\n>>\n>> Since we do HMAC with SHA-1, we use the functions `git_SHA1_foo()`. Ok.\n>> But then why not just use \"20\"? Isn't GIT_SHA1_RAWSZ coupled to the\n>> whole hash transition thing? This use of \"20\" is not, IMHO, the \"length\n>> in bytes [...] of an object name\" (quoting cache.h).\n>\n> Originally, GIT_SHA1_RAWSZ was a good stand-in for the hard-coded uses\n> of 20 (and GIT_SHA1_HEXSZ for 40) for object IDs.  Recently, we've\n> started moving toward using the_hash_algo for the object ID-specific\n> hash values, so I've started using those constants only to identify\n> SHA-1 specific items.\n>\n> In this case, using the constant makes it more obvious that what we're\n> passing is indeed an SHA-1 hash.  It also makes it easier to find all\n> the remaining instances of \"20\" in the codebase and analyze them\n> accordingly.\n>\n> I agree that this isn't an object name strictly, but it's essentially\n> equivalent.  If you feel strongly, I can leave this the way it is.\n\nI see. So one could say that in the ideal end-game, GIT_SHA1_RAWSZ would\nbe gone when the oid-hash-transition is over. Except since we also use\nSHA-1 for other stuff than object IDs, the real-world ideal end-game is\nthat we only have a few users lingering in places that have nothing to\ndo with oid, but only with SHA-1 (and maybe in the gluing for\ncalculating SHA-1 oids..).\n\nI do not feel strongly about this. I was just surprised to see it.\nThank you for explaining this.\n\nMartin\n"},{"id":"345843","messageId":"CAN0heSqpj9JfTrnMFRbquraxve9iTwoowgWRUhcD-gXHMg3V=g@mail.gmail.com","threadId":"48349","inReplyTo":"20180424235150.GD245996@genre.crustytoothpaste.net","subject":"Re: [PATCH 18/41] index-pack: abstract away hash function constant","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2018-04-25T18:49:47Z","receivedAt":"2018-04-25T18:49:51Z","isPatch":true,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"On 25 April 2018 at 01:51, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> On Tue, Apr 24, 2018 at 11:50:16AM +0200, Martin Ågren wrote:\n>> On 24 April 2018 at 01:39, brian m. carlson\n>> <sandals@crustytoothpaste.net> wrote:\n>> > The code for reading certain pack v2 offsets had a hard-coded 5\n>> > representing the number of uint32_t words that we needed to skip over.\n>> > Specify this value in terms of a value from the_hash_algo.\n>> >\n>> > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n>> > ---\n>> >  builtin/index-pack.c | 3 ++-\n>> >  1 file changed, 2 insertions(+), 1 deletion(-)\n>> >\n>> > diff --git a/builtin/index-pack.c b/builtin/index-pack.c\n>> > index d81473e722..c1f94a7da6 100644\n>> > --- a/builtin/index-pack.c\n>> > +++ b/builtin/index-pack.c\n>> > @@ -1543,12 +1543,13 @@ static void read_v2_anomalous_offsets(struct packed_git *p,\n>> >  {\n>> >         const uint32_t *idx1, *idx2;\n>> >         uint32_t i;\n>> > +       const uint32_t hashwords = the_hash_algo->rawsz / sizeof(uint32_t);\n>>\n>> Should we round up? Or just what should we do if a length is not\n>> divisible by 4? (I am not aware of any such hash functions, but one\n>> could exist for all I know.) Another question is whether such an\n>> index-pack v2 will ever contain non-SHA-1 oids to begin with. I can't\n>> find anything suggesting that it could, but this is unfamiliar code to\n>> me.\n>\n> I opted not to simply because I know that our current hash is 20 bytes\n> and the new one will be 32, and I know those are both divisible by 4.  I\n> feel confident that any future hash we choose will also be divisible by\n> 4, and the code is going to be complicated if it isn't.\n>\n> I agree that pack v2 is not going to have anything but SHA-1.  However,\n> writing all the code such that it's algorithm agnostic means that we can\n> do testing of new algorithms by wholesale replacing the algorithm with a\n> new one, which simplifies things considerably.\n\nOk. I do sort of wonder if a \"successful\" test run after globally\nsubstituting Hash-Foo for SHA-1 (regardless of whether the size changes\nor not) hints at a problem. That is, nowhere do we test that this code\nuses 20-byte SHA-1s, regardless of what other hash functions are\navailable and configured. Of course, until soon, that did not really\nhave to be tested since there was only one hash function available to\nchoose from. As for identifying all the places that matter ... no idea.\n\nOf course I can see how this helps get things to a point where Git does\nnot crash and burn because the hash has a different size, and where the\ntest suite doesn't spew failures because the initial chaining value of\n\"SHA-1\" is changed.\n\nOnce that is accomplished, I sort of suspect that this code will want to\nbe updated to not always blindly use the_hash_algo, but to always work\nwith SHA-1 sizes. Or rather, this would turn into more generic code to\nhandle both \"v2 with SHA-1\" and \"v3 with some hash function(s)\". This\ncommit might be a good first step in that direction.\n\nLong rambling short, yeah, I see your point.\n\nMartin\n"},{"id":"345899","messageId":"CACsJy8DUsFLDb786FmsR+eTriXaWGXEE+ZG8kCjq7JoipN1Phg@mail.gmail.com","threadId":"48349","inReplyTo":"CAN0heSqpj9JfTrnMFRbquraxve9iTwoowgWRUhcD-gXHMg3V=g@mail.gmail.com","subject":"Re: [PATCH 18/41] index-pack: abstract away hash function constant","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-04-26T15:46:28Z","receivedAt":"2018-04-26T15:47:02Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Apr 25, 2018 at 8:49 PM, Martin Ågren <martin.agren@gmail.com> wrote:\n>> I agree that pack v2 is not going to have anything but SHA-1.  However,\n>> writing all the code such that it's algorithm agnostic means that we can\n>> do testing of new algorithms by wholesale replacing the algorithm with a\n>> new one, which simplifies things considerably.\n>\n> Ok. I do sort of wonder if a \"successful\" test run after globally\n> substituting Hash-Foo for SHA-1 (regardless of whether the size changes\n> or not) hints at a problem. That is, nowhere do we test that this code\n> uses 20-byte SHA-1s, regardless of what other hash functions are\n> available and configured. Of course, until soon, that did not really\n> have to be tested since there was only one hash function available to\n> choose from. As for identifying all the places that matter ... no idea.\n>\n> Of course I can see how this helps get things to a point where Git does\n> not crash and burn because the hash has a different size, and where the\n> test suite doesn't spew failures because the initial chaining value of\n> \"SHA-1\" is changed.\n>\n> Once that is accomplished, I sort of suspect that this code will want to\n> be updated to not always blindly use the_hash_algo, but to always work\n> with SHA-1 sizes. Or rather, this would turn into more generic code to\n> handle both \"v2 with SHA-1\" and \"v3 with some hash function(s)\". This\n> commit might be a good first step in that direction.\n\nI also have an uneasy feeling when things this close to on-disk file\nformat get hash-agnostic treatment. I think we would need to start\nadding new file formats soon, from bottom up with simple things like\nloose object files (cat-file and hash-object should be enough to test\nblobs...), then moving up to pack files and more. This is when we can\nreally decide where to use the new hash and whether we should keep\nsome hashes as sha-1.\n\nFor trailing hashes for example, there's no need to move to a new hash\nwhich only costs us more cycles. We just use it as a fancy checksum to\navoid bit flips. But then my assumption about cost may be completely\nwrong without experimenting.\n\n> Long rambling short, yeah, I see your point.\n\nSo yeah. It may be ok to move everything to \"new hash\" now. But we\nneed a closer look soon.\n-- \nDuy\n"},{"id":"345994","messageId":"20180427210823.GB722934@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"CACsJy8DUsFLDb786FmsR+eTriXaWGXEE+ZG8kCjq7JoipN1Phg@mail.gmail.com","subject":"Re: [PATCH 18/41] index-pack: abstract away hash function constant","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-27T21:08:23Z","receivedAt":"2018-04-27T21:08:36Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Thu, Apr 26, 2018 at 05:46:28PM +0200, Duy Nguyen wrote:\n> On Wed, Apr 25, 2018 at 8:49 PM, Martin Ågren <martin.agren@gmail.com> wrote:\n> > Once that is accomplished, I sort of suspect that this code will want to\n> > be updated to not always blindly use the_hash_algo, but to always work\n> > with SHA-1 sizes. Or rather, this would turn into more generic code to\n> > handle both \"v2 with SHA-1\" and \"v3 with some hash function(s)\". This\n> > commit might be a good first step in that direction.\n> \n> I also have an uneasy feeling when things this close to on-disk file\n> format get hash-agnostic treatment. I think we would need to start\n> adding new file formats soon, from bottom up with simple things like\n> loose object files (cat-file and hash-object should be enough to test\n> blobs...), then moving up to pack files and more. This is when we can\n> really decide where to use the new hash and whether we should keep\n> some hashes as sha-1.\n\nI agree that this is work which needs to be done soon.  There are\nbasically a couple of pieces we need to handle NewHash:\n\n* Remove the dependencies on SHA-1 as much as possible.\n* Get the tests to pass with a different hash (almost done for 160-bit\n  hash; in progress for 256-bit hashes).\n* Write pack code.\n* Write loose object index code.\n* Write read-as-SHA-1 code.\n* Force the codebase to always use SHA-1 when dealing with fetch/push.\n* Distinguish between code which needs to use compatObjectFormat and\n  code which needs to use objectFormat.\n* Decide on NewHash.\n\nI'm working on the top two bullet points right now.  Others are welcome\nto pick up other pieces, or I'll get to them eventually.\n\nAs much as I'm dreading having the bikeshedding discussion over what\nwe're going to pick for NewHash, some of these pieces require knowing\nwhat algorithm it will be.  For example, we have some tests which either\nneed to be completely rewritten or have a translation table written for\nthem (think the ones that use colliding short names).  In order for\nthose tests to have the translation table written, we need to be able to\ncompute colliding values.  I'm annotating these with prerequisites, but\nthere are quite a few tests which are skipped.\n\nI expect writing the pack, loose object index, and read-as-SHA-1 code is\ngoing to require having some code for NewHash or stand-in present in\norder for it to compile and be tested.  It's possible that others could\ncome up with more imaginative solutions that don't require that, but I\nhave my doubts.\n\n> For trailing hashes for example, there's no need to move to a new hash\n> which only costs us more cycles. We just use it as a fancy checksum to\n> avoid bit flips. But then my assumption about cost may be completely\n> wrong without experimenting.\n\nI would argue that consistency is helpful.  Also, do we really want\npeople to be able to (eventually) create colliding packs that contain\ndifferent data?  That doesn't seem like a good idea.\n\nBut also, some of the candidates we're considering for NewHash are\nactually faster than SHA-1.  So for performance reasons alone, it might\nbe useful to adopt a consistent scheme.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"346020","messageId":"CACsJy8BCSMNRvcPS5HaWjaURpS7abfANVUmrJVrxZ=b0qqGjag@mail.gmail.com","threadId":"48349","inReplyTo":"20180427210823.GB722934@genre.crustytoothpaste.net","subject":"Re: [PATCH 18/41] index-pack: abstract away hash function constant","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-04-28T05:41:43Z","receivedAt":"2018-04-28T05:42:18Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Apr 27, 2018 at 11:08 PM, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> On Thu, Apr 26, 2018 at 05:46:28PM +0200, Duy Nguyen wrote:\n>> On Wed, Apr 25, 2018 at 8:49 PM, Martin Ågren <martin.agren@gmail.com> wrote:\n>> > Once that is accomplished, I sort of suspect that this code will want to\n>> > be updated to not always blindly use the_hash_algo, but to always work\n>> > with SHA-1 sizes. Or rather, this would turn into more generic code to\n>> > handle both \"v2 with SHA-1\" and \"v3 with some hash function(s)\". This\n>> > commit might be a good first step in that direction.\n>>\n>> I also have an uneasy feeling when things this close to on-disk file\n>> format get hash-agnostic treatment. I think we would need to start\n>> adding new file formats soon, from bottom up with simple things like\n>> loose object files (cat-file and hash-object should be enough to test\n>> blobs...), then moving up to pack files and more. This is when we can\n>> really decide where to use the new hash and whether we should keep\n>> some hashes as sha-1.\n>\n> I agree that this is work which needs to be done soon.  There are\n> basically a couple of pieces we need to handle NewHash:\n>\n> * Remove the dependencies on SHA-1 as much as possible.\n> * Get the tests to pass with a different hash (almost done for 160-bit\n>   hash; in progress for 256-bit hashes).\n\nThis step sounds good on paper but realistically could be a nightmare for you.\n\nI tried to implement a simple cat-file/hash-object combination with my\nimaginary newhash, which sounded straightforward to me since you have\ndone a lot of heavylifting. To my surprise I hit a lot more problems.\nMy point is, when I concentrate on just a few simple cases like this,\nI have a smaller scope to work with and could quickly identify\nproblems. When you work on the scale of the test suite, it's really\nhard to know where the problem is (and you don't even know what areas\nare newhash-safe).\n\nAnyway my cat-file/hash-object modification could be found here. I\nprobably will polish and send out a few good patches from it.\n\nhttps://github.com/pclouds/git/commits/new-hash\n-- \nDuy\n"},{"id":"346182","messageId":"CACsJy8CX7cgd4EGSHVUtm35Aq92Us8WBA-r746vEaZiFP5Q5Lg@mail.gmail.com","threadId":"48349","inReplyTo":"20180423233951.276447-1-sandals@crustytoothpaste.net","subject":"Re: [PATCH 00/41] object_id part 13","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-04-30T18:03:12Z","receivedAt":"2018-04-30T18:03:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Apr 24, 2018 at 1:39 AM, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> [0] I can synthesize blobs, trees, and commits, but things are currently\n> totally broken, which is, I suppose, to be expected.\n\nYup. I was tired and bored so I went playing with the new hash.\nWriting and reading blobs (with hash-object/cat-file) were relatively\neasy after fixing up fill_sha1_path and get_oid_basic). Then I worked\nmy way up to update-index/ls-files so that I could make trees with\nwrite-tree. And I hit the first road block: struct ondisk_cache_entry\nhard codes hash size so I would need to re-organize the code for more\nflexibility (or even redesign the file format if I want to keep byte\nalignment). Eck...\n\nI guess I'll be helping review this series instead :D\n-- \nDuy\n"},{"id":"346215","messageId":"20180430235943.GC13217@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"CACsJy8CX7cgd4EGSHVUtm35Aq92Us8WBA-r746vEaZiFP5Q5Lg@mail.gmail.com","subject":"Re: [PATCH 00/41] object_id part 13","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-04-30T23:59:43Z","receivedAt":"2018-04-30T23:59:55Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Mon, Apr 30, 2018 at 08:03:12PM +0200, Duy Nguyen wrote:\n> On Tue, Apr 24, 2018 at 1:39 AM, brian m. carlson\n> <sandals@crustytoothpaste.net> wrote:\n> > [0] I can synthesize blobs, trees, and commits, but things are currently\n> > totally broken, which is, I suppose, to be expected.\n> \n> Yup. I was tired and bored so I went playing with the new hash.\n> Writing and reading blobs (with hash-object/cat-file) were relatively\n> easy after fixing up fill_sha1_path and get_oid_basic). Then I worked\n> my way up to update-index/ls-files so that I could make trees with\n> write-tree. And I hit the first road block: struct ondisk_cache_entry\n> hard codes hash size so I would need to re-organize the code for more\n> flexibility (or even redesign the file format if I want to keep byte\n> alignment). Eck...\n> \n> I guess I'll be helping review this series instead :D\n\nYeah, I have code to fix that, but it's ugly.\n\nYou can see the work on part2 and part3 of the test fixes, plus the\nfixes for all of that stuff on my object-id-part14 branch.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"346220","messageId":"20180501022931.GF13217@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"CAN0heSpoe7SgNZnYDHXS7ByMmh3TH+exaS40btK7pq21MZ3cEA@mail.gmail.com","subject":"Re: [PATCH 31/41] wt-status: convert two uses of EMPTY_TREE_SHA1_HEX","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-05-01T02:29:31Z","receivedAt":"2018-05-01T02:39:16Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, Apr 24, 2018 at 12:03:35PM +0200, Martin Ågren wrote:\n> Just a thought: Maybe it would make sense to have a function\n> `oid_hex_empty_tree()` or similar to replace the\n> oid_to_hex[_r](the_hash_algo->empty_tree) idiom. It would help avoid the\n> buffer here, but also get rid of a few instances of code peeking into\n> the_hash_algo. I dunno.\n\nAt first I wasn't going to include this change in the series, but then I\nthought about what a good idea it was and decided to redo the\ncorresponding patches.  So I hope to have a v2 out tomorrow with this\nchange (and the rest of them) in it.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"346223","messageId":"20180501093603.GA15820@duynguyen.home","threadId":"48349","inReplyTo":"20180423233951.276447-2-sandals@crustytoothpaste.net","subject":"Re: [PATCH 01/41] cache: add a function to read an object ID from a buffer","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-01T09:36:03Z","receivedAt":"2018-05-01T09:36:11Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Apr 23, 2018 at 11:39:11PM +0000, brian m. carlson wrote:\n> diff --git a/cache.h b/cache.h\n> index bbaf5c349a..4bca177cf3 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -1008,6 +1008,11 @@ static inline void oidclr(struct object_id *oid)\n>  \tmemset(oid->hash, 0, GIT_MAX_RAWSZ);\n>  }\n>  \n> +static inline void oidread(struct object_id *oid, const unsigned char *hash)\n> +{\n> +\tmemcpy(oid->hash, hash, the_hash_algo->rawsz);\n\nIf performance is a concern, should we go with GIT_MAX_RAWSZ instead\nof the_hash_algo->rawsz which gives the compiler some more to bypass\nactual memcpy function and generate copy code directly?\n\nIf it is not a performance problem, should we avoid inline and move\nthe implementation somewhere?\n\n> +}\n> +\n>  \n"},{"id":"346224","messageId":"20180501093932.GB15820@duynguyen.home","threadId":"48349","inReplyTo":"20180423233951.276447-3-sandals@crustytoothpaste.net","subject":"Re: [PATCH 02/41] server-info: remove unused members from struct pack_info","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-01T09:39:32Z","receivedAt":"2018-05-01T09:39:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Apr 23, 2018 at 11:39:12PM +0000, brian m. carlson wrote:\n> The head member of struct pack_info is completely unused and the\n> nr_heads member is used only in one place, which is an assignment.\n> Since these structure members are not useful, remove them.\n\nIf you reroll, you could add that their last use was in 3e15c67c90\n(server-info: throw away T computation as well. - 2005-12-04)\n--\nDuy\n\n"},{"id":"346225","messageId":"20180501095004.GC15820@duynguyen.home","threadId":"48349","inReplyTo":"20180423233951.276447-4-sandals@crustytoothpaste.net","subject":"Re: [PATCH 03/41] Remove unused member in struct object_context","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-01T09:50:04Z","receivedAt":"2018-05-01T09:50:11Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Apr 23, 2018 at 11:39:13PM +0000, brian m. carlson wrote:\n> The tree member of struct object_context is unused except in one place\n> where we write to it.  Since there are no users of this member, remove\n> it.\n\nYep. It's never used since its introduction in 573285e552 (sha1_name:\nadd get_sha1_with_context() - 2010-06-09) in 'cp/textconv-cat-file'\ntopic. I guess the idea at that time was to keep all the information\nfrom get_tree_entry() in object context for future use.\n\nSince it's been eight years and nobody needs it still, it should be\ngood to go.\n--\nDuy\n"},{"id":"346227","messageId":"20180501100114.GD15820@duynguyen.home","threadId":"48349","inReplyTo":"20180423233951.276447-5-sandals@crustytoothpaste.net","subject":"Re: [PATCH 04/41] packfile: remove unused member from struct pack_entry","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-01T10:01:14Z","receivedAt":"2018-05-01T10:01:21Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Apr 23, 2018 at 11:39:14PM +0000, brian m. carlson wrote:\n> The sha1 member in struct pack_entry is unused except for one instance\n> in which we store a value in it.  Since nobody ever reads this value,\n> don't bother to compute it and remove the member from struct pack_entry.\n\nNever used since its introduction in 1f688557c0 ([PATCH] Teach\nread_sha1_file() and friends about packed git object store. -\n2005-06-27). Good riddance.\n--\nDuy\n"},{"id":"346228","messageId":"20180501102243.GE15820@duynguyen.home","threadId":"48349","inReplyTo":"20180423233951.276447-9-sandals@crustytoothpaste.net","subject":"Re: [PATCH 08/41] packfile: abstract away hash constant values","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-01T10:22:43Z","receivedAt":"2018-05-01T10:22:51Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Apr 23, 2018 at 11:39:18PM +0000, brian m. carlson wrote:\n> There are several instances of the constant 20 and 20-based values in\n> the packfile code.  Abstract away dependence on SHA-1 by using the\n> values from the_hash_algo instead.\n\nWhile we're abstracting away 20. There's the only 20 left in\nsha1_file.c that should also be gone. But I guess you could do that\nlater since you need to rename fill_sha1_path to\nfill_loose_object_path or something.\n\n\n> @@ -507,15 +509,15 @@ static int open_packed_git_1(struct packed_git *p)\n>  \t\t\t     \" while index indicates %\"PRIu32\" objects\",\n>  \t\t\t     p->pack_name, ntohl(hdr.hdr_entries),\n>  \t\t\t     p->num_objects);\n> -\tif (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)\n> +\tif (lseek(p->pack_fd, p->pack_size - hashsz, SEEK_SET) == -1)\n>  \t\treturn error(\"end of packfile %s is unavailable\", p->pack_name);\n> -\tread_result = read_in_full(p->pack_fd, sha1, sizeof(sha1));\n> +\tread_result = read_in_full(p->pack_fd, hash, hashsz);\n>  \tif (read_result < 0)\n>  \t\treturn error_errno(\"error reading from %s\", p->pack_name);\n> -\tif (read_result != sizeof(sha1))\n> +\tif (read_result != hashsz)\n>  \t\treturn error(\"packfile %s signature is unavailable\", p->pack_name);\n> -\tidx_sha1 = ((unsigned char *)p->index_data) + p->index_size - 40;\n> -\tif (hashcmp(sha1, idx_sha1))\n> +\tidx_hash = ((unsigned char *)p->index_data) + p->index_size - hashsz * 2;\n> +\tif (hashcmp(hash, idx_hash))\n\nSince the hash size is abstracted away, shouldn't this hashcmp become\noidcmp? (which still does not do the right thing, but at least it's\none less place to worry about)\n\nSame comment for other hashcmp in this patch.\n\n> @@ -675,7 +677,8 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local)\n>  \tp->pack_size = st.st_size;\n>  \tp->pack_local = local;\n>  \tp->mtime = st.st_mtime;\n> -\tif (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))\n> +\tif (path_len < the_hash_algo->hexsz ||\n> +\t    get_sha1_hex(path + path_len - the_hash_algo->hexsz, p->sha1))\n\nget_sha1_hex looks out of place when we start going with\nthe_hash_algo. Maybe change to get_oid_hex() too.\n\n> @@ -1678,10 +1683,10 @@ int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32\n>  \n>  \tindex_lookup = index_fanout + 4 * 256;\n>  \tif (p->index_version == 1) {\n> -\t\tindex_lookup_width = 24;\n> +\t\tindex_lookup_width = hashsz + 4;\n\nYou did good research to spot this 24 constant ;-)\n\n--\nDuy\n"},{"id":"346229","messageId":"20180501102640.GF15820@duynguyen.home","threadId":"48349","inReplyTo":"20180423233951.276447-10-sandals@crustytoothpaste.net","subject":"Re: [PATCH 09/41] pack-objects: abstract away hash algorithm","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-01T10:26:40Z","receivedAt":"2018-05-01T10:26:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Apr 23, 2018 at 11:39:19PM +0000, brian m. carlson wrote:\n> @@ -1850,7 +1852,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,\n>  \t/* Now some size filtering heuristics. */\n>  \ttrg_size = trg_entry->size;\n>  \tif (!trg_entry->delta) {\n> -\t\tmax_size = trg_size/2 - 20;\n> +\t\tmax_size = trg_size/2 - the_hash_algo->rawsz;\n\nThis may be questionable. Note the \"heuristics\" comment above. I'm not\neven sure if this is hash size or some magical-yet-randomly-good\nvalue. Just wanted to bring the attention for other people with better\nunderstand of this code to see\n\n>  \t\tref_depth = 1;\n>  \t} else {\n>  \t\tmax_size = trg_entry->delta_size;\n"},{"id":"346230","messageId":"20180501104257.GG15820@duynguyen.home","threadId":"48349","inReplyTo":"20180423233951.276447-40-sandals@crustytoothpaste.net","subject":"Re: [PATCH 39/41] Update shell scripts to compute empty tree object ID","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-01T10:42:57Z","receivedAt":"2018-05-01T10:43:04Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Apr 23, 2018 at 11:39:49PM +0000, brian m. carlson wrote:\n> Several of our shell scripts hard-code the object ID of the empty tree.\n> To avoid any problems when changing hashes, compute this value on\n> startup of the script.  For performance, store the value in a variable\n> and reuse it throughout the life of the script.\n> \n> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> ---\n>  git-filter-branch.sh               | 4 +++-\n>  git-rebase--interactive.sh         | 4 +++-\n>  templates/hooks--pre-commit.sample | 2 +-\n>  3 files changed, 7 insertions(+), 3 deletions(-)\n> \n> diff --git a/git-filter-branch.sh b/git-filter-branch.sh\n> index 64f21547c1..ccceaf19a7 100755\n> --- a/git-filter-branch.sh\n> +++ b/git-filter-branch.sh\n> @@ -11,6 +11,8 @@\n>  # The following functions will also be available in the commit filter:\n>  \n>  functions=$(cat << \\EOF\n> +EMPTY_TREE=$(git hash-object -t tree /dev/null)\n\nAll scripts (except those example hooks) must source\ngit-sh-setup. Should we define this in there instead?\n--\nDuy\n"},{"id":"346231","messageId":"20180501105134.GH15820@duynguyen.home","threadId":"48349","inReplyTo":"20180430235943.GC13217@genre.crustytoothpaste.net","subject":"Re: [PATCH 00/41] object_id part 13","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-01T10:51:34Z","receivedAt":"2018-05-01T10:51:42Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Apr 30, 2018 at 11:59:43PM +0000, brian m. carlson wrote:\n> > I guess I'll be helping review this series instead :D\n\nOverall I think this looks good.\n\n> \n> Yeah, I have code to fix that, but it's ugly.\n> \n> You can see the work on part2 and part3 of the test fixes, plus the\n> fixes for all of that stuff on my object-id-part14 branch.\n\nSince I gave it some thought, another way of dealing with this may be\nhiding this behind git_hash_algo abstraction, so we have one function\nfor sha1, one for newhash... and they are probably just macros that\ntake different struct definition.\n\n--\nDuy\n\n"},{"id":"346353","messageId":"20180501235837.GG13217@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"20180501093603.GA15820@duynguyen.home","subject":"Re: [PATCH 01/41] cache: add a function to read an object ID from a buffer","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-05-01T23:58:38Z","receivedAt":"2018-05-01T23:59:14Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, May 01, 2018 at 11:36:03AM +0200, Duy Nguyen wrote:\n> On Mon, Apr 23, 2018 at 11:39:11PM +0000, brian m. carlson wrote:\n> > diff --git a/cache.h b/cache.h\n> > index bbaf5c349a..4bca177cf3 100644\n> > --- a/cache.h\n> > +++ b/cache.h\n> > @@ -1008,6 +1008,11 @@ static inline void oidclr(struct object_id *oid)\n> >  \tmemset(oid->hash, 0, GIT_MAX_RAWSZ);\n> >  }\n> >  \n> > +static inline void oidread(struct object_id *oid, const unsigned char *hash)\n> > +{\n> > +\tmemcpy(oid->hash, hash, the_hash_algo->rawsz);\n> \n> If performance is a concern, should we go with GIT_MAX_RAWSZ instead\n> of the_hash_algo->rawsz which gives the compiler some more to bypass\n> actual memcpy function and generate copy code directly?\n\nI don't think we can do that.  If we have both NewHash and SHA-1\ncompiled in and are using SHA-1, GIT_MAX_RAWSZ will be 32, but we may\nonly have 20 bytes that are valid to read.\n\n> If it is not a performance problem, should we avoid inline and move\n> the implementation somewhere?\n\nI would like to make it as fast as possible if we can, especially since\nhashcpy is inline.  If you have concerns about performance, I can add a\npatch in a future series that does some sort of macro if we're using gcc\nthat does something like the following:\n\n  ({\n    int rawsz = the_hash_algo->rawsz;\n    if (rawsz != GIT_SHA1_RAWSZ && rawsz != GIT_MAX_RAWSZ)\n      __builtin_trap(); /* never reached */\n    rawsz;\n   })\n\nAnd then use that instead of the_hash_algo->rawsz in performance\nsensitive paths.  That would mean the compiler would know that it was\nonly one of those two values and it could optimize better.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"346356","messageId":"20180502001140.GH13217@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"20180501102243.GE15820@duynguyen.home","subject":"Re: [PATCH 08/41] packfile: abstract away hash constant values","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-05-02T00:11:41Z","receivedAt":"2018-05-02T00:11:50Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, May 01, 2018 at 12:22:43PM +0200, Duy Nguyen wrote:\n> On Mon, Apr 23, 2018 at 11:39:18PM +0000, brian m. carlson wrote:\n> > There are several instances of the constant 20 and 20-based values in\n> > the packfile code.  Abstract away dependence on SHA-1 by using the\n> > values from the_hash_algo instead.\n> \n> While we're abstracting away 20. There's the only 20 left in\n> sha1_file.c that should also be gone. But I guess you could do that\n> later since you need to rename fill_sha1_path to\n> fill_loose_object_path or something.\n\nI'm already working on knocking those out.\n\n> > @@ -507,15 +509,15 @@ static int open_packed_git_1(struct packed_git *p)\n> >  \t\t\t     \" while index indicates %\"PRIu32\" objects\",\n> >  \t\t\t     p->pack_name, ntohl(hdr.hdr_entries),\n> >  \t\t\t     p->num_objects);\n> > -\tif (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)\n> > +\tif (lseek(p->pack_fd, p->pack_size - hashsz, SEEK_SET) == -1)\n> >  \t\treturn error(\"end of packfile %s is unavailable\", p->pack_name);\n> > -\tread_result = read_in_full(p->pack_fd, sha1, sizeof(sha1));\n> > +\tread_result = read_in_full(p->pack_fd, hash, hashsz);\n> >  \tif (read_result < 0)\n> >  \t\treturn error_errno(\"error reading from %s\", p->pack_name);\n> > -\tif (read_result != sizeof(sha1))\n> > +\tif (read_result != hashsz)\n> >  \t\treturn error(\"packfile %s signature is unavailable\", p->pack_name);\n> > -\tidx_sha1 = ((unsigned char *)p->index_data) + p->index_size - 40;\n> > -\tif (hashcmp(sha1, idx_sha1))\n> > +\tidx_hash = ((unsigned char *)p->index_data) + p->index_size - hashsz * 2;\n> > +\tif (hashcmp(hash, idx_hash))\n> \n> Since the hash size is abstracted away, shouldn't this hashcmp become\n> oidcmp? (which still does not do the right thing, but at least it's\n> one less place to worry about)\n\nUnfortunately, I can't, because it's not an object ID.  I think the\ndecision was made to not transform non-object ID hashes into struct\nobject_id, which makes sense.  I suppose we could have an equivalent\nstruct hash or something for those other uses.\n\n> Same comment for other hashcmp in this patch.\n> \n> > @@ -675,7 +677,8 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local)\n> >  \tp->pack_size = st.st_size;\n> >  \tp->pack_local = local;\n> >  \tp->mtime = st.st_mtime;\n> > -\tif (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))\n> > +\tif (path_len < the_hash_algo->hexsz ||\n> > +\t    get_sha1_hex(path + path_len - the_hash_algo->hexsz, p->sha1))\n> \n> get_sha1_hex looks out of place when we start going with\n> the_hash_algo. Maybe change to get_oid_hex() too.\n\nI believe this is the pack hash, which isn't an object ID.  I will\ntransform it to be called something other than \"sha1\" and allocate more\nmemory for it in a future series, though.\n\n> > @@ -1678,10 +1683,10 @@ int bsearch_pack(const struct object_id *oid, const struct packed_git *p, uint32\n> >  \n> >  \tindex_lookup = index_fanout + 4 * 256;\n> >  \tif (p->index_version == 1) {\n> > -\t\tindex_lookup_width = 24;\n> > +\t\tindex_lookup_width = hashsz + 4;\n> \n> You did good research to spot this 24 constant ;-)\n\nThanks.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"346458","messageId":"CACsJy8C1nLTOZFvdgrRYDTXbQhdt5vkbVxHSEiAVuH6Vo8WB_Q@mail.gmail.com","threadId":"48349","inReplyTo":"20180502001140.GH13217@genre.crustytoothpaste.net","subject":"Re: [PATCH 08/41] packfile: abstract away hash constant values","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-05-02T15:26:25Z","receivedAt":"2018-05-02T15:27:01Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, May 2, 2018 at 2:11 AM, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> On Tue, May 01, 2018 at 12:22:43PM +0200, Duy Nguyen wrote:\n>> On Mon, Apr 23, 2018 at 11:39:18PM +0000, brian m. carlson wrote:\n>> > There are several instances of the constant 20 and 20-based values in\n>> > the packfile code.  Abstract away dependence on SHA-1 by using the\n>> > values from the_hash_algo instead.\n>>\n>> While we're abstracting away 20. There's the only 20 left in\n>> sha1_file.c that should also be gone. But I guess you could do that\n>> later since you need to rename fill_sha1_path to\n>> fill_loose_object_path or something.\n>\n> I'm already working on knocking those out.\n\nYeah I checked out your part14 branch after writing this note :P You\nstill need to rename the function though. I can remind that again when\npart14 is sent out.\n\n>> > @@ -507,15 +509,15 @@ static int open_packed_git_1(struct packed_git *p)\n>> >                          \" while index indicates %\"PRIu32\" objects\",\n>> >                          p->pack_name, ntohl(hdr.hdr_entries),\n>> >                          p->num_objects);\n>> > -   if (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)\n>> > +   if (lseek(p->pack_fd, p->pack_size - hashsz, SEEK_SET) == -1)\n>> >             return error(\"end of packfile %s is unavailable\", p->pack_name);\n>> > -   read_result = read_in_full(p->pack_fd, sha1, sizeof(sha1));\n>> > +   read_result = read_in_full(p->pack_fd, hash, hashsz);\n>> >     if (read_result < 0)\n>> >             return error_errno(\"error reading from %s\", p->pack_name);\n>> > -   if (read_result != sizeof(sha1))\n>> > +   if (read_result != hashsz)\n>> >             return error(\"packfile %s signature is unavailable\", p->pack_name);\n>> > -   idx_sha1 = ((unsigned char *)p->index_data) + p->index_size - 40;\n>> > -   if (hashcmp(sha1, idx_sha1))\n>> > +   idx_hash = ((unsigned char *)p->index_data) + p->index_size - hashsz * 2;\n>> > +   if (hashcmp(hash, idx_hash))\n>>\n>> Since the hash size is abstracted away, shouldn't this hashcmp become\n>> oidcmp? (which still does not do the right thing, but at least it's\n>> one less place to worry about)\n>\n> Unfortunately, I can't, because it's not an object ID.  I think the\n> decision was made to not transform non-object ID hashes into struct\n> object_id, which makes sense.  I suppose we could have an equivalent\n> struct hash or something for those other uses.\n\nI probably miss something, is hashcmp() supposed to stay after the\nconversion? And will it compare any hash (as configured in the_algo)\nor will it for SHA-1 only?\n\nIf hashcmp() will eventually compare the_algo->rawsz then yes this makes sense.\n\n>> > @@ -675,7 +677,8 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local)\n>> >     p->pack_size = st.st_size;\n>> >     p->pack_local = local;\n>> >     p->mtime = st.st_mtime;\n>> > -   if (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))\n>> > +   if (path_len < the_hash_algo->hexsz ||\n>> > +       get_sha1_hex(path + path_len - the_hash_algo->hexsz, p->sha1))\n>>\n>> get_sha1_hex looks out of place when we start going with\n>> the_hash_algo. Maybe change to get_oid_hex() too.\n>\n> I believe this is the pack hash, which isn't an object ID.  I will\n> transform it to be called something other than \"sha1\" and allocate more\n> memory for it in a future series, though.\n\nAh ok, it's the \"sha1\" in the name that bugged me. I'm all good then.\n-- \nDuy\n"},{"id":"346483","messageId":"20180502230555.GK13217@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"CACsJy8C1nLTOZFvdgrRYDTXbQhdt5vkbVxHSEiAVuH6Vo8WB_Q@mail.gmail.com","subject":"Re: [PATCH 08/41] packfile: abstract away hash constant values","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-05-02T23:05:55Z","receivedAt":"2018-05-02T23:06:04Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Wed, May 02, 2018 at 05:26:25PM +0200, Duy Nguyen wrote:\n> On Wed, May 2, 2018 at 2:11 AM, brian m. carlson\n> <sandals@crustytoothpaste.net> wrote:\n> > On Tue, May 01, 2018 at 12:22:43PM +0200, Duy Nguyen wrote:\n> >> While we're abstracting away 20. There's the only 20 left in\n> >> sha1_file.c that should also be gone. But I guess you could do that\n> >> later since you need to rename fill_sha1_path to\n> >> fill_loose_object_path or something.\n> >\n> > I'm already working on knocking those out.\n> \n> Yeah I checked out your part14 branch after writing this note :P You\n> still need to rename the function though. I can remind that again when\n> part14 is sent out.\n\nI've made a note in my project notes.\n\n> > Unfortunately, I can't, because it's not an object ID.  I think the\n> > decision was made to not transform non-object ID hashes into struct\n> > object_id, which makes sense.  I suppose we could have an equivalent\n> > struct hash or something for those other uses.\n> \n> I probably miss something, is hashcmp() supposed to stay after the\n> conversion? And will it compare any hash (as configured in the_algo)\n> or will it for SHA-1 only?\n\nYes, it will stick around for the handful of places where we have hashes\nlike pack checksums.\n\n> If hashcmp() will eventually compare the_algo->rawsz then yes this makes sense.\n\nThat's my intention, yes.\n\n> > I believe this is the pack hash, which isn't an object ID.  I will\n> > transform it to be called something other than \"sha1\" and allocate more\n> > memory for it in a future series, though.\n> \n> Ah ok, it's the \"sha1\" in the name that bugged me. I'm all good then.\n\nAlso noted in my project notes.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"346609","messageId":"20180504012943.GO13217@genre.crustytoothpaste.net","threadId":"48349","inReplyTo":"20180501104257.GG15820@duynguyen.home","subject":"Re: [PATCH 39/41] Update shell scripts to compute empty tree object ID","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2018-05-04T01:29:44Z","receivedAt":"2018-05-04T01:29:56Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Tue, May 01, 2018 at 12:42:57PM +0200, Duy Nguyen wrote:\n> On Mon, Apr 23, 2018 at 11:39:49PM +0000, brian m. carlson wrote:\n> > Several of our shell scripts hard-code the object ID of the empty tree.\n> > To avoid any problems when changing hashes, compute this value on\n> > startup of the script.  For performance, store the value in a variable\n> > and reuse it throughout the life of the script.\n> > \n> > Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> > ---\n> >  git-filter-branch.sh               | 4 +++-\n> >  git-rebase--interactive.sh         | 4 +++-\n> >  templates/hooks--pre-commit.sample | 2 +-\n> >  3 files changed, 7 insertions(+), 3 deletions(-)\n> > \n> > diff --git a/git-filter-branch.sh b/git-filter-branch.sh\n> > index 64f21547c1..ccceaf19a7 100755\n> > --- a/git-filter-branch.sh\n> > +++ b/git-filter-branch.sh\n> > @@ -11,6 +11,8 @@\n> >  # The following functions will also be available in the commit filter:\n> >  \n> >  functions=$(cat << \\EOF\n> > +EMPTY_TREE=$(git hash-object -t tree /dev/null)\n> \n> All scripts (except those example hooks) must source\n> git-sh-setup. Should we define this in there instead?\n\nI think at this point, I'm okay with special-casing these two uses, but\nI would generally say that if we gain any more we should move it there.\n\nThere's a trade-off between the benefits of reuse here and the fact that\nwe're forking a process, which incurs a cost, especially on Windows.\n\nI'm open to hearing other opinions, of course.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"}]}