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