{"thread":{"id":"47186","subject":"[PATCH v3 0/4] Hash abstraction","startedAt":"2017-11-12T21:29:18Z","lastAt":"2017-11-22T16:57:23Z","messageCount":9,"participants":["brian m. carlson","Junio C Hamano","Stefan Beller"],"isPatch":true,"patchVersion":3,"patchTotal":4},"messages":[{"id":"332367","messageId":"20171112212854.791179-1-sandals@crustytoothpaste.net","threadId":"47186","inReplyTo":null,"subject":"[PATCH v3 0/4] Hash abstraction","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2017-11-12T21:28:50Z","receivedAt":"2017-11-12T21:29:18Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"This is a series proposing a basic abstraction for hash functions.\n\nThe full description of the series can be found here:\nhttps://public-inbox.org/git/20171028181239.59458-1-sandals@crustytoothpaste.net/\n\nAt the bottom of this message is the output of git tbdiff between v2 and\nv3.\n\nChanges from v2:\n* Remove inline.\n* Add dummy functions that call die for unknown hash implementation.\n* Move structure definitions to hash.h and include git-compat-util.h in\n  hash.h.\n* Rename current_hash to the_hash_algo.\n* Use repo_set_hash_algo everywhere we set the hash algorithm for a\n  struct repository.\n\nChanges from v1:\n* Rebase onto 2.15-rc2.\n* Fix the uninitialized value that Peff pointed out.  This fixes the\n  error, but leaves the code in the same place, since I think it's where\n  it should be.\n* Improve commit message to explain the meaning of current_hash WRT the\n  transition plan.\n* Added an unknown hash algorithm constant and value to better implement\n  the transition plan.\n* Explain in the commit message why hex size and binary size are both\n  provided.\n* Add a format_id field to the struct, in coordination with the\n  transition plan.\n* Improve comments for struct fields and constants.\n\nbrian m. carlson (4):\n  setup: expose enumerated repo info\n  Add structure representing hash algorithm\n  Integrate hash algorithm support with repo setup\n  Switch empty tree and blob lookups to use hash abstraction\n\n builtin/am.c       |  2 +-\n builtin/checkout.c |  2 +-\n builtin/diff.c     |  2 +-\n builtin/pull.c     |  2 +-\n cache.h            | 12 +++++++----\n diff-lib.c         |  2 +-\n hash.h             | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n merge-recursive.c  |  2 +-\n notes-merge.c      |  2 +-\n repository.c       |  7 +++++++\n repository.h       |  5 +++++\n sequencer.c        |  6 +++---\n setup.c            | 49 +++++++++++++++++++++++++--------------------\n sha1_file.c        | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n submodule.c        |  2 +-\n 15 files changed, 174 insertions(+), 36 deletions(-)\n\ngit-tbdiff output:\n\n1: 7de9bc96ff = 1: 1ec859c3a8 setup: expose enumerated repo info\n2: fb5099972b ! 2: c9c628b745 Add structure representing hash algorithm\n    @@ -23,16 +23,29 @@\n         accept input from the user that might be in SHA-1 or in the NewHash\n         format.  Since we cannot know which the user has provided, add a\n         constant representing the unknown algorithm to allow us to indicate that\n    -    we must look the correct value up.\n    +    we must look the correct value up.  Provide dummy API functions that die\n    +    in this case.\n    +    \n    +    Finally, include git-compat-util.h in hash.h so that the required types\n    +    are available.  This aids people using automated tools their editors.\n         \n         Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n     \n    -diff --git a/cache.h b/cache.h\n    ---- a/cache.h\n    -+++ b/cache.h\n    +diff --git a/hash.h b/hash.h\n    +--- a/hash.h\n    ++++ b/hash.h\n     @@\n    - \tunsigned char hash[GIT_MAX_RAWSZ];\n    - };\n    + #ifndef HASH_H\n    + #define HASH_H\n    + \n    ++#include \"git-compat-util.h\"\n    ++\n    + #if defined(SHA1_PPC)\n    + #include \"ppc/sha1.h\"\n    + #elif defined(SHA1_APPLE)\n    +@@\n    + #include \"block-sha1/sha1.h\"\n    + #endif\n      \n     +/*\n     + * Note that these constants are suitable for indexing the hash_algos array and\n    @@ -89,9 +102,7 @@\n     +};\n     +extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];\n     +\n    - #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)\n    - #define DTYPE(de)\t((de)->d_type)\n    - #else\n    + #endif\n     \n     diff --git a/sha1_file.c b/sha1_file.c\n     --- a/sha1_file.c\n    @@ -100,19 +111,34 @@\n      \tEMPTY_BLOB_SHA1_BIN_LITERAL\n      };\n      \n    -+static inline void git_hash_sha1_init(void *ctx)\n    ++static void git_hash_sha1_init(void *ctx)\n     +{\n     +\tgit_SHA1_Init((git_SHA_CTX *)ctx);\n     +}\n     +\n    -+static inline void git_hash_sha1_update(void *ctx, const void *data, size_t len)\n    ++static void git_hash_sha1_update(void *ctx, const void *data, size_t len)\n     +{\n     +\tgit_SHA1_Update((git_SHA_CTX *)ctx, data, len);\n     +}\n     +\n    -+static inline void git_hash_sha1_final(unsigned char *hash, void *ctx)\n    ++static void git_hash_sha1_final(unsigned char *hash, void *ctx)\n     +{\n     +\tgit_SHA1_Final(hash, (git_SHA_CTX *)ctx);\n    ++}\n    ++\n    ++static void git_hash_unknown_init(void *ctx)\n    ++{\n    ++\tdie(\"trying to init unknown hash\");\n    ++}\n    ++\n    ++static void git_hash_unknown_update(void *ctx, const void *data, size_t len)\n    ++{\n    ++\tdie(\"trying to update unknown hash\");\n    ++}\n    ++\n    ++static void git_hash_unknown_final(unsigned char *hash, void *ctx)\n    ++{\n    ++\tdie(\"trying to finalize unknown hash\");\n     +}\n     +\n     +const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n    @@ -122,9 +148,9 @@\n     +\t\t0,\n     +\t\t0,\n     +\t\t0,\n    -+\t\tNULL,\n    -+\t\tNULL,\n    -+\t\tNULL,\n    ++\t\tgit_hash_unknown_init,\n    ++\t\tgit_hash_unknown_update,\n    ++\t\tgit_hash_unknown_final,\n     +\t\tNULL,\n     +\t\tNULL,\n     +\t},\n3: da7ea2e17a ! 3: 30ad79b734 Integrate hash algorithm support with repo setup\n    @@ -9,7 +9,7 @@\n         read_repository_format.  In the future, we'll enumerate this value from\n         the configuration.\n         \n    -    Add a constant, current_hash, which points to the hash_algo structure\n    +    Add a constant, the_hash_algo, which points to the hash_algo structure\n         pointer in the repository global.  Note that this is the hash which is\n         used to serialize data to disk, not the hash which is used to display\n         items to the user.  The transition plan anticipates that these may be\n    @@ -33,10 +33,10 @@\n      #ifndef platform_SHA_CTX\n      /*\n     @@\n    + \tunsigned char hash[GIT_MAX_RAWSZ];\n      };\n    - extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];\n      \n    -+#define current_hash the_repository->hash_algo\n    ++#define the_hash_algo the_repository->hash_algo\n     +\n      #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)\n      #define DTYPE(de)\t((de)->d_type)\n    @@ -69,7 +69,7 @@\n      \tif (read_and_verify_repository_format(&format, repo->commondir))\n      \t\tgoto error;\n      \n    -+\trepo->hash_algo = &hash_algos[format.hash_algo];\n    ++\trepo_set_hash_algo(repo, format.hash_algo);\n     +\n      \tif (worktree)\n      \t\trepo_set_worktree(repo, worktree);\n4: d17b67e4ed ! 4: cfe5e8cadd Switch empty tree and blob lookups to use hash abstraction\n    @@ -16,7 +16,7 @@\n      \t\ttree = lookup_tree(&head);\n      \telse\n     -\t\ttree = lookup_tree(&empty_tree_oid);\n    -+\t\ttree = lookup_tree(current_hash->empty_tree);\n    ++\t\ttree = lookup_tree(the_hash_algo->empty_tree);\n      \n      \tfp = xfopen(am_path(state, \"patch\"), \"w\");\n      \tinit_revisions(&rev_info, NULL);\n    @@ -29,7 +29,7 @@\n      \t\ttree = parse_tree_indirect(old->commit ?\n      \t\t\t\t\t   &old->commit->object.oid :\n     -\t\t\t\t\t   &empty_tree_oid);\n    -+\t\t\t\t\t   current_hash->empty_tree);\n    ++\t\t\t\t\t   the_hash_algo->empty_tree);\n      \t\tinit_tree_desc(&trees[0], tree->buffer, tree->size);\n      \t\ttree = parse_tree_indirect(&new->commit->object.oid);\n      \t\tinit_tree_desc(&trees[1], tree->buffer, tree->size);\n    @@ -42,7 +42,7 @@\n      \t\t\t\tif (!rev.pending.nr) {\n      \t\t\t\t\tstruct tree *tree;\n     -\t\t\t\t\ttree = lookup_tree(&empty_tree_oid);\n    -+\t\t\t\t\ttree = lookup_tree(current_hash->empty_tree);\n    ++\t\t\t\t\ttree = lookup_tree(the_hash_algo->empty_tree);\n      \t\t\t\t\tadd_pending_object(&rev, &tree->object, \"HEAD\");\n      \t\t\t\t}\n      \t\t\t\tbreak;\n    @@ -55,10 +55,10 @@\n      \t * branch.\n      \t */\n     -\tif (checkout_fast_forward(&empty_tree_oid, merge_head, 0))\n    -+\tif (checkout_fast_forward(current_hash->empty_tree, merge_head, 0))\n    ++\tif (checkout_fast_forward(the_hash_algo->empty_tree, merge_head, 0))\n      \t\treturn 1;\n      \n    - \tif (update_ref(\"initial pull\", \"HEAD\", merge_head->hash, curr_head->hash, 0, UPDATE_REFS_DIE_ON_ERR))\n    + \tif (update_ref(\"initial pull\", \"HEAD\", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))\n     \n     diff --git a/cache.h b/cache.h\n     --- a/cache.h\n    @@ -68,25 +68,25 @@\n      static inline int is_empty_blob_sha1(const unsigned char *sha1)\n      {\n     -\treturn !hashcmp(sha1, EMPTY_BLOB_SHA1_BIN);\n    -+\treturn !hashcmp(sha1, current_hash->empty_blob->hash);\n    ++\treturn !hashcmp(sha1, the_hash_algo->empty_blob->hash);\n      }\n      \n      static inline int is_empty_blob_oid(const struct object_id *oid)\n      {\n     -\treturn !hashcmp(oid->hash, EMPTY_BLOB_SHA1_BIN);\n    -+\treturn !oidcmp(oid, current_hash->empty_blob);\n    ++\treturn !oidcmp(oid, the_hash_algo->empty_blob);\n      }\n      \n      static inline int is_empty_tree_sha1(const unsigned char *sha1)\n      {\n     -\treturn !hashcmp(sha1, EMPTY_TREE_SHA1_BIN);\n    -+\treturn !hashcmp(sha1, current_hash->empty_tree->hash);\n    ++\treturn !hashcmp(sha1, the_hash_algo->empty_tree->hash);\n      }\n      \n      static inline int is_empty_tree_oid(const struct object_id *oid)\n      {\n     -\treturn !hashcmp(oid->hash, EMPTY_TREE_SHA1_BIN);\n    -+\treturn !oidcmp(oid, current_hash->empty_tree);\n    ++\treturn !oidcmp(oid, the_hash_algo->empty_tree);\n      }\n      \n      /* set default permissions by passing mode arguments to open(2) */\n    @@ -99,7 +99,7 @@\n      \t\t\t\t   ce_intent_to_add(ce)) {\n      \t\t\t\tdiff_addremove(&revs->diffopt, '+', ce->ce_mode,\n     -\t\t\t\t\t       &empty_tree_oid, 0,\n    -+\t\t\t\t\t       current_hash->empty_tree, 0,\n    ++\t\t\t\t\t       the_hash_algo->empty_tree, 0,\n      \t\t\t\t\t       ce->name, 0);\n      \t\t\t\tcontinue;\n      \t\t\t}\n    @@ -112,7 +112,7 @@\n      \t\tstruct tree *tree;\n      \n     -\t\ttree = lookup_tree(&empty_tree_oid);\n    -+\t\ttree = lookup_tree(current_hash->empty_tree);\n    ++\t\ttree = lookup_tree(the_hash_algo->empty_tree);\n      \t\tmerged_common_ancestors = make_virtual_commit(tree, \"ancestor\");\n      \t}\n      \n    @@ -125,7 +125,7 @@\n      \tif (!bases) {\n      \t\tbase_oid = &null_oid;\n     -\t\tbase_tree_oid = &empty_tree_oid;\n    -+\t\tbase_tree_oid = current_hash->empty_tree;\n    ++\t\tbase_tree_oid = the_hash_algo->empty_tree;\n      \t\tif (o->verbosity >= 4)\n      \t\t\tprintf(\"No merge base found; doing history-less merge\\n\");\n      \t} else if (!bases->next) {\n    @@ -138,7 +138,7 @@\n      static struct tree *empty_tree(void)\n      {\n     -\treturn lookup_tree(&empty_tree_oid);\n    -+\treturn lookup_tree(current_hash->empty_tree);\n    ++\treturn lookup_tree(the_hash_algo->empty_tree);\n      }\n      \n      static int error_dirty_index(struct replay_opts *opts)\n    @@ -147,7 +147,7 @@\n      \t\tptree_oid = &parent->tree->object.oid;\n      \t} else {\n     -\t\tptree_oid = &empty_tree_oid; /* commit is root */\n    -+\t\tptree_oid = current_hash->empty_tree; /* commit is root */\n    ++\t\tptree_oid = the_hash_algo->empty_tree; /* commit is root */\n      \t}\n      \n      \treturn !oidcmp(ptree_oid, &commit->tree->object.oid);\n    @@ -156,10 +156,10 @@\n      \t\tunborn = get_oid(\"HEAD\", &head);\n      \t\tif (unborn)\n     -\t\t\toidcpy(&head, &empty_tree_oid);\n    -+\t\t\toidcpy(&head, current_hash->empty_tree);\n    - \t\tif (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : \"HEAD\", 0, 0))\n    ++\t\t\toidcpy(&head, the_hash_algo->empty_tree);\n    + \t\tif (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : \"HEAD\",\n    + \t\t\t\t       NULL, 0))\n      \t\t\treturn error_dirty_index(opts);\n    - \t}\n     \n     diff --git a/submodule.c b/submodule.c\n     --- a/submodule.c\n    @@ -169,7 +169,7 @@\n      \t\tunsigned dirty_submodule)\n      {\n     -\tconst struct object_id *old = &empty_tree_oid, *new = &empty_tree_oid;\n    -+\tconst struct object_id *old = current_hash->empty_tree, *new = current_hash->empty_tree;\n    ++\tconst struct object_id *old = the_hash_algo->empty_tree, *new = the_hash_algo->empty_tree;\n      \tstruct commit *left = NULL, *right = NULL;\n      \tstruct commit_list *merge_bases = NULL;\n      \tstruct child_process cp = CHILD_PROCESS_INIT;\n"},{"id":"332368","messageId":"20171112212854.791179-2-sandals@crustytoothpaste.net","threadId":"47186","inReplyTo":"20171112212854.791179-1-sandals@crustytoothpaste.net","subject":"[PATCH v3 1/4] setup: expose enumerated repo info","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2017-11-12T21:28:51Z","receivedAt":"2017-11-12T21:29:21Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"We enumerate several different items as part of struct\nrepository_format, but then actually set up those values using the\nglobal variables we've initialized from them.  Instead, let's pass a\npointer to the structure down to the code where we enumerate these\nvalues, so we can later on use those values directly to perform setup.\n\nThis technique makes it easier for us to determine additional items\nabout the repository format (such as the hash algorithm) and then use\nthem for setup later on, without needing to add additional global\nvariables.  We can't avoid using the existing global variables since\nthey're intricately intertwined with how things work at the moment, but\nthis improves things for the future.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n setup.c | 46 +++++++++++++++++++++++++---------------------\n 1 file changed, 25 insertions(+), 21 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 94768512b7..cf1b22cd30 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -434,16 +434,15 @@ static int check_repo_format(const char *var, const char *value, void *vdata)\n \treturn 0;\n }\n \n-static int check_repository_format_gently(const char *gitdir, int *nongit_ok)\n+static int check_repository_format_gently(const char *gitdir, struct repository_format *candidate, int *nongit_ok)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n \tstruct strbuf err = STRBUF_INIT;\n-\tstruct repository_format candidate;\n \tint has_common;\n \n \thas_common = get_common_dir(&sb, gitdir);\n \tstrbuf_addstr(&sb, \"/config\");\n-\tread_repository_format(&candidate, sb.buf);\n+\tread_repository_format(candidate, sb.buf);\n \tstrbuf_release(&sb);\n \n \t/*\n@@ -451,10 +450,10 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)\n \t * we treat a missing config as a silent \"ok\", even when nongit_ok\n \t * is unset.\n \t */\n-\tif (candidate.version < 0)\n+\tif (candidate->version < 0)\n \t\treturn 0;\n \n-\tif (verify_repository_format(&candidate, &err) < 0) {\n+\tif (verify_repository_format(candidate, &err) < 0) {\n \t\tif (nongit_ok) {\n \t\t\twarning(\"%s\", err.buf);\n \t\t\tstrbuf_release(&err);\n@@ -464,21 +463,21 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)\n \t\tdie(\"%s\", err.buf);\n \t}\n \n-\trepository_format_precious_objects = candidate.precious_objects;\n-\tstring_list_clear(&candidate.unknown_extensions, 0);\n+\trepository_format_precious_objects = candidate->precious_objects;\n+\tstring_list_clear(&candidate->unknown_extensions, 0);\n \tif (!has_common) {\n-\t\tif (candidate.is_bare != -1) {\n-\t\t\tis_bare_repository_cfg = candidate.is_bare;\n+\t\tif (candidate->is_bare != -1) {\n+\t\t\tis_bare_repository_cfg = candidate->is_bare;\n \t\t\tif (is_bare_repository_cfg == 1)\n \t\t\t\tinside_work_tree = -1;\n \t\t}\n-\t\tif (candidate.work_tree) {\n+\t\tif (candidate->work_tree) {\n \t\t\tfree(git_work_tree_cfg);\n-\t\t\tgit_work_tree_cfg = candidate.work_tree;\n+\t\t\tgit_work_tree_cfg = candidate->work_tree;\n \t\t\tinside_work_tree = -1;\n \t\t}\n \t} else {\n-\t\tfree(candidate.work_tree);\n+\t\tfree(candidate->work_tree);\n \t}\n \n \treturn 0;\n@@ -625,6 +624,7 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)\n \n static const char *setup_explicit_git_dir(const char *gitdirenv,\n \t\t\t\t\t  struct strbuf *cwd,\n+\t\t\t\t\t  struct repository_format *repo_fmt,\n \t\t\t\t\t  int *nongit_ok)\n {\n \tconst char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);\n@@ -650,7 +650,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,\n \t\tdie(\"Not a git repository: '%s'\", gitdirenv);\n \t}\n \n-\tif (check_repository_format_gently(gitdirenv, nongit_ok)) {\n+\tif (check_repository_format_gently(gitdirenv, repo_fmt, nongit_ok)) {\n \t\tfree(gitfile);\n \t\treturn NULL;\n \t}\n@@ -723,9 +723,10 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,\n \n static const char *setup_discovered_git_dir(const char *gitdir,\n \t\t\t\t\t    struct strbuf *cwd, int offset,\n+\t\t\t\t\t    struct repository_format *repo_fmt,\n \t\t\t\t\t    int *nongit_ok)\n {\n-\tif (check_repository_format_gently(gitdir, nongit_ok))\n+\tif (check_repository_format_gently(gitdir, repo_fmt, nongit_ok))\n \t\treturn NULL;\n \n \t/* --work-tree is set without --git-dir; use discovered one */\n@@ -737,7 +738,7 @@ static const char *setup_discovered_git_dir(const char *gitdir,\n \t\t\tgitdir = to_free = real_pathdup(gitdir, 1);\n \t\tif (chdir(cwd->buf))\n \t\t\tdie_errno(\"Could not come back to cwd\");\n-\t\tret = setup_explicit_git_dir(gitdir, cwd, nongit_ok);\n+\t\tret = setup_explicit_git_dir(gitdir, cwd, repo_fmt, nongit_ok);\n \t\tfree(to_free);\n \t\treturn ret;\n \t}\n@@ -769,11 +770,12 @@ static const char *setup_discovered_git_dir(const char *gitdir,\n \n /* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */\n static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,\n+\t\t\t\t      struct repository_format *repo_fmt,\n \t\t\t\t      int *nongit_ok)\n {\n \tint root_len;\n \n-\tif (check_repository_format_gently(\".\", nongit_ok))\n+\tif (check_repository_format_gently(\".\", repo_fmt, nongit_ok))\n \t\treturn NULL;\n \n \tsetenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, \"0\", 1);\n@@ -785,7 +787,7 @@ static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,\n \t\tgitdir = offset == cwd->len ? \".\" : xmemdupz(cwd->buf, offset);\n \t\tif (chdir(cwd->buf))\n \t\t\tdie_errno(\"Could not come back to cwd\");\n-\t\treturn setup_explicit_git_dir(gitdir, cwd, nongit_ok);\n+\t\treturn setup_explicit_git_dir(gitdir, cwd, repo_fmt, nongit_ok);\n \t}\n \n \tinside_git_dir = 1;\n@@ -1026,6 +1028,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tstatic struct strbuf cwd = STRBUF_INIT;\n \tstruct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;\n \tconst char *prefix;\n+\tstruct repository_format repo_fmt;\n \n \t/*\n \t * We may have read an incomplete configuration before\n@@ -1053,18 +1056,18 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\tprefix = NULL;\n \t\tbreak;\n \tcase GIT_DIR_EXPLICIT:\n-\t\tprefix = setup_explicit_git_dir(gitdir.buf, &cwd, nongit_ok);\n+\t\tprefix = setup_explicit_git_dir(gitdir.buf, &cwd, &repo_fmt, nongit_ok);\n \t\tbreak;\n \tcase GIT_DIR_DISCOVERED:\n \t\tif (dir.len < cwd.len && chdir(dir.buf))\n \t\t\tdie(_(\"Cannot change to '%s'\"), dir.buf);\n \t\tprefix = setup_discovered_git_dir(gitdir.buf, &cwd, dir.len,\n-\t\t\t\t\t\t  nongit_ok);\n+\t\t\t\t\t\t  &repo_fmt, nongit_ok);\n \t\tbreak;\n \tcase GIT_DIR_BARE:\n \t\tif (dir.len < cwd.len && chdir(dir.buf))\n \t\t\tdie(_(\"Cannot change to '%s'\"), dir.buf);\n-\t\tprefix = setup_bare_git_dir(&cwd, dir.len, nongit_ok);\n+\t\tprefix = setup_bare_git_dir(&cwd, dir.len, &repo_fmt, nongit_ok);\n \t\tbreak;\n \tcase GIT_DIR_HIT_CEILING:\n \t\tprefix = setup_nongit(cwd.buf, nongit_ok);\n@@ -1171,7 +1174,8 @@ int git_config_perm(const char *var, const char *value)\n \n void check_repository_format(void)\n {\n-\tcheck_repository_format_gently(get_git_dir(), NULL);\n+\tstruct repository_format repo_fmt;\n+\tcheck_repository_format_gently(get_git_dir(), &repo_fmt, NULL);\n \tstartup_info->have_repository = 1;\n }\n \n"},{"id":"332369","messageId":"20171112212854.791179-3-sandals@crustytoothpaste.net","threadId":"47186","inReplyTo":"20171112212854.791179-1-sandals@crustytoothpaste.net","subject":"[PATCH v3 2/4] Add structure representing hash algorithm","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2017-11-12T21:28:52Z","receivedAt":"2017-11-12T21:29:23Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Since in the future we want to support an additional hash algorithm, add\na structure that represents a hash algorithm and all the data that must\ngo along with it.  Add a constant to allow easy enumeration of hash\nalgorithms.  Implement function typedefs to create an abstract API that\ncan be used by any hash algorithm, and wrappers for the existing SHA1\nfunctions that conform to this API.\n\nExpose a value for hex size as well as binary size.  While one will\nalways be twice the other, the two values are both used extremely\ncommonly throughout the codebase and providing both leads to improved\nreadability.\n\nDon't include an entry in the hash algorithm structure for the null\nobject ID.  As this value is all zeros, any suitably sized all-zero\nobject ID can be used, and there's no need to store a given one on a\nper-hash basis.\n\nThe current hash function transition plan envisions a time when we will\naccept input from the user that might be in SHA-1 or in the NewHash\nformat.  Since we cannot know which the user has provided, add a\nconstant representing the unknown algorithm to allow us to indicate that\nwe must look the correct value up.  Provide dummy API functions that die\nin this case.\n\nFinally, include git-compat-util.h in hash.h so that the required types\nare available.  This aids people using automated tools their editors.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n hash.h      | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n sha1_file.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 115 insertions(+)\n\ndiff --git a/hash.h b/hash.h\nindex 024d0d3d50..7d7a864f5d 100644\n--- a/hash.h\n+++ b/hash.h\n@@ -1,6 +1,8 @@\n #ifndef HASH_H\n #define HASH_H\n \n+#include \"git-compat-util.h\"\n+\n #if defined(SHA1_PPC)\n #include \"ppc/sha1.h\"\n #elif defined(SHA1_APPLE)\n@@ -13,4 +15,59 @@\n #include \"block-sha1/sha1.h\"\n #endif\n \n+/*\n+ * Note that these constants are suitable for indexing the hash_algos array and\n+ * comparing against each other, but are otherwise arbitrary, so they should not\n+ * be exposed to the user or serialized to disk.  To know whether a\n+ * git_hash_algo struct points to some usable hash function, test the format_id\n+ * field for being non-zero.  Use the name field for user-visible situations and\n+ * the format_id field for fixed-length fields on disk.\n+ */\n+/* An unknown hash function. */\n+#define GIT_HASH_UNKNOWN 0\n+/* SHA-1 */\n+#define GIT_HASH_SHA1 1\n+/* Number of algorithms supported (including unknown). */\n+#define GIT_HASH_NALGOS (GIT_HASH_SHA1 + 1)\n+\n+typedef void (*git_hash_init_fn)(void *ctx);\n+typedef void (*git_hash_update_fn)(void *ctx, const void *in, size_t len);\n+typedef void (*git_hash_final_fn)(unsigned char *hash, void *ctx);\n+\n+struct git_hash_algo {\n+\t/*\n+\t * The name of the algorithm, as appears in the config file and in\n+\t * messages.\n+\t */\n+\tconst char *name;\n+\n+\t/* A four-byte version identifier, used in pack indices. */\n+\tuint32_t format_id;\n+\n+\t/* The size of a hash context (e.g. git_SHA_CTX). */\n+\tsize_t ctxsz;\n+\n+\t/* The length of the hash in binary. */\n+\tsize_t rawsz;\n+\n+\t/* The length of the hash in hex characters. */\n+\tsize_t hexsz;\n+\n+\t/* The hash initialization function. */\n+\tgit_hash_init_fn init_fn;\n+\n+\t/* The hash update function. */\n+\tgit_hash_update_fn update_fn;\n+\n+\t/* The hash finalization function. */\n+\tgit_hash_final_fn final_fn;\n+\n+\t/* The OID of the empty tree. */\n+\tconst struct object_id *empty_tree;\n+\n+\t/* The OID of the empty blob. */\n+\tconst struct object_id *empty_blob;\n+};\n+extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];\n+\n #endif\ndiff --git a/sha1_file.c b/sha1_file.c\nindex d708981376..a04389be71 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -39,6 +39,64 @@ const struct object_id empty_blob_oid = {\n \tEMPTY_BLOB_SHA1_BIN_LITERAL\n };\n \n+static void git_hash_sha1_init(void *ctx)\n+{\n+\tgit_SHA1_Init((git_SHA_CTX *)ctx);\n+}\n+\n+static void git_hash_sha1_update(void *ctx, const void *data, size_t len)\n+{\n+\tgit_SHA1_Update((git_SHA_CTX *)ctx, data, len);\n+}\n+\n+static void git_hash_sha1_final(unsigned char *hash, void *ctx)\n+{\n+\tgit_SHA1_Final(hash, (git_SHA_CTX *)ctx);\n+}\n+\n+static void git_hash_unknown_init(void *ctx)\n+{\n+\tdie(\"trying to init unknown hash\");\n+}\n+\n+static void git_hash_unknown_update(void *ctx, const void *data, size_t len)\n+{\n+\tdie(\"trying to update unknown hash\");\n+}\n+\n+static void git_hash_unknown_final(unsigned char *hash, void *ctx)\n+{\n+\tdie(\"trying to finalize unknown hash\");\n+}\n+\n+const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {\n+\t{\n+\t\tNULL,\n+\t\t0x00000000,\n+\t\t0,\n+\t\t0,\n+\t\t0,\n+\t\tgit_hash_unknown_init,\n+\t\tgit_hash_unknown_update,\n+\t\tgit_hash_unknown_final,\n+\t\tNULL,\n+\t\tNULL,\n+\t},\n+\t{\n+\t\t\"sha-1\",\n+\t\t/* \"sha1\", big-endian */\n+\t\t0x73686131,\n+\t\tsizeof(git_SHA_CTX),\n+\t\tGIT_SHA1_RAWSZ,\n+\t\tGIT_SHA1_HEXSZ,\n+\t\tgit_hash_sha1_init,\n+\t\tgit_hash_sha1_update,\n+\t\tgit_hash_sha1_final,\n+\t\t&empty_tree_oid,\n+\t\t&empty_blob_oid,\n+\t},\n+};\n+\n /*\n  * This is meant to hold a *small* number of objects that you would\n  * want read_sha1_file() to be able to return, but yet you do not want\n"},{"id":"332370","messageId":"20171112212854.791179-5-sandals@crustytoothpaste.net","threadId":"47186","inReplyTo":"20171112212854.791179-1-sandals@crustytoothpaste.net","subject":"[PATCH v3 4/4] Switch empty tree and blob lookups to use hash abstraction","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2017-11-12T21:28:54Z","receivedAt":"2017-11-12T21:29:24Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"Switch the uses of empty_tree_oid and empty_blob_oid to use the\ncurrent_hash abstraction that represents the current hash algorithm in\nuse.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n builtin/am.c       | 2 +-\n builtin/checkout.c | 2 +-\n builtin/diff.c     | 2 +-\n builtin/pull.c     | 2 +-\n cache.h            | 8 ++++----\n diff-lib.c         | 2 +-\n merge-recursive.c  | 2 +-\n notes-merge.c      | 2 +-\n sequencer.c        | 6 +++---\n submodule.c        | 2 +-\n 10 files changed, 15 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 92c4853505..99dbde3e85 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1433,7 +1433,7 @@ static void write_index_patch(const struct am_state *state)\n \tif (!get_oid_tree(\"HEAD\", &head))\n \t\ttree = lookup_tree(&head);\n \telse\n-\t\ttree = lookup_tree(&empty_tree_oid);\n+\t\ttree = lookup_tree(the_hash_algo->empty_tree);\n \n \tfp = xfopen(am_path(state, \"patch\"), \"w\");\n \tinit_revisions(&rev_info, NULL);\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 6c2b4cd419..2b64805f35 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -514,7 +514,7 @@ static int merge_working_tree(const struct checkout_opts *opts,\n \t\t}\n \t\ttree = parse_tree_indirect(old->commit ?\n \t\t\t\t\t   &old->commit->object.oid :\n-\t\t\t\t\t   &empty_tree_oid);\n+\t\t\t\t\t   the_hash_algo->empty_tree);\n \t\tinit_tree_desc(&trees[0], tree->buffer, tree->size);\n \t\ttree = parse_tree_indirect(&new->commit->object.oid);\n \t\tinit_tree_desc(&trees[1], tree->buffer, tree->size);\ndiff --git a/builtin/diff.c b/builtin/diff.c\nindex 9808d062a8..16bfb22f73 100644\n--- a/builtin/diff.c\n+++ b/builtin/diff.c\n@@ -379,7 +379,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t\t\t\tadd_head_to_pending(&rev);\n \t\t\t\tif (!rev.pending.nr) {\n \t\t\t\t\tstruct tree *tree;\n-\t\t\t\t\ttree = lookup_tree(&empty_tree_oid);\n+\t\t\t\t\ttree = lookup_tree(the_hash_algo->empty_tree);\n \t\t\t\t\tadd_pending_object(&rev, &tree->object, \"HEAD\");\n \t\t\t\t}\n \t\t\t\tbreak;\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex a28f0ffadd..3d26f8ff32 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -545,7 +545,7 @@ static int pull_into_void(const struct object_id *merge_head,\n \t * index/worktree changes that the user already made on the unborn\n \t * branch.\n \t */\n-\tif (checkout_fast_forward(&empty_tree_oid, merge_head, 0))\n+\tif (checkout_fast_forward(the_hash_algo->empty_tree, merge_head, 0))\n \t\treturn 1;\n \n \tif (update_ref(\"initial pull\", \"HEAD\", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))\ndiff --git a/cache.h b/cache.h\nindex c238688f6c..d68895b45f 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1024,22 +1024,22 @@ 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, EMPTY_BLOB_SHA1_BIN);\n+\treturn !hashcmp(sha1, the_hash_algo->empty_blob->hash);\n }\n \n static inline int is_empty_blob_oid(const struct object_id *oid)\n {\n-\treturn !hashcmp(oid->hash, EMPTY_BLOB_SHA1_BIN);\n+\treturn !oidcmp(oid, the_hash_algo->empty_blob);\n }\n \n static inline int is_empty_tree_sha1(const unsigned char *sha1)\n {\n-\treturn !hashcmp(sha1, EMPTY_TREE_SHA1_BIN);\n+\treturn !hashcmp(sha1, the_hash_algo->empty_tree->hash);\n }\n \n static inline int is_empty_tree_oid(const struct object_id *oid)\n {\n-\treturn !hashcmp(oid->hash, EMPTY_TREE_SHA1_BIN);\n+\treturn !oidcmp(oid, the_hash_algo->empty_tree);\n }\n \n /* set default permissions by passing mode arguments to open(2) */\ndiff --git a/diff-lib.c b/diff-lib.c\nindex 731f0886d6..893fee432c 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -217,7 +217,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)\n \t\t\t} else if (revs->diffopt.ita_invisible_in_index &&\n \t\t\t\t   ce_intent_to_add(ce)) {\n \t\t\t\tdiff_addremove(&revs->diffopt, '+', ce->ce_mode,\n-\t\t\t\t\t       &empty_tree_oid, 0,\n+\t\t\t\t\t       the_hash_algo->empty_tree, 0,\n \t\t\t\t\t       ce->name, 0);\n \t\t\t\tcontinue;\n \t\t\t}\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 2ca8444c65..f89cc751e1 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -2081,7 +2081,7 @@ int merge_recursive(struct merge_options *o,\n \t\t/* if there is no common ancestor, use an empty tree */\n \t\tstruct tree *tree;\n \n-\t\ttree = lookup_tree(&empty_tree_oid);\n+\t\ttree = lookup_tree(the_hash_algo->empty_tree);\n \t\tmerged_common_ancestors = make_virtual_commit(tree, \"ancestor\");\n \t}\n \ndiff --git a/notes-merge.c b/notes-merge.c\nindex 4a83b0ebd5..0f6573cb17 100644\n--- a/notes-merge.c\n+++ b/notes-merge.c\n@@ -595,7 +595,7 @@ int notes_merge(struct notes_merge_options *o,\n \tbases = get_merge_bases(local, remote);\n \tif (!bases) {\n \t\tbase_oid = &null_oid;\n-\t\tbase_tree_oid = &empty_tree_oid;\n+\t\tbase_tree_oid = the_hash_algo->empty_tree;\n \t\tif (o->verbosity >= 4)\n \t\t\tprintf(\"No merge base found; doing history-less merge\\n\");\n \t} else if (!bases->next) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 6d027b06c8..2c191aeb36 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -347,7 +347,7 @@ static int read_oneliner(struct strbuf *buf,\n \n static struct tree *empty_tree(void)\n {\n-\treturn lookup_tree(&empty_tree_oid);\n+\treturn lookup_tree(the_hash_algo->empty_tree);\n }\n \n static int error_dirty_index(struct replay_opts *opts)\n@@ -705,7 +705,7 @@ static int is_original_commit_empty(struct commit *commit)\n \t\t\t\toid_to_hex(&parent->object.oid));\n \t\tptree_oid = &parent->tree->object.oid;\n \t} else {\n-\t\tptree_oid = &empty_tree_oid; /* commit is root */\n+\t\tptree_oid = the_hash_algo->empty_tree; /* commit is root */\n \t}\n \n \treturn !oidcmp(ptree_oid, &commit->tree->object.oid);\n@@ -958,7 +958,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,\n \t} else {\n \t\tunborn = get_oid(\"HEAD\", &head);\n \t\tif (unborn)\n-\t\t\toidcpy(&head, &empty_tree_oid);\n+\t\t\toidcpy(&head, the_hash_algo->empty_tree);\n \t\tif (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : \"HEAD\",\n \t\t\t\t       NULL, 0))\n \t\t\treturn error_dirty_index(opts);\ndiff --git a/submodule.c b/submodule.c\nindex 3ee4a0caa7..ec269a6fc0 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -587,7 +587,7 @@ void show_submodule_inline_diff(struct diff_options *o, const char *path,\n \t\tstruct object_id *one, struct object_id *two,\n \t\tunsigned dirty_submodule)\n {\n-\tconst struct object_id *old = &empty_tree_oid, *new = &empty_tree_oid;\n+\tconst struct object_id *old = the_hash_algo->empty_tree, *new = the_hash_algo->empty_tree;\n \tstruct commit *left = NULL, *right = NULL;\n \tstruct commit_list *merge_bases = NULL;\n \tstruct child_process cp = CHILD_PROCESS_INIT;\n"},{"id":"332371","messageId":"20171112212854.791179-4-sandals@crustytoothpaste.net","threadId":"47186","inReplyTo":"20171112212854.791179-1-sandals@crustytoothpaste.net","subject":"[PATCH v3 3/4] Integrate hash algorithm support with repo setup","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2017-11-12T21:28:53Z","receivedAt":"2017-11-12T21:29:27Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"In future versions of Git, we plan to support an additional hash\nalgorithm.  Integrate the enumeration of hash algorithms with repository\nsetup, and store a pointer to the enumerated data in struct repository.\nOf course, we currently only support SHA-1, so hard-code this value in\nread_repository_format.  In the future, we'll enumerate this value from\nthe configuration.\n\nAdd a constant, the_hash_algo, which points to the hash_algo structure\npointer in the repository global.  Note that this is the hash which is\nused to serialize data to disk, not the hash which is used to display\nitems to the user.  The transition plan anticipates that these may be\ndifferent.  We can add an additional element in the future (say,\nui_hash_algo) to provide for this case.\n\nInclude repository.h in cache.h since we now need to have access to\nthese struct and variable definitions.\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n cache.h      | 4 ++++\n repository.c | 7 +++++++\n repository.h | 5 +++++\n setup.c      | 3 +++\n 4 files changed, 19 insertions(+)\n\ndiff --git a/cache.h b/cache.h\nindex cb7fb7c004..c238688f6c 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -14,6 +14,7 @@\n #include \"hash.h\"\n #include \"path.h\"\n #include \"sha1-array.h\"\n+#include \"repository.h\"\n \n #ifndef platform_SHA_CTX\n /*\n@@ -77,6 +78,8 @@ struct object_id {\n \tunsigned char hash[GIT_MAX_RAWSZ];\n };\n \n+#define the_hash_algo the_repository->hash_algo\n+\n #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)\n #define DTYPE(de)\t((de)->d_type)\n #else\n@@ -888,6 +891,7 @@ struct repository_format {\n \tint version;\n \tint precious_objects;\n \tint is_bare;\n+\tint hash_algo;\n \tchar *work_tree;\n \tstruct string_list unknown_extensions;\n };\ndiff --git a/repository.c b/repository.c\nindex bb2fae5446..c6ceb9f9e4 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -64,6 +64,11 @@ void repo_set_gitdir(struct repository *repo, const char *path)\n \tfree(old_gitdir);\n }\n \n+void repo_set_hash_algo(struct repository *repo, int hash_algo)\n+{\n+\trepo->hash_algo = &hash_algos[hash_algo];\n+}\n+\n /*\n  * Attempt to resolve and set the provided 'gitdir' for repository 'repo'.\n  * Return 0 upon success and a non-zero value upon failure.\n@@ -136,6 +141,8 @@ int repo_init(struct repository *repo, const char *gitdir, const char *worktree)\n \tif (read_and_verify_repository_format(&format, repo->commondir))\n \t\tgoto error;\n \n+\trepo_set_hash_algo(repo, format.hash_algo);\n+\n \tif (worktree)\n \t\trepo_set_worktree(repo, worktree);\n \ndiff --git a/repository.h b/repository.h\nindex 7f5e24a0a2..0329e40c7f 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -4,6 +4,7 @@\n struct config_set;\n struct index_state;\n struct submodule_cache;\n+struct git_hash_algo;\n \n struct repository {\n \t/* Environment */\n@@ -67,6 +68,9 @@ struct repository {\n \t */\n \tstruct index_state *index;\n \n+\t/* Repository's current hash algorithm, as serialized on disk. */\n+\tconst struct git_hash_algo *hash_algo;\n+\n \t/* Configurations */\n \t/*\n \t * Bit used during initialization to indicate if repository state (like\n@@ -86,6 +90,7 @@ extern struct repository *the_repository;\n \n extern void repo_set_gitdir(struct repository *repo, const char *path);\n extern void repo_set_worktree(struct repository *repo, const char *path);\n+extern void repo_set_hash_algo(struct repository *repo, int algo);\n extern int repo_init(struct repository *repo, const char *gitdir, const char *worktree);\n extern int repo_submodule_init(struct repository *submodule,\n \t\t\t       struct repository *superproject,\ndiff --git a/setup.c b/setup.c\nindex cf1b22cd30..50c6b2ab11 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -488,6 +488,7 @@ int read_repository_format(struct repository_format *format, const char *path)\n \tmemset(format, 0, sizeof(*format));\n \tformat->version = -1;\n \tformat->is_bare = -1;\n+\tformat->hash_algo = GIT_HASH_SHA1;\n \tstring_list_init(&format->unknown_extensions, 1);\n \tgit_config_from_file(check_repo_format, path, format);\n \treturn format->version;\n@@ -1113,6 +1114,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\trepo_set_gitdir(the_repository, gitdir);\n \t\t\tsetup_git_env();\n \t\t}\n+\t\tif (startup_info->have_repository)\n+\t\t\trepo_set_hash_algo(the_repository, repo_fmt.hash_algo);\n \t}\n \n \tstrbuf_release(&dir);\n"},{"id":"332393","messageId":"xmqq4lpyajra.fsf@gitster.mtv.corp.google.com","threadId":"47186","inReplyTo":"20171112212854.791179-1-sandals@crustytoothpaste.net","subject":"Re: [PATCH v3 0/4] Hash abstraction","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-11-13T04:24:25Z","receivedAt":"2017-11-13T04:24:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> This is a series proposing a basic abstraction for hash functions.\n>\n> The full description of the series can be found here:\n> https://public-inbox.org/git/20171028181239.59458-1-sandals@crustytoothpaste.net/\n>\n> At the bottom of this message is the output of git tbdiff between v2 and\n> v3.\n>\n> Changes from v2:\n> * Remove inline.\n> * Add dummy functions that call die for unknown hash implementation.\n> * Move structure definitions to hash.h and include git-compat-util.h in\n>   hash.h.\n> * Rename current_hash to the_hash_algo.\n> * Use repo_set_hash_algo everywhere we set the hash algorithm for a\n>   struct repository.\n\nChange for all of the above in this series looked sensible to me.\nThank, will queue.\n"},{"id":"332430","messageId":"CAGZ79kaoZX_ek32+vB-j0tSp=tLRYn4vkx2WSSjMQ3CPNty6wg@mail.gmail.com","threadId":"47186","inReplyTo":"20171112212854.791179-5-sandals@crustytoothpaste.net","subject":"Re: [PATCH v3 4/4] Switch empty tree and blob lookups to use hash abstraction","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-11-13T18:43:49Z","receivedAt":"2017-11-13T18:43:56Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Sun, Nov 12, 2017 at 1:28 PM, brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> Switch the uses of empty_tree_oid and empty_blob_oid to use the\n> current_hash abstraction that represents the current hash algorithm in\n> use.\n>\n> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n> ---\n\nThanks for writing this series,\nall four patches look good to me.\n\nThanks,\nStefan\n"},{"id":"333253","messageId":"xmqqbmjuu4zt.fsf@gitster.mtv.corp.google.com","threadId":"47186","inReplyTo":"xmqq4lpyajra.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 0/4] Hash abstraction","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-11-22T07:50:14Z","receivedAt":"2017-11-22T07:50:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n>\n>> This is a series proposing a basic abstraction for hash functions.\n>>\n>> The full description of the series can be found here:\n>> https://public-inbox.org/git/20171028181239.59458-1-sandals@crustytoothpaste.net/\n>>\n>> At the bottom of this message is the output of git tbdiff between v2 and\n>> v3.\n>>\n>> Changes from v2:\n>> * Remove inline.\n>> * Add dummy functions that call die for unknown hash implementation.\n>> * Move structure definitions to hash.h and include git-compat-util.h in\n>>   hash.h.\n>> * Rename current_hash to the_hash_algo.\n>> * Use repo_set_hash_algo everywhere we set the hash algorithm for a\n>>   struct repository.\n>\n> Change for all of the above in this series looked sensible to me.\n> Thank, will queue.\n\nSo... is everybody happy enough with this version that nobody minds\nmore codebase to be adjusted on the infrastructure this series lays\nout?  I think this is ready for 'next', but just in case I missed\nsome discussions...\n\n"},{"id":"333295","messageId":"CAGZ79kaufHTT2dcfgMP-hve-Sj9G85SajDdGivKg1Ho3pu0Vgg@mail.gmail.com","threadId":"47186","inReplyTo":"xmqqbmjuu4zt.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 0/4] Hash abstraction","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-11-22T16:57:17Z","receivedAt":"2017-11-22T16:57:23Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Tue, Nov 21, 2017 at 11:50 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n>>\n>>> This is a series proposing a basic abstraction for hash functions.\n>>>\n>>> The full description of the series can be found here:\n>>> https://public-inbox.org/git/20171028181239.59458-1-sandals@crustytoothpaste.net/\n>>>\n>>> At the bottom of this message is the output of git tbdiff between v2 and\n>>> v3.\n>>>\n>>> Changes from v2:\n>>> * Remove inline.\n>>> * Add dummy functions that call die for unknown hash implementation.\n>>> * Move structure definitions to hash.h and include git-compat-util.h in\n>>>   hash.h.\n>>> * Rename current_hash to the_hash_algo.\n>>> * Use repo_set_hash_algo everywhere we set the hash algorithm for a\n>>>   struct repository.\n>>\n>> Change for all of the above in this series looked sensible to me.\n>> Thank, will queue.\n>\n> So... is everybody happy enough with this version that nobody minds\n> more codebase to be adjusted on the infrastructure this series lays\n> out?  I think this is ready for 'next', but just in case I missed\n> some discussions...\n\nyeah I was happy at the time of review; sorry for not saying so.\n"}]}