repository.con commit Merge branch 'ws/rebase-p' (57e4b1c)
   1#include "cache.h"
   2#include "repository.h"
   3#include "config.h"
   4#include "submodule-config.h"
   5
   6/* The main repository */
   7static struct repository the_repo;
   8struct repository *the_repository;
   9
  10void initialize_the_repository(void)
  11{
  12        the_repository = &the_repo;
  13
  14        the_repo.index = &the_index;
  15        repo_set_hash_algo(&the_repo, GIT_HASH_SHA1);
  16}
  17
  18static void expand_base_dir(char **out, const char *in,
  19                            const char *base_dir, const char *def_in)
  20{
  21        free(*out);
  22        if (in)
  23                *out = xstrdup(in);
  24        else
  25                *out = xstrfmt("%s/%s", base_dir, def_in);
  26}
  27
  28static void repo_set_commondir(struct repository *repo,
  29                               const char *commondir)
  30{
  31        struct strbuf sb = STRBUF_INIT;
  32
  33        free(repo->commondir);
  34
  35        if (commondir) {
  36                repo->different_commondir = 1;
  37                repo->commondir = xstrdup(commondir);
  38                return;
  39        }
  40
  41        repo->different_commondir = get_common_dir_noenv(&sb, repo->gitdir);
  42        repo->commondir = strbuf_detach(&sb, NULL);
  43}
  44
  45void repo_set_gitdir(struct repository *repo,
  46                     const char *root,
  47                     const struct set_gitdir_args *o)
  48{
  49        const char *gitfile = read_gitfile(root);
  50        /*
  51         * repo->gitdir is saved because the caller could pass "root"
  52         * that also points to repo->gitdir. We want to keep it alive
  53         * until after xstrdup(root). Then we can free it.
  54         */
  55        char *old_gitdir = repo->gitdir;
  56
  57        repo->gitdir = xstrdup(gitfile ? gitfile : root);
  58        free(old_gitdir);
  59
  60        repo_set_commondir(repo, o->commondir);
  61        expand_base_dir(&repo->objectdir, o->object_dir,
  62                        repo->commondir, "objects");
  63        free(repo->alternate_db);
  64        repo->alternate_db = xstrdup_or_null(o->alternate_db);
  65        expand_base_dir(&repo->graft_file, o->graft_file,
  66                        repo->commondir, "info/grafts");
  67        expand_base_dir(&repo->index_file, o->index_file,
  68                        repo->gitdir, "index");
  69}
  70
  71void repo_set_hash_algo(struct repository *repo, int hash_algo)
  72{
  73        repo->hash_algo = &hash_algos[hash_algo];
  74}
  75
  76/*
  77 * Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
  78 * Return 0 upon success and a non-zero value upon failure.
  79 */
  80static int repo_init_gitdir(struct repository *repo, const char *gitdir)
  81{
  82        int ret = 0;
  83        int error = 0;
  84        char *abspath = NULL;
  85        const char *resolved_gitdir;
  86        struct set_gitdir_args args = { NULL };
  87
  88        abspath = real_pathdup(gitdir, 0);
  89        if (!abspath) {
  90                ret = -1;
  91                goto out;
  92        }
  93
  94        /* 'gitdir' must reference the gitdir directly */
  95        resolved_gitdir = resolve_gitdir_gently(abspath, &error);
  96        if (!resolved_gitdir) {
  97                ret = -1;
  98                goto out;
  99        }
 100
 101        repo_set_gitdir(repo, resolved_gitdir, &args);
 102
 103out:
 104        free(abspath);
 105        return ret;
 106}
 107
 108void repo_set_worktree(struct repository *repo, const char *path)
 109{
 110        repo->worktree = real_pathdup(path, 1);
 111}
 112
 113static int read_and_verify_repository_format(struct repository_format *format,
 114                                             const char *commondir)
 115{
 116        int ret = 0;
 117        struct strbuf sb = STRBUF_INIT;
 118
 119        strbuf_addf(&sb, "%s/config", commondir);
 120        read_repository_format(format, sb.buf);
 121        strbuf_reset(&sb);
 122
 123        if (verify_repository_format(format, &sb) < 0) {
 124                warning("%s", sb.buf);
 125                ret = -1;
 126        }
 127
 128        strbuf_release(&sb);
 129        return ret;
 130}
 131
 132/*
 133 * Initialize 'repo' based on the provided 'gitdir'.
 134 * Return 0 upon success and a non-zero value upon failure.
 135 */
 136static int repo_init(struct repository *repo,
 137                     const char *gitdir,
 138                     const char *worktree)
 139{
 140        struct repository_format format;
 141        memset(repo, 0, sizeof(*repo));
 142
 143        if (repo_init_gitdir(repo, gitdir))
 144                goto error;
 145
 146        if (read_and_verify_repository_format(&format, repo->commondir))
 147                goto error;
 148
 149        repo_set_hash_algo(repo, format.hash_algo);
 150
 151        if (worktree)
 152                repo_set_worktree(repo, worktree);
 153
 154        return 0;
 155
 156error:
 157        repo_clear(repo);
 158        return -1;
 159}
 160
 161/*
 162 * Initialize 'submodule' as the submodule given by 'path' in parent repository
 163 * 'superproject'.
 164 * Return 0 upon success and a non-zero value upon failure.
 165 */
 166int repo_submodule_init(struct repository *submodule,
 167                        struct repository *superproject,
 168                        const char *path)
 169{
 170        const struct submodule *sub;
 171        struct strbuf gitdir = STRBUF_INIT;
 172        struct strbuf worktree = STRBUF_INIT;
 173        int ret = 0;
 174
 175        sub = submodule_from_cache(superproject, &null_oid, path);
 176        if (!sub) {
 177                ret = -1;
 178                goto out;
 179        }
 180
 181        strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path);
 182        strbuf_repo_worktree_path(&worktree, superproject, "%s", path);
 183
 184        if (repo_init(submodule, gitdir.buf, worktree.buf)) {
 185                /*
 186                 * If initilization fails then it may be due to the submodule
 187                 * not being populated in the superproject's worktree.  Instead
 188                 * we can try to initilize the submodule by finding it's gitdir
 189                 * in the superproject's 'modules' directory.  In this case the
 190                 * submodule would not have a worktree.
 191                 */
 192                strbuf_reset(&gitdir);
 193                strbuf_repo_git_path(&gitdir, superproject,
 194                                     "modules/%s", sub->name);
 195
 196                if (repo_init(submodule, gitdir.buf, NULL)) {
 197                        ret = -1;
 198                        goto out;
 199                }
 200        }
 201
 202        submodule->submodule_prefix = xstrfmt("%s%s/",
 203                                              superproject->submodule_prefix ?
 204                                              superproject->submodule_prefix :
 205                                              "", path);
 206
 207out:
 208        strbuf_release(&gitdir);
 209        strbuf_release(&worktree);
 210        return ret;
 211}
 212
 213void repo_clear(struct repository *repo)
 214{
 215        FREE_AND_NULL(repo->gitdir);
 216        FREE_AND_NULL(repo->commondir);
 217        FREE_AND_NULL(repo->objectdir);
 218        FREE_AND_NULL(repo->alternate_db);
 219        FREE_AND_NULL(repo->graft_file);
 220        FREE_AND_NULL(repo->index_file);
 221        FREE_AND_NULL(repo->worktree);
 222        FREE_AND_NULL(repo->submodule_prefix);
 223
 224        if (repo->config) {
 225                git_configset_clear(repo->config);
 226                FREE_AND_NULL(repo->config);
 227        }
 228
 229        if (repo->submodule_cache) {
 230                submodule_cache_free(repo->submodule_cache);
 231                repo->submodule_cache = NULL;
 232        }
 233
 234        if (repo->index) {
 235                discard_index(repo->index);
 236                FREE_AND_NULL(repo->index);
 237        }
 238}
 239
 240int repo_read_index(struct repository *repo)
 241{
 242        if (!repo->index)
 243                repo->index = xcalloc(1, sizeof(*repo->index));
 244
 245        return read_index_from(repo->index, repo->index_file, repo->gitdir);
 246}