@matheusbsbs / matheus-bagliano / commits / 8b8f7189df
Fork 0

builtin/init-db: allow specifying hash algorithm on command line

Allow the user to specify the hash algorithm on the command line by using the --object-format option to git init. Validate that the user is not attempting to reinitialize a repository with a different hash algorithm. Ensure that if we are writing a non-SHA-1 repository that we set the repository version to 1 and write the objectFormat extension. Restrict this option to work only when ENABLE_SHA256 is set until the codebase is in a situation to fully support this. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Feb 22, 2020 at 20:17 UTC 8b8f7189dff1f9ee2e3d65dfaafc2fc9f4956232
4 files changed +55 -9
Documentation/git-init.txt
+6 -1
@@ -10,7 +10,7 @@ SYNOPSIS
10 --------
11 [verse]
12 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
13 - [--separate-git-dir <git dir>]
13 + [--separate-git-dir <git dir>] [--object-format=<format]
14 [--shared[=<permissions>]] [directory]
15
16
@@ -48,6 +48,11 @@ Only print error and warning messages; all other output will be suppressed.
48 Create a bare repository. If `GIT_DIR` environment is not set, it is set to the
49 current working directory.
50
51 +--object-format=<format>::
52 +
53 +Specify the given object format (hash algorithm) for the repository. The valid
54 +values are 'sha1' and (if enabled) 'sha256'. 'sha1' is the default.
55 +
56 --template=<template_directory>::
57
58 Specify the directory from which templates will be used. (See the "TEMPLATE
builtin/clone.c
+1 -1
@@ -1097,7 +1097,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
1097 }
1098 }
1099
1100 - init_db(git_dir, real_git_dir, option_template, INIT_DB_QUIET);
1100 + init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
1101
1102 if (real_git_dir)
1103 git_dir = real_git_dir;
builtin/init-db.c
+46 -6
@@ -177,7 +177,8 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree)
177 }
178
179 static int create_default_files(const char *template_path,
180 - const char *original_git_dir)
180 + const char *original_git_dir,
181 + const struct repository_format *fmt)
182 {
183 struct stat st1;
184 struct strbuf buf = STRBUF_INIT;
@@ -187,6 +188,7 @@ static int create_default_files(const char *template_path,
188 int reinit;
189 int filemode;
190 struct strbuf err = STRBUF_INIT;
191 + int repo_version = GIT_REPO_VERSION;
192
193 /* Just look for `init.templatedir` */
194 init_db_template_dir = NULL; /* re-set in case it was set before */
@@ -244,11 +246,23 @@ static int create_default_files(const char *template_path,
246 exit(1);
247 }
248
249 +#ifndef ENABLE_SHA256
250 + if (fmt->hash_algo != GIT_HASH_SHA1)
251 + die(_("The hash algorithm %s is not supported in this build."), hash_algos[fmt->hash_algo].name);
252 +#endif
253 +
254 + if (fmt->hash_algo != GIT_HASH_SHA1)
255 + repo_version = GIT_REPO_VERSION_READ;
256 +
257 /* This forces creation of new config file */
258 xsnprintf(repo_version_string, sizeof(repo_version_string),
249 - "%d", GIT_REPO_VERSION);
259 + "%d", repo_version);
260 git_config_set("core.repositoryformatversion", repo_version_string);
261
262 + if (fmt->hash_algo != GIT_HASH_SHA1)
263 + git_config_set("extensions.objectformat",
264 + hash_algos[fmt->hash_algo].name);
265 +
266 /* Check filemode trustability */
267 path = git_path_buf(&buf, "config");
268 filemode = TEST_FILEMODE;
@@ -340,12 +354,26 @@ static void separate_git_dir(const char *git_dir, const char *git_link)
354 write_file(git_link, "gitdir: %s", git_dir);
355 }
356
357 +static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash)
358 +{
359 + /*
360 + * If we already have an initialized repo, don't allow the user to
361 + * specify a different algorithm, as that could cause corruption.
362 + * Otherwise, if the user has specified one on the command line, use it.
363 + */
364 + if (repo_fmt->version >= 0 && hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo)
365 + die(_("attempt to reinitialize repository with different hash"));
366 + else if (hash != GIT_HASH_UNKNOWN)
367 + repo_fmt->hash_algo = hash;
368 +}
369 +
370 int init_db(const char *git_dir, const char *real_git_dir,
344 - const char *template_dir, unsigned int flags)
371 + const char *template_dir, int hash, unsigned int flags)
372 {
373 int reinit;
374 int exist_ok = flags & INIT_DB_EXIST_OK;
375 char *original_git_dir = real_pathdup(git_dir, 1);
376 + struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
377
378 if (real_git_dir) {
379 struct stat st;
@@ -378,9 +406,11 @@ int init_db(const char *git_dir, const char *real_git_dir,
406 * config file, so this will not fail. What we are catching
407 * is an attempt to reinitialize new repository with an old tool.
408 */
381 - check_repository_format(NULL);
409 + check_repository_format(&repo_fmt);
410
383 - reinit = create_default_files(template_dir, original_git_dir);
411 + validate_hash_algorithm(&repo_fmt, hash);
412 +
413 + reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
414
415 create_object_directory();
416
@@ -482,6 +512,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
512 const char *work_tree;
513 const char *template_dir = NULL;
514 unsigned int flags = 0;
515 + const char *object_format = NULL;
516 + int hash_algo = GIT_HASH_UNKNOWN;
517 const struct option init_db_options[] = {
518 OPT_STRING(0, "template", &template_dir, N_("template-directory"),
519 N_("directory from which templates will be used")),
@@ -494,6 +526,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
526 OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
527 OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
528 N_("separate git dir from working tree")),
529 + OPT_STRING(0, "object-format", &object_format, N_("hash"),
530 + N_("specify the hash algorithm to use")),
531 OPT_END()
532 };
533
@@ -546,6 +580,12 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
580 free(cwd);
581 }
582
583 + if (object_format) {
584 + hash_algo = hash_algo_by_name(object_format);
585 + if (hash_algo == GIT_HASH_UNKNOWN)
586 + die(_("unknown hash algorithm '%s'"), object_format);
587 + }
588 +
589 if (init_shared_repository != -1)
590 set_shared_repository(init_shared_repository);
591
@@ -597,5 +637,5 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
637 UNLEAK(work_tree);
638
639 flags |= INIT_DB_EXIST_OK;
600 - return init_db(git_dir, real_git_dir, template_dir, flags);
640 + return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
641 }
cache.h
+2 -1
@@ -627,7 +627,8 @@ int path_inside_repo(const char *prefix, const char *path);
627 #define INIT_DB_EXIST_OK 0x0002
628
629 int init_db(const char *git_dir, const char *real_git_dir,
630 - const char *template_dir, unsigned int flags);
630 + const char *template_dir, int hash_algo,
631 + unsigned int flags);
632
633 void sanitize_stdfds(void);
634 int daemonize(void);