@@ -167,12 +167,14 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree)
167167 return 1 ;
168168}
169169
170- void initialize_repository_version (int hash_algo , int reinit )
170+ void initialize_repository_version (int hash_algo , int reinit ,
171+ const char * ref_storage_format )
171172{
172173 char repo_version_string [10 ];
173174 int repo_version = GIT_REPO_VERSION ;
174175
175- if (hash_algo != GIT_HASH_SHA1 )
176+ if (hash_algo != GIT_HASH_SHA1 ||
177+ !strcmp (ref_storage_format , "reftable" ))
176178 repo_version = GIT_REPO_VERSION_READ ;
177179
178180 /* This forces creation of new config file */
@@ -225,6 +227,7 @@ static int create_default_files(const char *template_path,
225227 is_bare_repository_cfg = init_is_bare_repository || !work_tree ;
226228 if (init_shared_repository != -1 )
227229 set_shared_repository (init_shared_repository );
230+ the_repository -> ref_storage_format = xstrdup (fmt -> ref_storage );
228231
229232 /*
230233 * We would have created the above under user's umask -- under
@@ -234,6 +237,24 @@ static int create_default_files(const char *template_path,
234237 adjust_shared_perm (get_git_dir ());
235238 }
236239
240+ /*
241+ * Check to see if .git/HEAD exists; this must happen before
242+ * initializing the ref db, because we want to see if there is an
243+ * existing HEAD.
244+ */
245+ path = git_path_buf (& buf , "HEAD" );
246+ reinit = (!access (path , R_OK ) ||
247+ readlink (path , junk , sizeof (junk ) - 1 ) != -1 );
248+
249+ /*
250+ * refs/heads is a file when using reftable. We can't reinitialize with
251+ * a reftable because it will overwrite HEAD
252+ */
253+ if (reinit && (!strcmp (fmt -> ref_storage , "reftable" )) ==
254+ is_directory (git_path_buf (& buf , "refs/heads" ))) {
255+ die ("cannot switch ref storage format." );
256+ }
257+
237258 /*
238259 * We need to create a "refs" dir in any case so that older
239260 * versions of git can tell that this is a repository.
@@ -248,9 +269,6 @@ static int create_default_files(const char *template_path,
248269 * Point the HEAD symref to the initial branch with if HEAD does
249270 * not yet exist.
250271 */
251- path = git_path_buf (& buf , "HEAD" );
252- reinit = (!access (path , R_OK )
253- || readlink (path , junk , sizeof (junk )- 1 ) != -1 );
254272 if (!reinit ) {
255273 char * ref ;
256274
@@ -267,7 +285,7 @@ static int create_default_files(const char *template_path,
267285 free (ref );
268286 }
269287
270- initialize_repository_version (fmt -> hash_algo , 0 );
288+ initialize_repository_version (fmt -> hash_algo , 0 , fmt -> ref_storage );
271289
272290 /* Check filemode trustability */
273291 path = git_path_buf (& buf , "config" );
@@ -382,7 +400,7 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
382400
383401int init_db (const char * git_dir , const char * real_git_dir ,
384402 const char * template_dir , int hash , const char * initial_branch ,
385- unsigned int flags )
403+ const char * ref_storage_format , unsigned int flags )
386404{
387405 int reinit ;
388406 int exist_ok = flags & INIT_DB_EXIST_OK ;
@@ -421,9 +439,31 @@ int init_db(const char *git_dir, const char *real_git_dir,
421439 * is an attempt to reinitialize new repository with an old tool.
422440 */
423441 check_repository_format (& repo_fmt );
442+ repo_fmt .ref_storage = xstrdup (ref_storage_format );
424443
425444 validate_hash_algorithm (& repo_fmt , hash );
426445
446+ /*
447+ * At this point, the_repository we have in-core does not look
448+ * anything like one that we would see initialized in an already
449+ * working repository after calling setup_git_directory().
450+ *
451+ * Calling repository.c::initialize_the_repository() may have
452+ * prepared the .index .objects and .parsed_objects members, but
453+ * other members like .gitdir, .commondir, etc. have not been
454+ * initialized.
455+ *
456+ * Many API functions assume they are working with the_repository
457+ * that has sensibly been initialized, but because we haven't
458+ * really read from an existing repository, we need to hand-craft
459+ * the necessary members of the structure to get out of this
460+ * chicken-and-egg situation.
461+ *
462+ * For now, we update the hash algorithm member to what the
463+ * validate_hash_algorithm() call decided for us.
464+ */
465+ repo_set_hash_algo (the_repository , repo_fmt .hash_algo );
466+
427467 reinit = create_default_files (template_dir , original_git_dir ,
428468 initial_branch , & repo_fmt ,
429469 flags & INIT_DB_QUIET );
@@ -454,6 +494,9 @@ int init_db(const char *git_dir, const char *real_git_dir,
454494 git_config_set ("receive.denyNonFastforwards" , "true" );
455495 }
456496
497+ if (!strcmp (ref_storage_format , "reftable" ))
498+ git_config_set ("extensions.refStorage" , ref_storage_format );
499+
457500 if (!(flags & INIT_DB_QUIET )) {
458501 int len = strlen (git_dir );
459502
@@ -527,6 +570,7 @@ static const char *const init_db_usage[] = {
527570int cmd_init_db (int argc , const char * * argv , const char * prefix )
528571{
529572 const char * git_dir ;
573+ const char * ref_storage_format = default_ref_storage ();
530574 const char * real_git_dir = NULL ;
531575 const char * work_tree ;
532576 const char * template_dir = NULL ;
@@ -535,15 +579,18 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
535579 const char * initial_branch = NULL ;
536580 int hash_algo = GIT_HASH_UNKNOWN ;
537581 const struct option init_db_options [] = {
538- OPT_STRING (0 , "template" , & template_dir , N_ ("template-directory" ),
539- N_ ("directory from which templates will be used" )),
582+ OPT_STRING (0 , "template" , & template_dir ,
583+ N_ ("template-directory" ),
584+ N_ ("directory from which templates will be used" )),
540585 OPT_SET_INT (0 , "bare" , & is_bare_repository_cfg ,
541- N_ ("create a bare repository" ), 1 ),
586+ N_ ("create a bare repository" ), 1 ),
542587 { OPTION_CALLBACK , 0 , "shared" , & init_shared_repository ,
543- N_ ("permissions" ),
544- N_ ("specify that the git repository is to be shared amongst several users" ),
545- PARSE_OPT_OPTARG | PARSE_OPT_NONEG , shared_callback , 0 },
588+ N_ ("permissions" ),
589+ N_ ("specify that the git repository is to be shared amongst several users" ),
590+ PARSE_OPT_OPTARG | PARSE_OPT_NONEG , shared_callback , 0 },
546591 OPT_BIT ('q' , "quiet" , & flags , N_ ("be quiet" ), INIT_DB_QUIET ),
592+ OPT_STRING (0 , "ref-storage" , & ref_storage_format , N_ ("backend" ),
593+ N_ ("the ref storage format to use" )),
547594 OPT_STRING (0 , "separate-git-dir" , & real_git_dir , N_ ("gitdir" ),
548595 N_ ("separate git dir from working tree" )),
549596 OPT_STRING ('b' , "initial-branch" , & initial_branch , N_ ("name" ),
@@ -686,10 +733,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
686733 }
687734
688735 UNLEAK (real_git_dir );
736+ UNLEAK (ref_storage_format );
689737 UNLEAK (git_dir );
690738 UNLEAK (work_tree );
691739
692740 flags |= INIT_DB_EXIST_OK ;
693741 return init_db (git_dir , real_git_dir , template_dir , hash_algo ,
694- initial_branch , flags );
742+ initial_branch , ref_storage_format , flags );
695743}
0 commit comments