After 454253f059 (builtin/index-pack: improve hash function abstraction - 2018-02-01), index-pack uses the_hash_algo for hashing. If "git index-pack" is executed without a repository, we do not know what hash algorithm to be used and the_hash_algo in theory could be undefined. Since there should be some information about the hash algorithm in the input pack file, we can initialize the correct hash algorithm with that if the_hash_algo is not yet initialized. This assumes that pack files with new hash algorithm MUST step up pack version. While at there, make sure the hash algorithm requested by the pack file and configured by the repository (if we're running with a repo) are consistent. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- builtin/index-pack.c | 29 ++++++++++++++++++++++++++++- repository.h | 5 +++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 7e3e1a461c..2c75f28b41 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -326,10 +326,34 @@ static const char *open_pack_file(const char *pack_name) output_fd = -1; nothread_data.pack_fd = input_fd; } - the_hash_algo->init_fn(&input_ctx); return pack_name; } +static void prepare_hash_algo(uint32_t pack_version) +{ + int pack_algo_id; + const struct git_hash_algo *pack_algo; + + switch (pack_version) { + case 2: + case 3: + pack_algo_id = GIT_HASH_SHA1; + break; + default: + die("BUG: how to determine hash algo for version %d?", + pack_version); + } + + if (!repo_has_valid_hash_algo(the_repository)) /* running without repo */ + repo_set_hash_algo(the_repository, pack_algo_id); + + pack_algo = &hash_algos[pack_algo_id]; + if (the_hash_algo->format_id != pack_algo->format_id) + die(_("incompatible hash algorithm, " + "configured for %s but the pack file needs %s"), + the_hash_algo->name, pack_algo->name); +} + static void parse_pack_header(void) { struct pack_header *hdr = fill(sizeof(struct pack_header)); @@ -341,6 +365,9 @@ static void parse_pack_header(void) die(_("pack version %"PRIu32" unsupported"), ntohl(hdr->hdr_version)); + prepare_hash_algo(ntohl(hdr->hdr_version)); + the_hash_algo->init_fn(&input_ctx); + nr_objects = ntohl(hdr->hdr_entries); use(sizeof(struct pack_header)); } diff --git a/repository.h b/repository.h index 5092df3700..02c695bc74 100644 --- a/repository.h +++ b/repository.h @@ -113,4 +113,9 @@ static inline const struct git_hash_algo *repo_get_hash_algo( return repo->hash_algo; } +static inline int repo_has_valid_hash_algo(const struct repository *repo) +{ + return repo->hash_algo != NULL; +} + #endif /* REPOSITORY_H */ -- 2.16.1.435.g8f24da2e1a