]>
Commit | Line | Data |
---|---|---|
121b2673 CMN |
1 | #include "clar_libgit2.h" |
2 | ||
3 | #include "git2/clone.h" | |
4 | #include "clone.h" | |
5 | #include "buffer.h" | |
2614819c CMN |
6 | #include "path.h" |
7 | #include "posix.h" | |
22a2d3d5 | 8 | #include "futils.h" |
121b2673 | 9 | |
529fd30d ET |
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 | ||
7d7f6d33 | 19 | #ifdef GIT_WIN32 |
12f32d91 ET |
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 | ||
16288d2d | 30 | if (git__isalpha(path[0]) && path[1] == ':' && path[2] == '/') { |
12f32d91 ET |
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 | } | |
7d7f6d33 | 53 | #endif |
12f32d91 | 54 | |
121b2673 CMN |
55 | void test_clone_local__should_clone_local(void) |
56 | { | |
57 | git_buf buf = GIT_BUF_INIT; | |
121b2673 CMN |
58 | |
59 | /* we use a fixture path because it needs to exist for us to want to clone */ | |
529fd30d ET |
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)); | |
121b2673 | 67 | |
529fd30d ET |
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 | ||
ac3d33df | 94 | git_buf_dispose(&buf); |
121b2673 | 95 | } |
2614819c CMN |
96 | |
97 | void test_clone_local__hardlinks(void) | |
98 | { | |
99 | git_repository *repo; | |
6812afaf | 100 | git_clone_options opts = GIT_CLONE_OPTIONS_INIT; |
2614819c CMN |
101 | git_buf buf = GIT_BUF_INIT; |
102 | struct stat st; | |
103 | ||
bc9f67fa CMN |
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 | */ | |
6812afaf CMN |
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)); | |
2614819c CMN |
112 | git_repository_free(repo); |
113 | ||
bc9f67fa | 114 | /* This second clone is in the same filesystem, so we can hardlink */ |
2614819c | 115 | |
6812afaf CMN |
116 | opts.local = GIT_CLONE_LOCAL; |
117 | cl_git_pass(git_clone(&repo, cl_git_path_url("clone.git"), "./clone2.git", &opts)); | |
2614819c CMN |
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)); | |
bc9f67fa | 124 | cl_assert_equal_i(2, st.st_nlink); |
2614819c CMN |
125 | #endif |
126 | ||
2614819c CMN |
127 | git_repository_free(repo); |
128 | git_buf_clear(&buf); | |
129 | ||
6812afaf CMN |
130 | opts.local = GIT_CLONE_LOCAL_NO_LINKS; |
131 | cl_git_pass(git_clone(&repo, cl_git_path_url("clone.git"), "./clone3.git", &opts)); | |
2614819c CMN |
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 | ||
bc9f67fa CMN |
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 | ||
ac3d33df | 152 | git_buf_dispose(&buf); |
2614819c | 153 | git_repository_free(repo); |
bc9f67fa CMN |
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)); | |
2614819c | 159 | } |
12f32d91 ET |
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)); | |
209425ce | 176 | cl_git_pass(git_remote_lookup(&remote, repo, "origin")); |
12f32d91 ET |
177 | |
178 | cl_assert_equal_s(git_unc.ptr, git_remote_url(remote)); | |
179 | ||
180 | git_remote_free(remote); | |
181 | git_repository_free(repo); | |
ac3d33df JK |
182 | git_buf_dispose(&unc); |
183 | git_buf_dispose(&git_unc); | |
12f32d91 ET |
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)); | |
209425ce | 203 | cl_git_pass(git_remote_lookup(&remote, repo, "origin")); |
12f32d91 ET |
204 | |
205 | cl_assert_equal_s(git_unc.ptr, git_remote_url(remote)); | |
206 | ||
207 | git_remote_free(remote); | |
208 | git_repository_free(repo); | |
ac3d33df | 209 | git_buf_dispose(&git_unc); |
12f32d91 ET |
210 | |
211 | cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES)); | |
212 | #endif | |
213 | } |