diff options
Diffstat (limited to 'src/repository.c')
-rw-r--r-- | src/repository.c | 185 |
1 files changed, 116 insertions, 69 deletions
diff --git a/src/repository.c b/src/repository.c index 52509ffc1..23cafe05a 100644 --- a/src/repository.c +++ b/src/repository.c @@ -961,80 +961,121 @@ static int create_empty_file(const char *path, mode_t mode) return 0; } -static int repo_init_config( - git_config *parent, - const char *repo_dir, - const char *work_dir, - uint32_t flags, - uint32_t mode) +static int repo_local_config( + git_config **out, + git_buf *config_dir, + git_repository *repo, + const char *repo_dir) { int error = 0; - git_buf buf = GIT_BUF_INIT; - const char *cfg_path = NULL; - git_config *config = NULL; - bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0); + git_config *parent; + const char *cfg_path; -#define SET_REPO_CONFIG(TYPE, NAME, VAL) do {\ - if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \ - goto cleanup; } while (0) - - if (git_buf_joinpath(&buf, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) + if (git_buf_joinpath(config_dir, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) return -1; - cfg_path = git_buf_cstr(&buf); + cfg_path = git_buf_cstr(config_dir); + /* make LOCAL config if missing */ if (!git_path_isfile(cfg_path) && (error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0) - goto cleanup; + return error; - if (!parent) - error = git_config_open_ondisk(&config, cfg_path); - else if ((error = git_config_open_level( - &config, parent, GIT_CONFIG_LEVEL_LOCAL)) < 0) - { + /* if no repo, just open that file directly */ + if (!repo) + return git_config_open_ondisk(out, cfg_path); + + /* otherwise, open parent config and get that level */ + if ((error = git_repository_config__weakptr(&parent, repo)) < 0) + return error; + + if (git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL) < 0) { giterr_clear(); if (!(error = git_config_add_file_ondisk( parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, false))) - error = git_config_open_level( - &config, parent, GIT_CONFIG_LEVEL_LOCAL); + error = git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL); } - if (error < 0) - goto cleanup; - if ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0 && - (error = check_repositoryformatversion(config)) < 0) - goto cleanup; + git_config_free(parent); + + return error; +} + +static int repo_init_fs_configs( + git_config *cfg, + const char *cfg_path, + const char *repo_dir, + const char *work_dir, + bool update_ignorecase) +{ + int error = 0; + + if (!work_dir) + work_dir = repo_dir; + + if ((error = git_config_set_bool( + cfg, "core.filemode", is_chmod_supported(cfg_path))) < 0) + return error; + + if (!are_symlinks_supported(work_dir)) { + if ((error = git_config_set_bool(cfg, "core.symlinks", false)) < 0) + return error; + } else if (git_config_delete_entry(cfg, "core.symlinks") < 0) + giterr_clear(); - SET_REPO_CONFIG( - bool, "core.bare", is_bare); - SET_REPO_CONFIG( - int32, "core.repositoryformatversion", GIT_REPO_VERSION); - SET_REPO_CONFIG( - bool, "core.filemode", is_chmod_supported(cfg_path)); + if (update_ignorecase) { + if (is_filesystem_case_insensitive(repo_dir)) { + if ((error = git_config_set_bool(cfg, "core.ignorecase", true)) < 0) + return error; + } else if (git_config_delete_entry(cfg, "core.ignorecase") < 0) + giterr_clear(); + } #ifdef GIT_USE_ICONV - SET_REPO_CONFIG( - bool, "core.precomposeunicode", - does_fs_decompose_unicode_paths(is_bare ? repo_dir : work_dir)); + if ((error = git_config_set_bool( + cfg, "core.precomposeunicode", + does_fs_decompose_unicode_paths(work_dir))) < 0) + return error; #endif - if (!are_symlinks_supported(is_bare ? repo_dir : work_dir)) - SET_REPO_CONFIG(bool, "core.symlinks", false); + return 0; +} - /* core git does not do this on a reinit, but it is a property of - * the filesystem, so I think we should... - */ - if (!(flags & GIT_REPOSITORY_INIT__IS_REINIT) && - is_filesystem_case_insensitive(repo_dir)) - SET_REPO_CONFIG(bool, "core.ignorecase", true); +static int repo_init_config( + const char *repo_dir, + const char *work_dir, + uint32_t flags, + uint32_t mode) +{ + int error = 0; + git_buf cfg_path = GIT_BUF_INIT; + git_config *config = NULL; + bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0); + bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0); + + if ((error = repo_local_config(&config, &cfg_path, NULL, repo_dir)) < 0) + goto cleanup; + + if (is_reinit && (error = check_repositoryformatversion(config)) < 0) + goto cleanup; + +#define SET_REPO_CONFIG(TYPE, NAME, VAL) do { \ + if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \ + goto cleanup; } while (0) + + SET_REPO_CONFIG(bool, "core.bare", is_bare); + SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION); + + if ((error = repo_init_fs_configs( + config, cfg_path.ptr, repo_dir, work_dir, !is_reinit)) < 0) + goto cleanup; if (!is_bare) { SET_REPO_CONFIG(bool, "core.logallrefupdates", true); - if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) { + if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) SET_REPO_CONFIG(string, "core.worktree", work_dir); - } - else if ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0) { + else if (is_reinit) { if (git_config_delete_entry(config, "core.worktree") < 0) giterr_clear(); } @@ -1050,38 +1091,44 @@ static int repo_init_config( } cleanup: - git_buf_free(&buf); + git_buf_free(&cfg_path); git_config_free(config); return error; } -int git_repository_reset_filesystem(git_repository *repo) +static int repo_reset_submodule_fs(git_submodule *sm, const char *n, void *p) { - int error = 0; - uint32_t flags = 0; - const char *repo_dir, *work_dir; - git_config *cfg; + git_repository *smrepo = NULL; + GIT_UNUSED(n); GIT_UNUSED(p); - assert(repo); + if (git_submodule_open(&smrepo, sm) < 0 || + git_repository_reset_filesystem(smrepo, true) < 0) + giterr_clear(); + git_repository_free(smrepo); - repo_dir = git_repository_path(repo); - work_dir = git_repository_workdir(repo); + return 0; +} - if (git_repository_is_bare(repo)) - flags |= GIT_REPOSITORY_INIT_BARE; - else if (!git__prefixcmp(repo_dir, work_dir) && - !strcmp(repo_dir + strlen(work_dir), DOT_GIT "/")) - flags |= GIT_REPOSITORY_INIT__NATURAL_WD; +int git_repository_reset_filesystem(git_repository *repo, int recurse) +{ + int error = 0; + git_buf path = GIT_BUF_INIT; + git_config *config = NULL; + const char *repo_dir = git_repository_path(repo); - if ((error = git_repository_config(&cfg, repo)) < 0) - return error; + if (!(error = repo_local_config(&config, &path, repo, repo_dir))) + error = repo_init_fs_configs( + config, path.ptr, repo_dir, git_repository_workdir(repo), true); - error = repo_init_config(cfg, repo_dir, work_dir, flags, 0); + git_config_free(config); + git_buf_free(&path); - git_config_free(cfg); git_repository__cvar_cache_clear(repo); + if (!repo->is_bare && recurse) + (void)git_submodule_foreach(repo, repo_reset_submodule_fs, NULL); + return error; } @@ -1473,7 +1520,7 @@ int git_repository_init_ext( opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT; error = repo_init_config( - NULL, repo_path.ptr, wd_path.ptr, opts->flags, opts->mode); + repo_path.ptr, wd_path.ptr, opts->flags, opts->mode); /* TODO: reinitialize the templates */ } @@ -1481,7 +1528,7 @@ int git_repository_init_ext( if (!(error = repo_init_structure( repo_path.ptr, wd_path.ptr, opts)) && !(error = repo_init_config( - NULL, repo_path.ptr, wd_path.ptr, opts->flags, opts->mode))) + repo_path.ptr, wd_path.ptr, opts->flags, opts->mode))) error = repo_init_create_head( repo_path.ptr, opts->initial_head); } |