]> git.proxmox.com Git - libgit2.git/blob - tests/repo/open.c
Merge pull request #1997 from mgbowen/merge-options-init-fix
[libgit2.git] / tests / repo / open.c
1 #include "clar_libgit2.h"
2 #include "fileops.h"
3 #include "sysdir.h"
4 #include <ctype.h>
5
6 void test_repo_open__cleanup(void)
7 {
8 cl_git_sandbox_cleanup();
9
10 if (git_path_isdir("alternate"))
11 git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES);
12 }
13
14 void test_repo_open__bare_empty_repo(void)
15 {
16 git_repository *repo = cl_git_sandbox_init("empty_bare.git");
17
18 cl_assert(git_repository_path(repo) != NULL);
19 cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0);
20 cl_assert(git_repository_workdir(repo) == NULL);
21 }
22
23 void test_repo_open__standard_empty_repo_through_gitdir(void)
24 {
25 git_repository *repo;
26
27 cl_git_pass(git_repository_open(&repo, cl_fixture("empty_standard_repo/.gitted")));
28
29 cl_assert(git_repository_path(repo) != NULL);
30 cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0);
31
32 cl_assert(git_repository_workdir(repo) != NULL);
33 cl_assert(git__suffixcmp(git_repository_workdir(repo), "/") == 0);
34
35 git_repository_free(repo);
36 }
37
38 void test_repo_open__standard_empty_repo_through_workdir(void)
39 {
40 git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
41
42 cl_assert(git_repository_path(repo) != NULL);
43 cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0);
44
45 cl_assert(git_repository_workdir(repo) != NULL);
46 cl_assert(git__suffixcmp(git_repository_workdir(repo), "/") == 0);
47 }
48
49
50 void test_repo_open__open_with_discover(void)
51 {
52 static const char *variants[] = {
53 "attr", "attr/", "attr/.git", "attr/.git/",
54 "attr/sub", "attr/sub/", "attr/sub/sub", "attr/sub/sub/",
55 NULL
56 };
57 git_repository *repo;
58 const char **scan;
59
60 cl_fixture_sandbox("attr");
61 cl_git_pass(p_rename("attr/.gitted", "attr/.git"));
62
63 for (scan = variants; *scan != NULL; scan++) {
64 cl_git_pass(git_repository_open_ext(&repo, *scan, 0, NULL));
65 cl_assert(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0);
66 cl_assert(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0);
67 git_repository_free(repo);
68 }
69
70 cl_fixture_cleanup("attr");
71 }
72
73 static void make_gitlink_dir(const char *dir, const char *linktext)
74 {
75 git_buf path = GIT_BUF_INIT;
76
77 cl_git_pass(git_futils_mkdir(dir, NULL, 0777, GIT_MKDIR_VERIFY_DIR));
78 cl_git_pass(git_buf_joinpath(&path, dir, ".git"));
79 cl_git_rewritefile(path.ptr, linktext);
80 git_buf_free(&path);
81 }
82
83 void test_repo_open__gitlinked(void)
84 {
85 /* need to have both repo dir and workdir set up correctly */
86 git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
87 git_repository *repo2;
88
89 make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git");
90
91 cl_git_pass(git_repository_open(&repo2, "alternate"));
92
93 cl_assert(git_repository_path(repo2) != NULL);
94 cl_assert_(git__suffixcmp(git_repository_path(repo2), "empty_standard_repo/.git/") == 0, git_repository_path(repo2));
95 cl_assert_equal_s(git_repository_path(repo), git_repository_path(repo2));
96
97 cl_assert(git_repository_workdir(repo2) != NULL);
98 cl_assert_(git__suffixcmp(git_repository_workdir(repo2), "alternate/") == 0, git_repository_workdir(repo2));
99
100 git_repository_free(repo2);
101 }
102
103 void test_repo_open__from_git_new_workdir(void)
104 {
105 /* The git-new-workdir script that ships with git sets up a bunch of
106 * symlinks to create a second workdir that shares the object db with
107 * another checkout. Libgit2 can open a repo that has been configured
108 * this way.
109 */
110 cl_git_sandbox_init("empty_standard_repo");
111
112 #ifndef GIT_WIN32
113 git_repository *repo2;
114 git_buf link_tgt = GIT_BUF_INIT, link = GIT_BUF_INIT, body = GIT_BUF_INIT;
115 const char **scan;
116 int link_fd;
117 static const char *links[] = {
118 "config", "refs", "logs/refs", "objects", "info", "hooks",
119 "packed-refs", "remotes", "rr-cache", "svn", NULL
120 };
121 static const char *copies[] = {
122 "HEAD", NULL
123 };
124
125 cl_git_pass(p_mkdir("alternate", 0777));
126 cl_git_pass(p_mkdir("alternate/.git", 0777));
127
128 for (scan = links; *scan != NULL; scan++) {
129 git_buf_joinpath(&link_tgt, "empty_standard_repo/.git", *scan);
130 if (git_path_exists(link_tgt.ptr)) {
131 git_buf_joinpath(&link_tgt, "../../empty_standard_repo/.git", *scan);
132 git_buf_joinpath(&link, "alternate/.git", *scan);
133 if (strchr(*scan, '/'))
134 git_futils_mkpath2file(link.ptr, 0777);
135 cl_assert_(symlink(link_tgt.ptr, link.ptr) == 0, strerror(errno));
136 }
137 }
138 for (scan = copies; *scan != NULL; scan++) {
139 git_buf_joinpath(&link_tgt, "empty_standard_repo/.git", *scan);
140 if (git_path_exists(link_tgt.ptr)) {
141 git_buf_joinpath(&link, "alternate/.git", *scan);
142 cl_git_pass(git_futils_readbuffer(&body, link_tgt.ptr));
143
144 cl_assert((link_fd = git_futils_creat_withpath(link.ptr, 0777, 0666)) >= 0);
145 cl_must_pass(p_write(link_fd, body.ptr, body.size));
146 p_close(link_fd);
147 }
148 }
149
150 git_buf_free(&link_tgt);
151 git_buf_free(&link);
152 git_buf_free(&body);
153
154
155 cl_git_pass(git_repository_open(&repo2, "alternate"));
156
157 cl_assert(git_repository_path(repo2) != NULL);
158 cl_assert_(git__suffixcmp(git_repository_path(repo2), "alternate/.git/") == 0, git_repository_path(repo2));
159
160 cl_assert(git_repository_workdir(repo2) != NULL);
161 cl_assert_(git__suffixcmp(git_repository_workdir(repo2), "alternate/") == 0, git_repository_workdir(repo2));
162
163 git_repository_free(repo2);
164 #endif
165 }
166
167 void test_repo_open__failures(void)
168 {
169 git_repository *base, *repo;
170 git_buf ceiling = GIT_BUF_INIT;
171
172 base = cl_git_sandbox_init("attr");
173 cl_git_pass(git_buf_sets(&ceiling, git_repository_workdir(base)));
174
175 /* fail with no searching */
176 cl_git_fail(git_repository_open(&repo, "attr/sub"));
177 cl_git_fail(git_repository_open_ext(
178 &repo, "attr/sub", GIT_REPOSITORY_OPEN_NO_SEARCH, NULL));
179
180 /* fail with ceiling too low */
181 cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub"));
182 cl_git_fail(git_repository_open_ext(&repo, "attr/sub", 0, ceiling.ptr));
183
184 /* fail with no repo */
185 cl_git_pass(p_mkdir("alternate", 0777));
186 cl_git_pass(p_mkdir("alternate/.git", 0777));
187 cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL));
188 cl_git_fail(git_repository_open_ext(&repo, "alternate/.git", 0, NULL));
189
190 git_buf_free(&ceiling);
191 }
192
193 void test_repo_open__bad_gitlinks(void)
194 {
195 git_repository *repo;
196 static const char *bad_links[] = {
197 "garbage\n", "gitdir", "gitdir:\n", "gitdir: foobar",
198 "gitdir: ../invalid", "gitdir: ../invalid2",
199 "gitdir: ../attr/.git with extra stuff",
200 NULL
201 };
202 const char **scan;
203
204 cl_git_sandbox_init("attr");
205
206 cl_git_pass(p_mkdir("invalid", 0777));
207 cl_git_pass(git_futils_mkdir_r("invalid2/.git", NULL, 0777));
208
209 for (scan = bad_links; *scan != NULL; scan++) {
210 make_gitlink_dir("alternate", *scan);
211 cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL));
212 }
213
214 git_futils_rmdir_r("invalid", NULL, GIT_RMDIR_REMOVE_FILES);
215 git_futils_rmdir_r("invalid2", NULL, GIT_RMDIR_REMOVE_FILES);
216 }
217
218 #ifdef GIT_WIN32
219 static void unposix_path(git_buf *path)
220 {
221 char *src, *tgt;
222
223 src = tgt = path->ptr;
224
225 /* convert "/d/..." to "d:\..." */
226 if (src[0] == '/' && isalpha(src[1]) && src[2] == '/') {
227 *tgt++ = src[1];
228 *tgt++ = ':';
229 *tgt++ = '\\';
230 src += 3;
231 }
232
233 while (*src) {
234 *tgt++ = (*src == '/') ? '\\' : *src;
235 src++;
236 }
237
238 *tgt = '\0';
239 }
240 #endif
241
242 void test_repo_open__win32_path(void)
243 {
244 #ifdef GIT_WIN32
245 git_repository *repo = cl_git_sandbox_init("empty_standard_repo"), *repo2;
246 git_buf winpath = GIT_BUF_INIT;
247 static const char *repo_path = "empty_standard_repo/.git/";
248 static const char *repo_wd = "empty_standard_repo/";
249
250 cl_assert(git__suffixcmp(git_repository_path(repo), repo_path) == 0);
251 cl_assert(git__suffixcmp(git_repository_workdir(repo), repo_wd) == 0);
252
253 cl_git_pass(git_buf_sets(&winpath, git_repository_path(repo)));
254 unposix_path(&winpath);
255 cl_git_pass(git_repository_open(&repo2, winpath.ptr));
256 cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0);
257 cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0);
258 git_repository_free(repo2);
259
260 cl_git_pass(git_buf_sets(&winpath, git_repository_path(repo)));
261 git_buf_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */
262 unposix_path(&winpath);
263 cl_git_pass(git_repository_open(&repo2, winpath.ptr));
264 cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0);
265 cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0);
266 git_repository_free(repo2);
267
268 cl_git_pass(git_buf_sets(&winpath, git_repository_workdir(repo)));
269 unposix_path(&winpath);
270 cl_git_pass(git_repository_open(&repo2, winpath.ptr));
271 cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0);
272 cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0);
273 git_repository_free(repo2);
274
275 cl_git_pass(git_buf_sets(&winpath, git_repository_workdir(repo)));
276 git_buf_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */
277 unposix_path(&winpath);
278 cl_git_pass(git_repository_open(&repo2, winpath.ptr));
279 cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0);
280 cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0);
281 git_repository_free(repo2);
282
283 git_buf_free(&winpath);
284 #endif
285 }
286
287 void test_repo_open__opening_a_non_existing_repository_returns_ENOTFOUND(void)
288 {
289 git_repository *repo;
290 cl_assert_equal_i(GIT_ENOTFOUND, git_repository_open(&repo, "i-do-not/exist"));
291 }
292
293 void test_repo_open__no_config(void)
294 {
295 git_buf path = GIT_BUF_INIT;
296 git_repository *repo;
297 git_config *config;
298
299 cl_fixture_sandbox("empty_standard_repo");
300 cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
301
302 /* remove local config */
303 cl_git_pass(git_futils_rmdir_r(
304 "empty_standard_repo/.git/config", NULL, GIT_RMDIR_REMOVE_FILES));
305
306 /* isolate from system level configs */
307 cl_must_pass(p_mkdir("alternate", 0777));
308 cl_git_pass(git_path_prettify(&path, "alternate", NULL));
309 cl_git_pass(git_libgit2_opts(
310 GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
311 cl_git_pass(git_libgit2_opts(
312 GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr));
313 cl_git_pass(git_libgit2_opts(
314 GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr));
315
316 git_buf_free(&path);
317
318 cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
319 cl_git_pass(git_repository_config(&config, repo));
320
321 cl_git_pass(git_config_set_string(config, "test.set", "42"));
322
323 git_config_free(config);
324 git_repository_free(repo);
325 cl_fixture_cleanup("empty_standard_repo");
326
327 git_sysdir_global_shutdown();
328 }
329
330 void test_repo_open__force_bare(void)
331 {
332 /* need to have both repo dir and workdir set up correctly */
333 git_repository *repo = cl_git_sandbox_init("empty_standard_repo");
334 git_repository *barerepo;
335
336 make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git");
337
338 cl_assert(!git_repository_is_bare(repo));
339
340 cl_git_pass(git_repository_open(&barerepo, "alternate"));
341 cl_assert(!git_repository_is_bare(barerepo));
342 git_repository_free(barerepo);
343
344 cl_git_pass(git_repository_open_bare(
345 &barerepo, "empty_standard_repo/.git"));
346 cl_assert(git_repository_is_bare(barerepo));
347 git_repository_free(barerepo);
348
349 cl_git_fail(git_repository_open_bare(&barerepo, "alternate/.git"));
350
351 cl_git_pass(git_repository_open_ext(
352 &barerepo, "alternate/.git", GIT_REPOSITORY_OPEN_BARE, NULL));
353 cl_assert(git_repository_is_bare(barerepo));
354 git_repository_free(barerepo);
355
356 cl_git_pass(p_mkdir("empty_standard_repo/subdir", 0777));
357 cl_git_mkfile("empty_standard_repo/subdir/something.txt", "something");
358
359 cl_git_fail(git_repository_open_bare(
360 &barerepo, "empty_standard_repo/subdir"));
361
362 cl_git_pass(git_repository_open_ext(
363 &barerepo, "empty_standard_repo/subdir", GIT_REPOSITORY_OPEN_BARE, NULL));
364 cl_assert(git_repository_is_bare(barerepo));
365 git_repository_free(barerepo);
366
367 cl_git_pass(p_mkdir("alternate/subdir", 0777));
368 cl_git_pass(p_mkdir("alternate/subdir/sub2", 0777));
369 cl_git_mkfile("alternate/subdir/sub2/something.txt", "something");
370
371 cl_git_fail(git_repository_open_bare(&barerepo, "alternate/subdir/sub2"));
372
373 cl_git_pass(git_repository_open_ext(
374 &barerepo, "alternate/subdir/sub2", GIT_REPOSITORY_OPEN_BARE, NULL));
375 cl_assert(git_repository_is_bare(barerepo));
376 git_repository_free(barerepo);
377 }