repository.con commit config: read config from a repository object (3b25622)
   1#include "cache.h"
   2#include "repository.h"
   3#include "config.h"
   4
   5/* The main repository */
   6static struct repository the_repo;
   7struct repository *the_repository = &the_repo;
   8
   9static char *git_path_from_env(const char *envvar, const char *git_dir,
  10                               const char *path, int fromenv)
  11{
  12        if (fromenv) {
  13                const char *value = getenv(envvar);
  14                if (value)
  15                        return xstrdup(value);
  16        }
  17
  18        return xstrfmt("%s/%s", git_dir, path);
  19}
  20
  21static int find_common_dir(struct strbuf *sb, const char *gitdir, int fromenv)
  22{
  23        if (fromenv) {
  24                const char *value = getenv(GIT_COMMON_DIR_ENVIRONMENT);
  25                if (value) {
  26                        strbuf_addstr(sb, value);
  27                        return 1;
  28                }
  29        }
  30
  31        return get_common_dir_noenv(sb, gitdir);
  32}
  33
  34static void repo_setup_env(struct repository *repo)
  35{
  36        struct strbuf sb = STRBUF_INIT;
  37
  38        repo->different_commondir = find_common_dir(&sb, repo->gitdir,
  39                                                    !repo->ignore_env);
  40        repo->commondir = strbuf_detach(&sb, NULL);
  41        repo->objectdir = git_path_from_env(DB_ENVIRONMENT, repo->commondir,
  42                                            "objects", !repo->ignore_env);
  43        repo->graft_file = git_path_from_env(GRAFT_ENVIRONMENT, repo->commondir,
  44                                             "info/grafts", !repo->ignore_env);
  45        repo->index_file = git_path_from_env(INDEX_ENVIRONMENT, repo->gitdir,
  46                                             "index", !repo->ignore_env);
  47}
  48
  49void repo_set_gitdir(struct repository *repo, const char *path)
  50{
  51        const char *gitfile = read_gitfile(path);
  52
  53        /*
  54         * NEEDSWORK: Eventually we want to be able to free gitdir and the rest
  55         * of the environment before reinitializing it again, but we have some
  56         * crazy code paths where we try to set gitdir with the current gitdir
  57         * and we don't want to free gitdir before copying the passed in value.
  58         */
  59        repo->gitdir = xstrdup(gitfile ? gitfile : path);
  60
  61        repo_setup_env(repo);
  62}
  63
  64/*
  65 * Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
  66 * Return 0 upon success and a non-zero value upon failure.
  67 */
  68static int repo_init_gitdir(struct repository *repo, const char *gitdir)
  69{
  70        int ret = 0;
  71        int error = 0;
  72        char *abspath = NULL;
  73        const char *resolved_gitdir;
  74
  75        abspath = real_pathdup(gitdir, 0);
  76        if (!abspath) {
  77                ret = -1;
  78                goto out;
  79        }
  80
  81        /* 'gitdir' must reference the gitdir directly */
  82        resolved_gitdir = resolve_gitdir_gently(abspath, &error);
  83        if (!resolved_gitdir) {
  84                ret = -1;
  85                goto out;
  86        }
  87
  88        repo_set_gitdir(repo, resolved_gitdir);
  89
  90out:
  91        free(abspath);
  92        return ret;
  93}
  94
  95void repo_set_worktree(struct repository *repo, const char *path)
  96{
  97        repo->worktree = real_pathdup(path, 1);
  98}
  99
 100static int read_and_verify_repository_format(struct repository_format *format,
 101                                             const char *commondir)
 102{
 103        int ret = 0;
 104        struct strbuf sb = STRBUF_INIT;
 105
 106        strbuf_addf(&sb, "%s/config", commondir);
 107        read_repository_format(format, sb.buf);
 108        strbuf_reset(&sb);
 109
 110        if (verify_repository_format(format, &sb) < 0) {
 111                warning("%s", sb.buf);
 112                ret = -1;
 113        }
 114
 115        strbuf_release(&sb);
 116        return ret;
 117}
 118
 119/*
 120 * Initialize 'repo' based on the provided 'gitdir'.
 121 * Return 0 upon success and a non-zero value upon failure.
 122 */
 123int repo_init(struct repository *repo, const char *gitdir, const char *worktree)
 124{
 125        struct repository_format format;
 126        memset(repo, 0, sizeof(*repo));
 127
 128        repo->ignore_env = 1;
 129
 130        if (repo_init_gitdir(repo, gitdir))
 131                goto error;
 132
 133        if (read_and_verify_repository_format(&format, repo->commondir))
 134                goto error;
 135
 136        if (worktree)
 137                repo_set_worktree(repo, worktree);
 138
 139        return 0;
 140
 141error:
 142        repo_clear(repo);
 143        return -1;
 144}
 145
 146void repo_clear(struct repository *repo)
 147{
 148        free(repo->gitdir);
 149        repo->gitdir = NULL;
 150        free(repo->commondir);
 151        repo->commondir = NULL;
 152        free(repo->objectdir);
 153        repo->objectdir = NULL;
 154        free(repo->graft_file);
 155        repo->graft_file = NULL;
 156        free(repo->index_file);
 157        repo->index_file = NULL;
 158        free(repo->worktree);
 159        repo->worktree = NULL;
 160
 161        if (repo->config) {
 162                git_configset_clear(repo->config);
 163                free(repo->config);
 164                repo->config = NULL;
 165        }
 166}