]> git.proxmox.com Git - libgit2.git/blob - tests/clone/local.c
New upstream version 1.3.0+dfsg.1
[libgit2.git] / tests / clone / local.c
1 #include "clar_libgit2.h"
2
3 #include "git2/clone.h"
4 #include "clone.h"
5 #include "buffer.h"
6 #include "path.h"
7 #include "posix.h"
8 #include "futils.h"
9
10 static int file_url(git_buf *buf, const char *host, const char *path)
11 {
12 if (path[0] == '/')
13 path++;
14
15 git_buf_clear(buf);
16 return git_buf_printf(buf, "file://%s/%s", host, path);
17 }
18
19 #ifdef GIT_WIN32
20 static int git_style_unc_path(git_buf *buf, const char *host, const char *path)
21 {
22 git_buf_clear(buf);
23
24 if (host)
25 git_buf_printf(buf, "//%s/", host);
26
27 if (path[0] == '/')
28 path++;
29
30 if (git__isalpha(path[0]) && path[1] == ':' && path[2] == '/') {
31 git_buf_printf(buf, "%c$/", path[0]);
32 path += 3;
33 }
34
35 git_buf_puts(buf, path);
36
37 return git_buf_oom(buf) ? -1 : 0;
38 }
39
40 static int unc_path(git_buf *buf, const char *host, const char *path)
41 {
42 char *c;
43
44 if (git_style_unc_path(buf, host, path) < 0)
45 return -1;
46
47 for (c = buf->ptr; *c; c++)
48 if (*c == '/')
49 *c = '\\';
50
51 return 0;
52 }
53 #endif
54
55 void test_clone_local__should_clone_local(void)
56 {
57 git_buf buf = GIT_BUF_INIT;
58
59 /* we use a fixture path because it needs to exist for us to want to clone */
60 const char *path = cl_fixture("testrepo.git");
61
62 cl_git_pass(file_url(&buf, "", path));
63 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO));
64 cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL));
65 cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS));
66 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_NO_LOCAL));
67
68 cl_git_pass(file_url(&buf, "localhost", path));
69 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO));
70 cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL));
71 cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS));
72 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_NO_LOCAL));
73
74 cl_git_pass(file_url(&buf, "other-host.mycompany.com", path));
75 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO));
76 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL));
77 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS));
78 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_NO_LOCAL));
79
80 /* Ensure that file:/// urls are percent decoded: .git == %2e%67%69%74 */
81 cl_git_pass(file_url(&buf, "", path));
82 git_buf_shorten(&buf, 4);
83 cl_git_pass(git_buf_puts(&buf, "%2e%67%69%74"));
84 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_AUTO));
85 cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL));
86 cl_assert_equal_i(1, git_clone__should_clone_local(buf.ptr, GIT_CLONE_LOCAL_NO_LINKS));
87 cl_assert_equal_i(0, git_clone__should_clone_local(buf.ptr, GIT_CLONE_NO_LOCAL));
88
89 cl_assert_equal_i(1, git_clone__should_clone_local(path, GIT_CLONE_LOCAL_AUTO));
90 cl_assert_equal_i(1, git_clone__should_clone_local(path, GIT_CLONE_LOCAL));
91 cl_assert_equal_i(1, git_clone__should_clone_local(path, GIT_CLONE_LOCAL_NO_LINKS));
92 cl_assert_equal_i(0, git_clone__should_clone_local(path, GIT_CLONE_NO_LOCAL));
93
94 git_buf_dispose(&buf);
95 }
96
97 void test_clone_local__hardlinks(void)
98 {
99 git_repository *repo;
100 git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
101 git_buf buf = GIT_BUF_INIT;
102 struct stat st;
103
104 /*
105 * In this first clone, we just copy over, since the temp dir
106 * will often be in a different filesystem, so we cannot
107 * link. It also allows us to control the number of links
108 */
109 opts.bare = true;
110 opts.local = GIT_CLONE_LOCAL_NO_LINKS;
111 cl_git_pass(git_clone(&repo, cl_fixture("testrepo.git"), "./clone.git", &opts));
112 git_repository_free(repo);
113
114 /* This second clone is in the same filesystem, so we can hardlink */
115
116 opts.local = GIT_CLONE_LOCAL;
117 cl_git_pass(git_clone(&repo, cl_git_path_url("clone.git"), "./clone2.git", &opts));
118
119 #ifndef GIT_WIN32
120 git_buf_clear(&buf);
121 cl_git_pass(git_buf_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
122
123 cl_git_pass(p_stat(buf.ptr, &st));
124 cl_assert_equal_i(2, st.st_nlink);
125 #endif
126
127 git_repository_free(repo);
128 git_buf_clear(&buf);
129
130 opts.local = GIT_CLONE_LOCAL_NO_LINKS;
131 cl_git_pass(git_clone(&repo, cl_git_path_url("clone.git"), "./clone3.git", &opts));
132
133 git_buf_clear(&buf);
134 cl_git_pass(git_buf_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
135
136 cl_git_pass(p_stat(buf.ptr, &st));
137 cl_assert_equal_i(1, st.st_nlink);
138
139 git_repository_free(repo);
140
141 /* this one should automatically use links */
142 cl_git_pass(git_clone(&repo, "./clone.git", "./clone4.git", NULL));
143
144 #ifndef GIT_WIN32
145 git_buf_clear(&buf);
146 cl_git_pass(git_buf_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125"));
147
148 cl_git_pass(p_stat(buf.ptr, &st));
149 cl_assert_equal_i(3, st.st_nlink);
150 #endif
151
152 git_buf_dispose(&buf);
153 git_repository_free(repo);
154
155 cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
156 cl_git_pass(git_futils_rmdir_r("./clone2.git", NULL, GIT_RMDIR_REMOVE_FILES));
157 cl_git_pass(git_futils_rmdir_r("./clone3.git", NULL, GIT_RMDIR_REMOVE_FILES));
158 cl_git_pass(git_futils_rmdir_r("./clone4.git", NULL, GIT_RMDIR_REMOVE_FILES));
159 }
160
161 void test_clone_local__standard_unc_paths_are_written_git_style(void)
162 {
163 #ifdef GIT_WIN32
164 git_repository *repo;
165 git_remote *remote;
166 git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
167 git_buf unc = GIT_BUF_INIT, git_unc = GIT_BUF_INIT;
168
169 /* we use a fixture path because it needs to exist for us to want to clone */
170 const char *path = cl_fixture("testrepo.git");
171
172 cl_git_pass(unc_path(&unc, "localhost", path));
173 cl_git_pass(git_style_unc_path(&git_unc, "localhost", path));
174
175 cl_git_pass(git_clone(&repo, unc.ptr, "./clone.git", &opts));
176 cl_git_pass(git_remote_lookup(&remote, repo, "origin"));
177
178 cl_assert_equal_s(git_unc.ptr, git_remote_url(remote));
179
180 git_remote_free(remote);
181 git_repository_free(repo);
182 git_buf_dispose(&unc);
183 git_buf_dispose(&git_unc);
184
185 cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
186 #endif
187 }
188
189 void test_clone_local__git_style_unc_paths(void)
190 {
191 #ifdef GIT_WIN32
192 git_repository *repo;
193 git_remote *remote;
194 git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
195 git_buf git_unc = GIT_BUF_INIT;
196
197 /* we use a fixture path because it needs to exist for us to want to clone */
198 const char *path = cl_fixture("testrepo.git");
199
200 cl_git_pass(git_style_unc_path(&git_unc, "localhost", path));
201
202 cl_git_pass(git_clone(&repo, git_unc.ptr, "./clone.git", &opts));
203 cl_git_pass(git_remote_lookup(&remote, repo, "origin"));
204
205 cl_assert_equal_s(git_unc.ptr, git_remote_url(remote));
206
207 git_remote_free(remote);
208 git_repository_free(repo);
209 git_buf_dispose(&git_unc);
210
211 cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
212 #endif
213 }