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