Skip to content

Commit 8b8f718

Browse files
bk2204gitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cfe3917 commit 8b8f718

File tree

4 files changed

+55
-9
lines changed

4 files changed

+55
-9
lines changed

Documentation/git-init.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ SYNOPSIS
1010
--------
1111
[verse]
1212
'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
13-
[--separate-git-dir <git dir>]
13+
[--separate-git-dir <git dir>] [--object-format=<format]
1414
[--shared[=<permissions>]] [directory]
1515

1616

@@ -48,6 +48,11 @@ Only print error and warning messages; all other output will be suppressed.
4848
Create a bare repository. If `GIT_DIR` environment is not set, it is set to the
4949
current working directory.
5050

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+
5156
--template=<template_directory>::
5257

5358
Specify the directory from which templates will be used. (See the "TEMPLATE

builtin/clone.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
10971097
}
10981098
}
10991099

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);
11011101

11021102
if (real_git_dir)
11031103
git_dir = real_git_dir;

builtin/init-db.c

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree)
177177
}
178178

179179
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)
181182
{
182183
struct stat st1;
183184
struct strbuf buf = STRBUF_INIT;
@@ -187,6 +188,7 @@ static int create_default_files(const char *template_path,
187188
int reinit;
188189
int filemode;
189190
struct strbuf err = STRBUF_INIT;
191+
int repo_version = GIT_REPO_VERSION;
190192

191193
/* Just look for `init.templatedir` */
192194
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,
244246
exit(1);
245247
}
246248

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+
247257
/* This forces creation of new config file */
248258
xsnprintf(repo_version_string, sizeof(repo_version_string),
249-
"%d", GIT_REPO_VERSION);
259+
"%d", repo_version);
250260
git_config_set("core.repositoryformatversion", repo_version_string);
251261

262+
if (fmt->hash_algo != GIT_HASH_SHA1)
263+
git_config_set("extensions.objectformat",
264+
hash_algos[fmt->hash_algo].name);
265+
252266
/* Check filemode trustability */
253267
path = git_path_buf(&buf, "config");
254268
filemode = TEST_FILEMODE;
@@ -340,12 +354,26 @@ static void separate_git_dir(const char *git_dir, const char *git_link)
340354
write_file(git_link, "gitdir: %s", git_dir);
341355
}
342356

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+
343370
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)
345372
{
346373
int reinit;
347374
int exist_ok = flags & INIT_DB_EXIST_OK;
348375
char *original_git_dir = real_pathdup(git_dir, 1);
376+
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
349377

350378
if (real_git_dir) {
351379
struct stat st;
@@ -378,9 +406,11 @@ int init_db(const char *git_dir, const char *real_git_dir,
378406
* config file, so this will not fail. What we are catching
379407
* is an attempt to reinitialize new repository with an old tool.
380408
*/
381-
check_repository_format(NULL);
409+
check_repository_format(&repo_fmt);
382410

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);
384414

385415
create_object_directory();
386416

@@ -482,6 +512,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
482512
const char *work_tree;
483513
const char *template_dir = NULL;
484514
unsigned int flags = 0;
515+
const char *object_format = NULL;
516+
int hash_algo = GIT_HASH_UNKNOWN;
485517
const struct option init_db_options[] = {
486518
OPT_STRING(0, "template", &template_dir, N_("template-directory"),
487519
N_("directory from which templates will be used")),
@@ -494,6 +526,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
494526
OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
495527
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
496528
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")),
497531
OPT_END()
498532
};
499533

@@ -546,6 +580,12 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
546580
free(cwd);
547581
}
548582

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+
549589
if (init_shared_repository != -1)
550590
set_shared_repository(init_shared_repository);
551591

@@ -597,5 +637,5 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
597637
UNLEAK(work_tree);
598638

599639
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);
601641
}

cache.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,8 @@ int path_inside_repo(const char *prefix, const char *path);
627627
#define INIT_DB_EXIST_OK 0x0002
628628

629629
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);
631632

632633
void sanitize_stdfds(void);
633634
int daemonize(void);

0 commit comments

Comments
 (0)