diff options
Diffstat (limited to 'setup.c')
-rw-r--r-- | setup.c | 186 |
1 files changed, 136 insertions, 50 deletions
@@ -13,7 +13,6 @@ #include "string-list.h" #include "chdir-notify.h" #include "path.h" -#include "promisor-remote.h" #include "quote.h" #include "trace2.h" #include "worktree.h" @@ -559,6 +558,8 @@ static enum extension_result handle_extension_v0(const char *var, data->precious_objects = git_config_bool(var, value); return EXTENSION_OK; } else if (!strcmp(ext, "partialclone")) { + if (!value) + return config_error_nonbool(var); data->partial_clone = xstrdup(value); return EXTENSION_OK; } else if (!strcmp(ext, "worktreeconfig")) { @@ -590,6 +591,36 @@ static enum extension_result handle_extension(const char *var, "extensions.objectformat", value); data->hash_algo = format; return EXTENSION_OK; + } else if (!strcmp(ext, "compatobjectformat")) { + struct string_list_item *item; + int format; + + if (!value) + return config_error_nonbool(var); + format = hash_algo_by_name(value); + if (format == GIT_HASH_UNKNOWN) + return error(_("invalid value for '%s': '%s'"), + "extensions.compatobjectformat", value); + /* For now only support compatObjectFormat being specified once. */ + for_each_string_list_item(item, &data->v1_only_extensions) { + if (!strcmp(item->string, "compatobjectformat")) + return error(_("'%s' already specified as '%s'"), + "extensions.compatobjectformat", + hash_algos[data->compat_hash_algo].name); + } + data->compat_hash_algo = format; + return EXTENSION_OK; + } else if (!strcmp(ext, "refstorage")) { + unsigned int format; + + if (!value) + return config_error_nonbool(var); + format = ref_storage_format_by_name(value); + if (format == REF_STORAGE_FORMAT_UNKNOWN) + return error(_("invalid value for '%s': '%s'"), + "extensions.refstorage", value); + data->ref_storage_format = format; + return EXTENSION_OK; } return EXTENSION_UNKNOWN; } @@ -1565,6 +1596,10 @@ const char *setup_git_directory_gently(int *nongit_ok) } if (startup_info->have_repository) { repo_set_hash_algo(the_repository, repo_fmt.hash_algo); + repo_set_compat_hash_algo(the_repository, + repo_fmt.compat_hash_algo); + repo_set_ref_storage_format(the_repository, + repo_fmt.ref_storage_format); the_repository->repository_format_worktree_config = repo_fmt.worktree_config; /* take ownership of repo_fmt.partial_clone */ @@ -1658,6 +1693,9 @@ void check_repository_format(struct repository_format *fmt) check_repository_format_gently(get_git_dir(), fmt, NULL); startup_info->have_repository = 1; repo_set_hash_algo(the_repository, fmt->hash_algo); + repo_set_compat_hash_algo(the_repository, fmt->compat_hash_algo); + repo_set_ref_storage_format(the_repository, + fmt->ref_storage_format); the_repository->repository_format_worktree_config = fmt->worktree_config; the_repository->repository_format_partial_clone = @@ -1866,12 +1904,15 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree) return 1; } -void initialize_repository_version(int hash_algo, int reinit) +void initialize_repository_version(int hash_algo, + unsigned int ref_storage_format, + int reinit) { char repo_version_string[10]; int repo_version = GIT_REPO_VERSION; - if (hash_algo != GIT_HASH_SHA1) + if (hash_algo != GIT_HASH_SHA1 || + ref_storage_format != REF_STORAGE_FORMAT_FILES) repo_version = GIT_REPO_VERSION_READ; /* This forces creation of new config file */ @@ -1884,23 +1925,72 @@ void initialize_repository_version(int hash_algo, int reinit) hash_algos[hash_algo].name); else if (reinit) git_config_set_gently("extensions.objectformat", NULL); + + if (ref_storage_format != REF_STORAGE_FORMAT_FILES) + git_config_set("extensions.refstorage", + ref_storage_format_to_name(ref_storage_format)); +} + +static int is_reinit(void) +{ + struct strbuf buf = STRBUF_INIT; + char junk[2]; + int ret; + + git_path_buf(&buf, "HEAD"); + ret = !access(buf.buf, R_OK) || readlink(buf.buf, junk, sizeof(junk) - 1) != -1; + strbuf_release(&buf); + return ret; +} + +void create_reference_database(unsigned int ref_storage_format, + const char *initial_branch, int quiet) +{ + struct strbuf err = STRBUF_INIT; + int reinit = is_reinit(); + + repo_set_ref_storage_format(the_repository, ref_storage_format); + if (refs_init_db(get_main_ref_store(the_repository), 0, &err)) + die("failed to set up refs db: %s", err.buf); + + /* + * Point the HEAD symref to the initial branch with if HEAD does + * not yet exist. + */ + if (!reinit) { + char *ref; + + if (!initial_branch) + initial_branch = git_default_branch_name(quiet); + + ref = xstrfmt("refs/heads/%s", initial_branch); + if (check_refname_format(ref, 0) < 0) + die(_("invalid initial branch name: '%s'"), + initial_branch); + + if (create_symref("HEAD", ref, NULL) < 0) + exit(1); + free(ref); + } + + if (reinit && initial_branch) + warning(_("re-init: ignored --initial-branch=%s"), + initial_branch); + + strbuf_release(&err); } static int create_default_files(const char *template_path, const char *original_git_dir, - const char *initial_branch, const struct repository_format *fmt, int prev_bare_repository, - int init_shared_repository, - int quiet) + int init_shared_repository) { struct stat st1; struct strbuf buf = STRBUF_INIT; char *path; - char junk[2]; int reinit; int filemode; - struct strbuf err = STRBUF_INIT; const char *init_template_dir = NULL; const char *work_tree = get_git_work_tree(); @@ -1920,6 +2010,8 @@ static int create_default_files(const char *template_path, reset_shared_repository(); git_config(git_default_config, NULL); + reinit = is_reinit(); + /* * We must make sure command-line options continue to override any * values we might have just re-read from the config. @@ -1963,40 +2055,7 @@ static int create_default_files(const char *template_path, adjust_shared_perm(get_git_dir()); } - /* - * We need to create a "refs" dir in any case so that older - * versions of git can tell that this is a repository. - */ - safe_create_dir(git_path("refs"), 1); - adjust_shared_perm(git_path("refs")); - - if (refs_init_db(&err)) - die("failed to set up refs db: %s", err.buf); - - /* - * Point the HEAD symref to the initial branch with if HEAD does - * not yet exist. - */ - path = git_path_buf(&buf, "HEAD"); - reinit = (!access(path, R_OK) - || readlink(path, junk, sizeof(junk)-1) != -1); - if (!reinit) { - char *ref; - - if (!initial_branch) - initial_branch = git_default_branch_name(quiet); - - ref = xstrfmt("refs/heads/%s", initial_branch); - if (check_refname_format(ref, 0) < 0) - die(_("invalid initial branch name: '%s'"), - initial_branch); - - if (create_symref("HEAD", ref, NULL) < 0) - exit(1); - free(ref); - } - - initialize_repository_version(fmt->hash_algo, 0); + initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0); /* Check filemode trustability */ path = git_path_buf(&buf, "config"); @@ -2109,8 +2168,29 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash } } +static void validate_ref_storage_format(struct repository_format *repo_fmt, + unsigned int format) +{ + const char *name = getenv("GIT_DEFAULT_REF_FORMAT"); + + if (repo_fmt->version >= 0 && + format != REF_STORAGE_FORMAT_UNKNOWN && + format != repo_fmt->ref_storage_format) { + die(_("attempt to reinitialize repository with different reference storage format")); + } else if (format != REF_STORAGE_FORMAT_UNKNOWN) { + repo_fmt->ref_storage_format = format; + } else if (name) { + format = ref_storage_format_by_name(name); + if (format == REF_STORAGE_FORMAT_UNKNOWN) + die(_("unknown ref storage format '%s'"), name); + repo_fmt->ref_storage_format = format; + } +} + int init_db(const char *git_dir, const char *real_git_dir, - const char *template_dir, int hash, const char *initial_branch, + const char *template_dir, int hash, + unsigned int ref_storage_format, + const char *initial_branch, int init_shared_repository, unsigned int flags) { int reinit; @@ -2153,16 +2233,22 @@ int init_db(const char *git_dir, const char *real_git_dir, check_repository_format(&repo_fmt); validate_hash_algorithm(&repo_fmt, hash); + validate_ref_storage_format(&repo_fmt, ref_storage_format); reinit = create_default_files(template_dir, original_git_dir, - initial_branch, &repo_fmt, - prev_bare_repository, - init_shared_repository, - flags & INIT_DB_QUIET); - if (reinit && initial_branch) - warning(_("re-init: ignored --initial-branch=%s"), - initial_branch); + &repo_fmt, prev_bare_repository, + init_shared_repository); + + /* + * Now that we have set up both the hash algorithm and the ref storage + * format we can update the repository's settings accordingly. + */ + repo_set_hash_algo(the_repository, repo_fmt.hash_algo); + repo_set_ref_storage_format(the_repository, repo_fmt.ref_storage_format); + if (!(flags & INIT_DB_SKIP_REFDB)) + create_reference_database(repo_fmt.ref_storage_format, + initial_branch, flags & INIT_DB_QUIET); create_object_directory(); if (get_shared_repository()) { |