]>
Commit | Line | Data |
---|---|---|
613d5eb9 PK |
1 | #include "clar_libgit2.h" |
2 | #include "buffer.h" | |
3 | #include "posix.h" | |
4 | #include "vector.h" | |
5 | #include "../submodule/submodule_helpers.h" | |
6 | #include "push_util.h" | |
7 | ||
613d5eb9 PK |
8 | static git_repository *_repo; |
9 | ||
10 | static char *_remote_url; | |
11 | static char *_remote_user; | |
12 | static char *_remote_pass; | |
13 | ||
14 | static git_remote *_remote; | |
15 | static record_callbacks_data _record_cbs_data = {{ 0 }}; | |
16 | static git_remote_callbacks _record_cbs = RECORD_CALLBACKS_INIT(&_record_cbs_data); | |
17 | ||
18 | static git_oid _oid_b6; | |
19 | static git_oid _oid_b5; | |
20 | static git_oid _oid_b4; | |
21 | static git_oid _oid_b3; | |
22 | static git_oid _oid_b2; | |
23 | static git_oid _oid_b1; | |
24 | ||
abeefbbe MS |
25 | static git_oid _tag_commit; |
26 | static git_oid _tag_tree; | |
27 | static git_oid _tag_blob; | |
28 | static git_oid _tag_lightweight; | |
29 | ||
59bccf33 | 30 | static int cred_acquire_cb(git_cred **cred, const char *url, unsigned int allowed_types, void *payload) |
613d5eb9 PK |
31 | { |
32 | GIT_UNUSED(url); | |
33 | ||
59bccf33 BS |
34 | *((bool*)payload) = true; |
35 | ||
613d5eb9 PK |
36 | if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 || |
37 | git_cred_userpass_plaintext_new(cred, _remote_user, _remote_pass) < 0) | |
38 | return -1; | |
39 | ||
40 | return 0; | |
41 | } | |
42 | ||
43 | typedef struct { | |
44 | const char *ref; | |
45 | const char *msg; | |
46 | } push_status; | |
47 | ||
48 | /** | |
49 | * git_push_status_foreach callback that records status entries. | |
50 | * @param data (git_vector *) of push_status instances | |
51 | */ | |
52 | static int record_push_status_cb(const char *ref, const char *msg, void *data) | |
53 | { | |
54 | git_vector *statuses = (git_vector *)data; | |
55 | push_status *s; | |
56 | ||
57 | cl_assert(s = git__malloc(sizeof(*s))); | |
58 | s->ref = ref; | |
59 | s->msg = msg; | |
60 | ||
61 | git_vector_insert(statuses, s); | |
62 | ||
63 | return 0; | |
64 | } | |
65 | ||
66 | static void do_verify_push_status(git_push *push, const push_status expected[], const size_t expected_len) | |
67 | { | |
68 | git_vector actual = GIT_VECTOR_INIT; | |
69 | push_status *iter; | |
70 | bool failed = false; | |
71 | size_t i; | |
72 | ||
73 | git_push_status_foreach(push, record_push_status_cb, &actual); | |
74 | ||
75 | if (expected_len != actual.length) | |
76 | failed = true; | |
77 | else | |
78 | git_vector_foreach(&actual, i, iter) | |
79 | if (strcmp(expected[i].ref, iter->ref) || | |
80 | (expected[i].msg && strcmp(expected[i].msg, iter->msg))) { | |
81 | failed = true; | |
82 | break; | |
83 | } | |
84 | ||
85 | if (failed) { | |
86 | git_buf msg = GIT_BUF_INIT; | |
87 | ||
88 | git_buf_puts(&msg, "Expected and actual push statuses differ:\nEXPECTED:\n"); | |
89 | ||
90 | for(i = 0; i < expected_len; i++) { | |
91 | git_buf_printf(&msg, "%s: %s\n", | |
92 | expected[i].ref, | |
93 | expected[i].msg ? expected[i].msg : "<NULL>"); | |
94 | } | |
95 | ||
96 | git_buf_puts(&msg, "\nACTUAL:\n"); | |
97 | ||
98 | git_vector_foreach(&actual, i, iter) | |
99 | git_buf_printf(&msg, "%s: %s\n", iter->ref, iter->msg); | |
100 | ||
101 | cl_fail(git_buf_cstr(&msg)); | |
102 | ||
103 | git_buf_free(&msg); | |
104 | } | |
105 | ||
106 | git_vector_foreach(&actual, i, iter) | |
107 | git__free(iter); | |
108 | ||
109 | git_vector_free(&actual); | |
110 | } | |
111 | ||
112 | /** | |
113 | * Verifies that after git_push_finish(), refs on a remote have the expected | |
114 | * names, oids, and order. | |
156cfec0 | 115 | * |
613d5eb9 PK |
116 | * @param remote remote to verify |
117 | * @param expected_refs expected remote refs after push | |
118 | * @param expected_refs_len length of expected_refs | |
119 | */ | |
120 | static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) | |
121 | { | |
122 | git_vector actual_refs = GIT_VECTOR_INIT; | |
123 | ||
124 | git_remote_ls(remote, record_ref_cb, &actual_refs); | |
125 | verify_remote_refs(&actual_refs, expected_refs, expected_refs_len); | |
126 | ||
127 | git_vector_free(&actual_refs); | |
128 | } | |
129 | ||
6443eaf2 | 130 | void test_online_push__initialize(void) |
613d5eb9 PK |
131 | { |
132 | git_vector delete_specs = GIT_VECTOR_INIT; | |
133 | size_t i; | |
134 | char *curr_del_spec; | |
59bccf33 | 135 | bool cred_acquire_called = false; |
613d5eb9 PK |
136 | |
137 | _repo = cl_git_sandbox_init("push_src"); | |
138 | ||
139 | cl_fixture_sandbox("testrepo.git"); | |
140 | cl_rename("push_src/submodule/.gitted", "push_src/submodule/.git"); | |
141 | ||
142 | rewrite_gitmodules(git_repository_workdir(_repo)); | |
143 | ||
144 | /* git log --format=oneline --decorate --graph | |
145 | * *-. 951bbbb90e2259a4c8950db78946784fb53fcbce (HEAD, b6) merge b3, b4, and b5 to b6 | |
146 | * |\ \ | |
147 | * | | * fa38b91f199934685819bea316186d8b008c52a2 (b5) added submodule named 'submodule' pointing to '../testrepo.git' | |
148 | * | * | 27b7ce66243eb1403862d05f958c002312df173d (b4) edited fold\b.txt | |
149 | * | |/ | |
150 | * * | d9b63a88223d8367516f50bd131a5f7349b7f3e4 (b3) edited a.txt | |
151 | * |/ | |
152 | * * a78705c3b2725f931d3ee05348d83cc26700f247 (b2, b1) added fold and fold/b.txt | |
153 | * * 5c0bb3d1b9449d1cc69d7519fd05166f01840915 added a.txt | |
154 | */ | |
155 | git_oid_fromstr(&_oid_b6, "951bbbb90e2259a4c8950db78946784fb53fcbce"); | |
156 | git_oid_fromstr(&_oid_b5, "fa38b91f199934685819bea316186d8b008c52a2"); | |
157 | git_oid_fromstr(&_oid_b4, "27b7ce66243eb1403862d05f958c002312df173d"); | |
158 | git_oid_fromstr(&_oid_b3, "d9b63a88223d8367516f50bd131a5f7349b7f3e4"); | |
159 | git_oid_fromstr(&_oid_b2, "a78705c3b2725f931d3ee05348d83cc26700f247"); | |
160 | git_oid_fromstr(&_oid_b1, "a78705c3b2725f931d3ee05348d83cc26700f247"); | |
161 | ||
abeefbbe MS |
162 | git_oid_fromstr(&_tag_commit, "805c54522e614f29f70d2413a0470247d8b424ac"); |
163 | git_oid_fromstr(&_tag_tree, "ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e"); | |
164 | git_oid_fromstr(&_tag_blob, "b483ae7ba66decee9aee971f501221dea84b1498"); | |
165 | git_oid_fromstr(&_tag_lightweight, "951bbbb90e2259a4c8950db78946784fb53fcbce"); | |
166 | ||
613d5eb9 PK |
167 | /* Remote URL environment variable must be set. User and password are optional. */ |
168 | _remote_url = cl_getenv("GITTEST_REMOTE_URL"); | |
169 | _remote_user = cl_getenv("GITTEST_REMOTE_USER"); | |
170 | _remote_pass = cl_getenv("GITTEST_REMOTE_PASS"); | |
171 | _remote = NULL; | |
172 | ||
173 | if (_remote_url) { | |
29f27599 | 174 | cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); |
613d5eb9 | 175 | |
59bccf33 | 176 | git_remote_set_cred_acquire_cb(_remote, cred_acquire_cb, &cred_acquire_called); |
613d5eb9 PK |
177 | record_callbacks_data_clear(&_record_cbs_data); |
178 | git_remote_set_callbacks(_remote, &_record_cbs); | |
179 | ||
180 | cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); | |
181 | ||
182 | /* Clean up previously pushed branches. Fails if receive.denyDeletes is | |
183 | * set on the remote. Also, on Git 1.7.0 and newer, you must run | |
184 | * 'git config receive.denyDeleteCurrent ignore' in the remote repo in | |
185 | * order to delete the remote branch pointed to by HEAD (usually master). | |
186 | * See: https://raw.github.com/git/git/master/Documentation/RelNotes/1.7.0.txt | |
187 | */ | |
188 | cl_git_pass(git_remote_ls(_remote, delete_ref_cb, &delete_specs)); | |
189 | if (delete_specs.length) { | |
190 | git_push *push; | |
191 | ||
192 | cl_git_pass(git_push_new(&push, _remote)); | |
193 | ||
194 | git_vector_foreach(&delete_specs, i, curr_del_spec) { | |
195 | git_push_add_refspec(push, curr_del_spec); | |
196 | git__free(curr_del_spec); | |
197 | } | |
198 | ||
199 | cl_git_pass(git_push_finish(push)); | |
200 | git_push_free(push); | |
201 | } | |
202 | ||
203 | git_remote_disconnect(_remote); | |
204 | git_vector_free(&delete_specs); | |
205 | ||
206 | /* Now that we've deleted everything, fetch from the remote */ | |
207 | cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_FETCH)); | |
208 | cl_git_pass(git_remote_download(_remote, NULL, NULL)); | |
209 | cl_git_pass(git_remote_update_tips(_remote)); | |
210 | git_remote_disconnect(_remote); | |
211 | } else | |
212 | printf("GITTEST_REMOTE_URL unset; skipping push test\n"); | |
213 | } | |
214 | ||
6443eaf2 | 215 | void test_online_push__cleanup(void) |
613d5eb9 PK |
216 | { |
217 | if (_remote) | |
218 | git_remote_free(_remote); | |
c4e3e797 BS |
219 | _remote = NULL; |
220 | ||
221 | /* Freed by cl_git_sandbox_cleanup */ | |
222 | _repo = NULL; | |
613d5eb9 PK |
223 | |
224 | record_callbacks_data_clear(&_record_cbs_data); | |
225 | ||
226 | cl_fixture_cleanup("testrepo.git"); | |
227 | cl_git_sandbox_cleanup(); | |
228 | } | |
229 | ||
230 | /** | |
231 | * Calls push and relists refs on remote to verify success. | |
156cfec0 | 232 | * |
613d5eb9 PK |
233 | * @param refspecs refspecs to push |
234 | * @param refspecs_len length of refspecs | |
235 | * @param expected_refs expected remote refs after push | |
236 | * @param expected_refs_len length of expected_refs | |
237 | * @param expected_ret expected return value from git_push_finish() | |
238 | */ | |
239 | static void do_push(const char *refspecs[], size_t refspecs_len, | |
240 | push_status expected_statuses[], size_t expected_statuses_len, | |
241 | expected_ref expected_refs[], size_t expected_refs_len, int expected_ret) | |
242 | { | |
243 | git_push *push; | |
244 | size_t i; | |
245 | int ret; | |
246 | ||
247 | if (_remote) { | |
248 | cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); | |
249 | ||
250 | cl_git_pass(git_push_new(&push, _remote)); | |
251 | ||
252 | for (i = 0; i < refspecs_len; i++) | |
253 | cl_git_pass(git_push_add_refspec(push, refspecs[i])); | |
254 | ||
255 | if (expected_ret < 0) { | |
256 | cl_git_fail(ret = git_push_finish(push)); | |
257 | cl_assert_equal_i(0, git_push_unpack_ok(push)); | |
258 | } | |
259 | else { | |
260 | cl_git_pass(ret = git_push_finish(push)); | |
261 | cl_assert_equal_i(1, git_push_unpack_ok(push)); | |
262 | } | |
263 | ||
264 | do_verify_push_status(push, expected_statuses, expected_statuses_len); | |
265 | ||
266 | cl_assert_equal_i(expected_ret, ret); | |
267 | ||
268 | git_push_free(push); | |
269 | ||
270 | verify_refs(_remote, expected_refs, expected_refs_len); | |
271 | ||
272 | cl_git_pass(git_remote_update_tips(_remote)); | |
273 | ||
274 | git_remote_disconnect(_remote); | |
275 | } | |
276 | } | |
277 | ||
278 | /* Call push_finish() without ever calling git_push_add_refspec() */ | |
6443eaf2 | 279 | void test_online_push__noop(void) |
613d5eb9 PK |
280 | { |
281 | do_push(NULL, 0, NULL, 0, NULL, 0, 0); | |
282 | } | |
283 | ||
6443eaf2 | 284 | void test_online_push__b1(void) |
613d5eb9 PK |
285 | { |
286 | const char *specs[] = { "refs/heads/b1:refs/heads/b1" }; | |
287 | push_status exp_stats[] = { { "refs/heads/b1", NULL } }; | |
288 | expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } }; | |
289 | do_push(specs, ARRAY_SIZE(specs), | |
290 | exp_stats, ARRAY_SIZE(exp_stats), | |
291 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
292 | } | |
293 | ||
6443eaf2 | 294 | void test_online_push__b2(void) |
613d5eb9 PK |
295 | { |
296 | const char *specs[] = { "refs/heads/b2:refs/heads/b2" }; | |
297 | push_status exp_stats[] = { { "refs/heads/b2", NULL } }; | |
298 | expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } }; | |
299 | do_push(specs, ARRAY_SIZE(specs), | |
300 | exp_stats, ARRAY_SIZE(exp_stats), | |
301 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
302 | } | |
303 | ||
6443eaf2 | 304 | void test_online_push__b3(void) |
613d5eb9 PK |
305 | { |
306 | const char *specs[] = { "refs/heads/b3:refs/heads/b3" }; | |
307 | push_status exp_stats[] = { { "refs/heads/b3", NULL } }; | |
308 | expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } }; | |
309 | do_push(specs, ARRAY_SIZE(specs), | |
310 | exp_stats, ARRAY_SIZE(exp_stats), | |
311 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
312 | } | |
313 | ||
6443eaf2 | 314 | void test_online_push__b4(void) |
613d5eb9 PK |
315 | { |
316 | const char *specs[] = { "refs/heads/b4:refs/heads/b4" }; | |
317 | push_status exp_stats[] = { { "refs/heads/b4", NULL } }; | |
318 | expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } }; | |
319 | do_push(specs, ARRAY_SIZE(specs), | |
320 | exp_stats, ARRAY_SIZE(exp_stats), | |
321 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
322 | } | |
323 | ||
6443eaf2 | 324 | void test_online_push__b5(void) |
613d5eb9 PK |
325 | { |
326 | const char *specs[] = { "refs/heads/b5:refs/heads/b5" }; | |
327 | push_status exp_stats[] = { { "refs/heads/b5", NULL } }; | |
328 | expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } }; | |
329 | do_push(specs, ARRAY_SIZE(specs), | |
330 | exp_stats, ARRAY_SIZE(exp_stats), | |
331 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
332 | } | |
333 | ||
6443eaf2 | 334 | void test_online_push__multi(void) |
613d5eb9 PK |
335 | { |
336 | const char *specs[] = { | |
337 | "refs/heads/b1:refs/heads/b1", | |
338 | "refs/heads/b2:refs/heads/b2", | |
339 | "refs/heads/b3:refs/heads/b3", | |
340 | "refs/heads/b4:refs/heads/b4", | |
341 | "refs/heads/b5:refs/heads/b5" | |
342 | }; | |
343 | push_status exp_stats[] = { | |
344 | { "refs/heads/b1", NULL }, | |
345 | { "refs/heads/b2", NULL }, | |
346 | { "refs/heads/b3", NULL }, | |
347 | { "refs/heads/b4", NULL }, | |
348 | { "refs/heads/b5", NULL } | |
349 | }; | |
350 | expected_ref exp_refs[] = { | |
351 | { "refs/heads/b1", &_oid_b1 }, | |
352 | { "refs/heads/b2", &_oid_b2 }, | |
353 | { "refs/heads/b3", &_oid_b3 }, | |
354 | { "refs/heads/b4", &_oid_b4 }, | |
355 | { "refs/heads/b5", &_oid_b5 } | |
356 | }; | |
357 | do_push(specs, ARRAY_SIZE(specs), | |
358 | exp_stats, ARRAY_SIZE(exp_stats), | |
359 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
360 | } | |
361 | ||
6443eaf2 | 362 | void test_online_push__implicit_tgt(void) |
613d5eb9 PK |
363 | { |
364 | const char *specs1[] = { "refs/heads/b1:" }; | |
365 | push_status exp_stats1[] = { { "refs/heads/b1", NULL } }; | |
366 | expected_ref exp_refs1[] = { { "refs/heads/b1", &_oid_b1 } }; | |
367 | ||
368 | const char *specs2[] = { "refs/heads/b2:" }; | |
369 | push_status exp_stats2[] = { { "refs/heads/b2", NULL } }; | |
370 | expected_ref exp_refs2[] = { | |
371 | { "refs/heads/b1", &_oid_b1 }, | |
372 | { "refs/heads/b2", &_oid_b2 } | |
373 | }; | |
374 | ||
375 | do_push(specs1, ARRAY_SIZE(specs1), | |
376 | exp_stats1, ARRAY_SIZE(exp_stats1), | |
377 | exp_refs1, ARRAY_SIZE(exp_refs1), 0); | |
378 | do_push(specs2, ARRAY_SIZE(specs2), | |
379 | exp_stats2, ARRAY_SIZE(exp_stats2), | |
380 | exp_refs2, ARRAY_SIZE(exp_refs2), 0); | |
381 | } | |
382 | ||
6443eaf2 | 383 | void test_online_push__fast_fwd(void) |
613d5eb9 PK |
384 | { |
385 | /* Fast forward b1 in tgt from _oid_b1 to _oid_b6. */ | |
386 | ||
387 | const char *specs_init[] = { "refs/heads/b1:refs/heads/b1" }; | |
388 | push_status exp_stats_init[] = { { "refs/heads/b1", NULL } }; | |
389 | expected_ref exp_refs_init[] = { { "refs/heads/b1", &_oid_b1 } }; | |
390 | ||
391 | const char *specs_ff[] = { "refs/heads/b6:refs/heads/b1" }; | |
392 | push_status exp_stats_ff[] = { { "refs/heads/b1", NULL } }; | |
393 | expected_ref exp_refs_ff[] = { { "refs/heads/b1", &_oid_b6 } }; | |
394 | ||
395 | /* Do a force push to reset b1 in target back to _oid_b1 */ | |
396 | const char *specs_reset[] = { "+refs/heads/b1:refs/heads/b1" }; | |
397 | /* Force should have no effect on a fast forward push */ | |
398 | const char *specs_ff_force[] = { "+refs/heads/b6:refs/heads/b1" }; | |
399 | ||
400 | do_push(specs_init, ARRAY_SIZE(specs_init), | |
401 | exp_stats_init, ARRAY_SIZE(exp_stats_init), | |
402 | exp_refs_init, ARRAY_SIZE(exp_refs_init), 0); | |
403 | ||
404 | do_push(specs_ff, ARRAY_SIZE(specs_ff), | |
405 | exp_stats_ff, ARRAY_SIZE(exp_stats_ff), | |
406 | exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0); | |
407 | ||
408 | do_push(specs_reset, ARRAY_SIZE(specs_reset), | |
409 | exp_stats_init, ARRAY_SIZE(exp_stats_init), | |
410 | exp_refs_init, ARRAY_SIZE(exp_refs_init), 0); | |
411 | ||
412 | do_push(specs_ff_force, ARRAY_SIZE(specs_ff_force), | |
413 | exp_stats_ff, ARRAY_SIZE(exp_stats_ff), | |
414 | exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0); | |
415 | } | |
416 | ||
abeefbbe MS |
417 | void test_online_push__tag_commit(void) |
418 | { | |
419 | const char *specs[] = { "refs/tags/tag-commit:refs/tags/tag-commit" }; | |
420 | push_status exp_stats[] = { { "refs/tags/tag-commit", NULL } }; | |
421 | expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } }; | |
422 | do_push(specs, ARRAY_SIZE(specs), | |
423 | exp_stats, ARRAY_SIZE(exp_stats), | |
424 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
425 | } | |
426 | ||
427 | void test_online_push__tag_tree(void) | |
428 | { | |
429 | const char *specs[] = { "refs/tags/tag-tree:refs/tags/tag-tree" }; | |
430 | push_status exp_stats[] = { { "refs/tags/tag-tree", NULL } }; | |
431 | expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } }; | |
432 | do_push(specs, ARRAY_SIZE(specs), | |
433 | exp_stats, ARRAY_SIZE(exp_stats), | |
434 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
435 | } | |
436 | ||
437 | void test_online_push__tag_blob(void) | |
438 | { | |
439 | const char *specs[] = { "refs/tags/tag-blob:refs/tags/tag-blob" }; | |
440 | push_status exp_stats[] = { { "refs/tags/tag-blob", NULL } }; | |
441 | expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } }; | |
442 | do_push(specs, ARRAY_SIZE(specs), | |
443 | exp_stats, ARRAY_SIZE(exp_stats), | |
444 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
445 | } | |
446 | ||
447 | void test_online_push__tag_lightweight(void) | |
448 | { | |
449 | const char *specs[] = { "refs/tags/tag-lightweight:refs/tags/tag-lightweight" }; | |
450 | push_status exp_stats[] = { { "refs/tags/tag-lightweight", NULL } }; | |
451 | expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } }; | |
452 | do_push(specs, ARRAY_SIZE(specs), | |
453 | exp_stats, ARRAY_SIZE(exp_stats), | |
454 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
455 | } | |
456 | ||
6443eaf2 | 457 | void test_online_push__force(void) |
613d5eb9 PK |
458 | { |
459 | const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"}; | |
460 | push_status exp_stats1[] = { { "refs/heads/tgt", NULL } }; | |
461 | expected_ref exp_refs1[] = { { "refs/heads/tgt", &_oid_b3 } }; | |
462 | ||
463 | const char *specs2[] = {"refs/heads/b4:refs/heads/tgt"}; | |
464 | ||
465 | const char *specs2_force[] = {"+refs/heads/b4:refs/heads/tgt"}; | |
466 | push_status exp_stats2_force[] = { { "refs/heads/tgt", NULL } }; | |
467 | expected_ref exp_refs2_force[] = { { "refs/heads/tgt", &_oid_b4 } }; | |
468 | ||
469 | do_push(specs1, ARRAY_SIZE(specs1), | |
470 | exp_stats1, ARRAY_SIZE(exp_stats1), | |
471 | exp_refs1, ARRAY_SIZE(exp_refs1), 0); | |
472 | ||
473 | do_push(specs2, ARRAY_SIZE(specs2), | |
474 | NULL, 0, | |
475 | exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD); | |
476 | ||
477 | /* Non-fast-forward update with force should pass. */ | |
478 | do_push(specs2_force, ARRAY_SIZE(specs2_force), | |
479 | exp_stats2_force, ARRAY_SIZE(exp_stats2_force), | |
480 | exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0); | |
481 | } | |
482 | ||
6443eaf2 | 483 | void test_online_push__delete(void) |
613d5eb9 PK |
484 | { |
485 | const char *specs1[] = { | |
486 | "refs/heads/b1:refs/heads/tgt1", | |
487 | "refs/heads/b1:refs/heads/tgt2" | |
488 | }; | |
489 | push_status exp_stats1[] = { | |
490 | { "refs/heads/tgt1", NULL }, | |
491 | { "refs/heads/tgt2", NULL } | |
492 | }; | |
493 | expected_ref exp_refs1[] = { | |
494 | { "refs/heads/tgt1", &_oid_b1 }, | |
495 | { "refs/heads/tgt2", &_oid_b1 } | |
496 | }; | |
497 | ||
498 | const char *specs_del_fake[] = { ":refs/heads/fake" }; | |
499 | /* Force has no effect for delete. */ | |
500 | const char *specs_del_fake_force[] = { "+:refs/heads/fake" }; | |
d73d52df | 501 | push_status exp_stats_fake[] = { { "refs/heads/fake", NULL } }; |
613d5eb9 PK |
502 | |
503 | const char *specs_delete[] = { ":refs/heads/tgt1" }; | |
504 | push_status exp_stats_delete[] = { { "refs/heads/tgt1", NULL } }; | |
505 | expected_ref exp_refs_delete[] = { { "refs/heads/tgt2", &_oid_b1 } }; | |
506 | /* Force has no effect for delete. */ | |
507 | const char *specs_delete_force[] = { "+:refs/heads/tgt1" }; | |
508 | ||
509 | do_push(specs1, ARRAY_SIZE(specs1), | |
510 | exp_stats1, ARRAY_SIZE(exp_stats1), | |
511 | exp_refs1, ARRAY_SIZE(exp_refs1), 0); | |
512 | ||
d73d52df CW |
513 | /* When deleting a non-existent branch, the git client sends zero for both |
514 | * the old and new commit id. This should succeed on the server with the | |
515 | * same status report as if the branch were actually deleted. The server | |
516 | * returns a warning on the side-band iff the side-band is supported. | |
517 | * Since libgit2 doesn't support the side-band yet, there are no warnings. | |
613d5eb9 PK |
518 | */ |
519 | do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake), | |
d73d52df CW |
520 | exp_stats_fake, 1, |
521 | exp_refs1, ARRAY_SIZE(exp_refs1), 0); | |
613d5eb9 | 522 | do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force), |
d73d52df CW |
523 | exp_stats_fake, 1, |
524 | exp_refs1, ARRAY_SIZE(exp_refs1), 0); | |
613d5eb9 PK |
525 | |
526 | /* Delete one of the pushed branches. */ | |
527 | do_push(specs_delete, ARRAY_SIZE(specs_delete), | |
528 | exp_stats_delete, ARRAY_SIZE(exp_stats_delete), | |
529 | exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0); | |
530 | ||
531 | /* Re-push branches and retry delete with force. */ | |
532 | do_push(specs1, ARRAY_SIZE(specs1), | |
533 | exp_stats1, ARRAY_SIZE(exp_stats1), | |
534 | exp_refs1, ARRAY_SIZE(exp_refs1), 0); | |
535 | do_push(specs_delete_force, ARRAY_SIZE(specs_delete_force), | |
536 | exp_stats_delete, ARRAY_SIZE(exp_stats_delete), | |
537 | exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0); | |
538 | } | |
539 | ||
6443eaf2 | 540 | void test_online_push__bad_refspecs(void) |
613d5eb9 PK |
541 | { |
542 | /* All classes of refspecs that should be rejected by | |
543 | * git_push_add_refspec() should go in this test. | |
544 | */ | |
545 | git_push *push; | |
546 | ||
547 | if (_remote) { | |
b412d563 | 548 | // cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); |
613d5eb9 PK |
549 | cl_git_pass(git_push_new(&push, _remote)); |
550 | ||
551 | /* Unexpanded branch names not supported */ | |
552 | cl_git_fail(git_push_add_refspec(push, "b6:b6")); | |
553 | ||
554 | git_push_free(push); | |
555 | } | |
556 | } | |
557 | ||
6443eaf2 | 558 | void test_online_push__expressions(void) |
613d5eb9 PK |
559 | { |
560 | /* TODO: Expressions in refspecs doesn't actually work yet */ | |
561 | const char *specs_left_expr[] = { "refs/heads/b2~1:refs/heads/b2" }; | |
562 | ||
563 | const char *specs_right_expr[] = { "refs/heads/b2:refs/heads/b2~1" }; | |
564 | push_status exp_stats_right_expr[] = { { "refs/heads/b2~1", "funny refname" } }; | |
565 | ||
566 | /* TODO: Find a more precise way of checking errors than a exit code of -1. */ | |
567 | do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr), | |
568 | NULL, 0, | |
569 | NULL, 0, -1); | |
570 | ||
571 | do_push(specs_right_expr, ARRAY_SIZE(specs_right_expr), | |
572 | exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr), | |
573 | NULL, 0, 0); | |
574 | } | |
087f64d3 | 575 | |
abeefbbe | 576 | void test_online_push__notes(void) |
087f64d3 JM |
577 | { |
578 | git_oid note_oid, *target_oid, expected_oid; | |
579 | git_signature *signature; | |
580 | const char *specs[] = { "refs/notes/commits:refs/notes/commits" }; | |
581 | push_status exp_stats[] = { { "refs/notes/commits", NULL } }; | |
582 | expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } }; | |
583 | git_oid_fromstr(&expected_oid, "8461a99b27b7043e58ff6e1f5d2cf07d282534fb"); | |
584 | ||
585 | target_oid = &_oid_b6; | |
586 | ||
587 | /* Create note to push */ | |
588 | cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ | |
abeefbbe | 589 | cl_git_pass(git_note_create(¬e_oid, _repo, signature, signature, NULL, target_oid, "hello world\n", 0)); |
087f64d3 JM |
590 | |
591 | do_push(specs, ARRAY_SIZE(specs), | |
592 | exp_stats, ARRAY_SIZE(exp_stats), | |
593 | exp_refs, ARRAY_SIZE(exp_refs), 0); | |
594 | ||
595 | git_signature_free(signature); | |
596 | } |