]>
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" | |
1d645aab JM |
7 | #include "refspec.h" |
8 | #include "remote.h" | |
613d5eb9 | 9 | |
613d5eb9 PK |
10 | static git_repository *_repo; |
11 | ||
84efffc3 ET |
12 | static char *_remote_url; |
13 | ||
5be622fb CMN |
14 | static char *_remote_ssh_key; |
15 | static char *_remote_ssh_pubkey; | |
16 | static char *_remote_ssh_passphrase; | |
17 | ||
613d5eb9 PK |
18 | static char *_remote_user; |
19 | static char *_remote_pass; | |
20 | ||
84efffc3 ET |
21 | static char *_remote_default; |
22 | ||
e3c131c5 CMN |
23 | static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *); |
24 | ||
613d5eb9 PK |
25 | static git_remote *_remote; |
26 | static record_callbacks_data _record_cbs_data = {{ 0 }}; | |
27 | static git_remote_callbacks _record_cbs = RECORD_CALLBACKS_INIT(&_record_cbs_data); | |
28 | ||
29 | static git_oid _oid_b6; | |
30 | static git_oid _oid_b5; | |
31 | static git_oid _oid_b4; | |
32 | static git_oid _oid_b3; | |
33 | static git_oid _oid_b2; | |
34 | static git_oid _oid_b1; | |
35 | ||
abeefbbe MS |
36 | static git_oid _tag_commit; |
37 | static git_oid _tag_tree; | |
38 | static git_oid _tag_blob; | |
39 | static git_oid _tag_lightweight; | |
1c13b0bf | 40 | static git_oid _tag_tag; |
abeefbbe | 41 | |
7602cb7c | 42 | static int cred_acquire_cb( |
2648dc1a ET |
43 | git_cred **cred, |
44 | const char *url, | |
45 | const char *user_from_url, | |
46 | unsigned int allowed_types, | |
47 | void *payload) | |
613d5eb9 PK |
48 | { |
49 | GIT_UNUSED(url); | |
7602cb7c | 50 | GIT_UNUSED(user_from_url); |
2648dc1a | 51 | GIT_UNUSED(payload); |
613d5eb9 | 52 | |
e26b08d3 CMN |
53 | if (GIT_CREDTYPE_USERNAME & allowed_types) { |
54 | if (!_remote_user) { | |
55 | printf("GITTEST_REMOTE_USER must be set\n"); | |
56 | return -1; | |
57 | } | |
58 | ||
59 | return git_cred_username_new(cred, _remote_user); | |
60 | } | |
61 | ||
84efffc3 ET |
62 | if (GIT_CREDTYPE_DEFAULT & allowed_types) { |
63 | if (!_remote_default) { | |
64 | printf("GITTEST_REMOTE_DEFAULT must be set to use NTLM/Negotiate credentials\n"); | |
65 | return -1; | |
66 | } | |
67 | ||
68 | return git_cred_default_new(cred); | |
69 | } | |
70 | ||
70a8c78f | 71 | if (GIT_CREDTYPE_SSH_KEY & allowed_types) { |
2648dc1a ET |
72 | if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) { |
73 | printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n"); | |
74 | return -1; | |
75 | } | |
84efffc3 | 76 | |
70a8c78f | 77 | return git_cred_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); |
2648dc1a | 78 | } |
5be622fb | 79 | |
2648dc1a ET |
80 | if (GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) { |
81 | if (!_remote_user || !_remote_pass) { | |
82 | printf("GITTEST_REMOTE_USER and GITTEST_REMOTE_PASS must be set\n"); | |
83 | return -1; | |
84 | } | |
613d5eb9 | 85 | |
2648dc1a ET |
86 | return git_cred_userpass_plaintext_new(cred, _remote_user, _remote_pass); |
87 | } | |
88 | ||
89 | return -1; | |
613d5eb9 PK |
90 | } |
91 | ||
9d41984c ET |
92 | /* the results of a push status. when used for expected values, msg may be NULL |
93 | * to indicate that it should not be matched. */ | |
613d5eb9 PK |
94 | typedef struct { |
95 | const char *ref; | |
9d41984c | 96 | int success; |
613d5eb9 PK |
97 | const char *msg; |
98 | } push_status; | |
99 | ||
100 | /** | |
101 | * git_push_status_foreach callback that records status entries. | |
102 | * @param data (git_vector *) of push_status instances | |
103 | */ | |
104 | static int record_push_status_cb(const char *ref, const char *msg, void *data) | |
105 | { | |
106 | git_vector *statuses = (git_vector *)data; | |
107 | push_status *s; | |
108 | ||
109 | cl_assert(s = git__malloc(sizeof(*s))); | |
110 | s->ref = ref; | |
9d41984c | 111 | s->success = (msg == NULL); |
613d5eb9 PK |
112 | s->msg = msg; |
113 | ||
114 | git_vector_insert(statuses, s); | |
115 | ||
116 | return 0; | |
117 | } | |
118 | ||
119 | static void do_verify_push_status(git_push *push, const push_status expected[], const size_t expected_len) | |
120 | { | |
121 | git_vector actual = GIT_VECTOR_INIT; | |
122 | push_status *iter; | |
123 | bool failed = false; | |
124 | size_t i; | |
125 | ||
126 | git_push_status_foreach(push, record_push_status_cb, &actual); | |
127 | ||
128 | if (expected_len != actual.length) | |
129 | failed = true; | |
130 | else | |
131 | git_vector_foreach(&actual, i, iter) | |
132 | if (strcmp(expected[i].ref, iter->ref) || | |
9d41984c ET |
133 | (expected[i].success != iter->success) || |
134 | (expected[i].msg && (!iter->msg || strcmp(expected[i].msg, iter->msg)))) { | |
613d5eb9 PK |
135 | failed = true; |
136 | break; | |
137 | } | |
138 | ||
139 | if (failed) { | |
140 | git_buf msg = GIT_BUF_INIT; | |
141 | ||
142 | git_buf_puts(&msg, "Expected and actual push statuses differ:\nEXPECTED:\n"); | |
143 | ||
144 | for(i = 0; i < expected_len; i++) { | |
145 | git_buf_printf(&msg, "%s: %s\n", | |
146 | expected[i].ref, | |
9d41984c | 147 | expected[i].success ? "success" : "failed"); |
613d5eb9 PK |
148 | } |
149 | ||
150 | git_buf_puts(&msg, "\nACTUAL:\n"); | |
151 | ||
9d41984c ET |
152 | git_vector_foreach(&actual, i, iter) { |
153 | if (iter->success) | |
154 | git_buf_printf(&msg, "%s: success\n", iter->ref); | |
155 | else | |
156 | git_buf_printf(&msg, "%s: failed with message: %s", iter->ref, iter->msg); | |
157 | } | |
613d5eb9 PK |
158 | |
159 | cl_fail(git_buf_cstr(&msg)); | |
160 | ||
161 | git_buf_free(&msg); | |
162 | } | |
163 | ||
164 | git_vector_foreach(&actual, i, iter) | |
165 | git__free(iter); | |
166 | ||
167 | git_vector_free(&actual); | |
168 | } | |
169 | ||
170 | /** | |
171 | * Verifies that after git_push_finish(), refs on a remote have the expected | |
172 | * names, oids, and order. | |
156cfec0 | 173 | * |
613d5eb9 PK |
174 | * @param remote remote to verify |
175 | * @param expected_refs expected remote refs after push | |
176 | * @param expected_refs_len length of expected_refs | |
177 | */ | |
178 | static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) | |
179 | { | |
359dce72 CMN |
180 | const git_remote_head **actual_refs; |
181 | size_t actual_refs_len; | |
613d5eb9 | 182 | |
359dce72 CMN |
183 | git_remote_ls(&actual_refs, &actual_refs_len, remote); |
184 | verify_remote_refs(actual_refs, actual_refs_len, expected_refs, expected_refs_len); | |
613d5eb9 PK |
185 | } |
186 | ||
1d645aab JM |
187 | /** |
188 | * Verifies that after git_push_update_tips(), remote tracking branches have the expected | |
189 | * names and oids. | |
190 | * | |
191 | * @param remote remote to verify | |
192 | * @param expected_refs expected remote refs after push | |
193 | * @param expected_refs_len length of expected_refs | |
194 | */ | |
195 | static void verify_tracking_branches(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) | |
196 | { | |
4330ab26 | 197 | git_refspec *fetch_spec; |
1d645aab JM |
198 | size_t i, j; |
199 | git_buf msg = GIT_BUF_INIT; | |
200 | git_buf ref_name = GIT_BUF_INIT; | |
1d645aab | 201 | git_vector actual_refs = GIT_VECTOR_INIT; |
8ec889a4 | 202 | git_branch_iterator *iter; |
1d645aab JM |
203 | char *actual_ref; |
204 | git_oid oid; | |
8ec889a4 | 205 | int failed = 0, error; |
a667ca82 | 206 | git_branch_t branch_type; |
8ec889a4 | 207 | git_reference *ref; |
1d645aab JM |
208 | |
209 | /* Get current remote branches */ | |
8ec889a4 CMN |
210 | cl_git_pass(git_branch_iterator_new(&iter, remote->repo, GIT_BRANCH_REMOTE)); |
211 | ||
212 | while ((error = git_branch_next(&ref, &branch_type, iter)) == 0) { | |
213 | cl_assert_equal_i(branch_type, GIT_BRANCH_REMOTE); | |
214 | ||
215 | cl_git_pass(git_vector_insert(&actual_refs, git__strdup(git_reference_name(ref)))); | |
f96e7e6c ET |
216 | |
217 | git_reference_free(ref); | |
8ec889a4 CMN |
218 | } |
219 | ||
220 | cl_assert_equal_i(error, GIT_ITEROVER); | |
11bd7a03 | 221 | git_branch_iterator_free(iter); |
1d645aab JM |
222 | |
223 | /* Loop through expected refs, make sure they exist */ | |
224 | for (i = 0; i < expected_refs_len; i++) { | |
225 | ||
226 | /* Convert remote reference name into tracking branch name. | |
227 | * If the spec is not under refs/heads/, then skip. | |
228 | */ | |
4330ab26 CMN |
229 | fetch_spec = git_remote__matching_refspec(remote, expected_refs[i].name); |
230 | if (!fetch_spec) | |
1d645aab JM |
231 | continue; |
232 | ||
bf522e08 | 233 | cl_git_pass(git_refspec_transform(&ref_name, fetch_spec, expected_refs[i].name)); |
1d645aab JM |
234 | |
235 | /* Find matching remote branch */ | |
236 | git_vector_foreach(&actual_refs, j, actual_ref) { | |
8ec889a4 | 237 | if (!strcmp(git_buf_cstr(&ref_name), actual_ref)) |
1d645aab JM |
238 | break; |
239 | } | |
240 | ||
241 | if (j == actual_refs.length) { | |
242 | git_buf_printf(&msg, "Did not find expected tracking branch '%s'.", git_buf_cstr(&ref_name)); | |
243 | failed = 1; | |
244 | goto failed; | |
245 | } | |
246 | ||
247 | /* Make sure tracking branch is at expected commit ID */ | |
8ec889a4 | 248 | cl_git_pass(git_reference_name_to_id(&oid, remote->repo, actual_ref)); |
1d645aab JM |
249 | |
250 | if (git_oid_cmp(expected_refs[i].oid, &oid) != 0) { | |
251 | git_buf_puts(&msg, "Tracking branch commit does not match expected ID."); | |
252 | failed = 1; | |
253 | goto failed; | |
254 | } | |
255 | ||
2ff4469a | 256 | git__free(actual_ref); |
1d645aab JM |
257 | cl_git_pass(git_vector_remove(&actual_refs, j)); |
258 | } | |
259 | ||
260 | /* Make sure there are no extra branches */ | |
261 | if (actual_refs.length > 0) { | |
262 | git_buf_puts(&msg, "Unexpected remote tracking branches exist."); | |
263 | failed = 1; | |
264 | goto failed; | |
265 | } | |
266 | ||
267 | failed: | |
f70cfd34 | 268 | if (failed) |
1d645aab JM |
269 | cl_fail(git_buf_cstr(&msg)); |
270 | ||
271 | git_vector_foreach(&actual_refs, i, actual_ref) | |
272 | git__free(actual_ref); | |
273 | ||
274 | git_vector_free(&actual_refs); | |
275 | git_buf_free(&msg); | |
2ff4469a | 276 | git_buf_free(&ref_name); |
f70cfd34 JG |
277 | } |
278 | ||
279 | static void verify_update_tips_callback(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) | |
280 | { | |
281 | git_refspec *fetch_spec; | |
282 | git_buf msg = GIT_BUF_INIT; | |
283 | git_buf ref_name = GIT_BUF_INIT; | |
284 | updated_tip *tip = NULL; | |
285 | size_t i, j; | |
286 | int failed = 0; | |
287 | ||
288 | for (i = 0; i < expected_refs_len; ++i) { | |
289 | /* Convert remote reference name into tracking branch name. | |
290 | * If the spec is not under refs/heads/, then skip. | |
291 | */ | |
292 | fetch_spec = git_remote__matching_refspec(remote, expected_refs[i].name); | |
293 | if (!fetch_spec) | |
294 | continue; | |
295 | ||
296 | cl_git_pass(git_refspec_transform(&ref_name, fetch_spec, expected_refs[i].name)); | |
297 | ||
298 | /* Find matching update_tip entry */ | |
299 | git_vector_foreach(&_record_cbs_data.updated_tips, j, tip) { | |
300 | if (!strcmp(git_buf_cstr(&ref_name), tip->name)) | |
301 | break; | |
302 | } | |
303 | ||
304 | if (j == _record_cbs_data.updated_tips.length) { | |
305 | git_buf_printf(&msg, "Did not find expected updated tip entry for branch '%s'.", git_buf_cstr(&ref_name)); | |
306 | failed = 1; | |
307 | goto failed; | |
308 | } | |
309 | ||
310 | if (git_oid_cmp(expected_refs[i].oid, tip->new_oid) != 0) { | |
311 | git_buf_printf(&msg, "Updated tip ID does not match expected ID"); | |
312 | failed = 1; | |
313 | goto failed; | |
314 | } | |
315 | } | |
316 | ||
317 | failed: | |
318 | if (failed) | |
319 | cl_fail(git_buf_cstr(&msg)); | |
320 | ||
321 | git_buf_free(&ref_name); | |
322 | git_buf_free(&msg); | |
1d645aab JM |
323 | } |
324 | ||
6443eaf2 | 325 | void test_online_push__initialize(void) |
613d5eb9 PK |
326 | { |
327 | git_vector delete_specs = GIT_VECTOR_INIT; | |
ae297212 CMN |
328 | const git_remote_head **heads; |
329 | size_t i, heads_len; | |
613d5eb9 PK |
330 | char *curr_del_spec; |
331 | ||
332 | _repo = cl_git_sandbox_init("push_src"); | |
333 | ||
334 | cl_fixture_sandbox("testrepo.git"); | |
335 | cl_rename("push_src/submodule/.gitted", "push_src/submodule/.git"); | |
336 | ||
337 | rewrite_gitmodules(git_repository_workdir(_repo)); | |
338 | ||
339 | /* git log --format=oneline --decorate --graph | |
340 | * *-. 951bbbb90e2259a4c8950db78946784fb53fcbce (HEAD, b6) merge b3, b4, and b5 to b6 | |
341 | * |\ \ | |
342 | * | | * fa38b91f199934685819bea316186d8b008c52a2 (b5) added submodule named 'submodule' pointing to '../testrepo.git' | |
343 | * | * | 27b7ce66243eb1403862d05f958c002312df173d (b4) edited fold\b.txt | |
344 | * | |/ | |
345 | * * | d9b63a88223d8367516f50bd131a5f7349b7f3e4 (b3) edited a.txt | |
346 | * |/ | |
347 | * * a78705c3b2725f931d3ee05348d83cc26700f247 (b2, b1) added fold and fold/b.txt | |
348 | * * 5c0bb3d1b9449d1cc69d7519fd05166f01840915 added a.txt | |
349 | */ | |
350 | git_oid_fromstr(&_oid_b6, "951bbbb90e2259a4c8950db78946784fb53fcbce"); | |
351 | git_oid_fromstr(&_oid_b5, "fa38b91f199934685819bea316186d8b008c52a2"); | |
352 | git_oid_fromstr(&_oid_b4, "27b7ce66243eb1403862d05f958c002312df173d"); | |
353 | git_oid_fromstr(&_oid_b3, "d9b63a88223d8367516f50bd131a5f7349b7f3e4"); | |
354 | git_oid_fromstr(&_oid_b2, "a78705c3b2725f931d3ee05348d83cc26700f247"); | |
355 | git_oid_fromstr(&_oid_b1, "a78705c3b2725f931d3ee05348d83cc26700f247"); | |
356 | ||
abeefbbe MS |
357 | git_oid_fromstr(&_tag_commit, "805c54522e614f29f70d2413a0470247d8b424ac"); |
358 | git_oid_fromstr(&_tag_tree, "ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e"); | |
359 | git_oid_fromstr(&_tag_blob, "b483ae7ba66decee9aee971f501221dea84b1498"); | |
360 | git_oid_fromstr(&_tag_lightweight, "951bbbb90e2259a4c8950db78946784fb53fcbce"); | |
1c13b0bf | 361 | git_oid_fromstr(&_tag_tag, "eea4f2705eeec2db3813f2430829afce99cd00b5"); |
abeefbbe | 362 | |
613d5eb9 PK |
363 | /* Remote URL environment variable must be set. User and password are optional. */ |
364 | _remote_url = cl_getenv("GITTEST_REMOTE_URL"); | |
365 | _remote_user = cl_getenv("GITTEST_REMOTE_USER"); | |
366 | _remote_pass = cl_getenv("GITTEST_REMOTE_PASS"); | |
5be622fb CMN |
367 | _remote_ssh_key = cl_getenv("GITTEST_REMOTE_SSH_KEY"); |
368 | _remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY"); | |
369 | _remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE"); | |
84efffc3 | 370 | _remote_default = cl_getenv("GITTEST_REMOTE_DEFAULT"); |
613d5eb9 PK |
371 | _remote = NULL; |
372 | ||
0f65733b VM |
373 | /* Skip the test if we're missing the remote URL */ |
374 | if (!_remote_url) | |
375 | cl_skip(); | |
613d5eb9 | 376 | |
0f65733b | 377 | cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); |
613d5eb9 | 378 | |
0f65733b VM |
379 | record_callbacks_data_clear(&_record_cbs_data); |
380 | git_remote_set_callbacks(_remote, &_record_cbs); | |
613d5eb9 | 381 | |
0f65733b | 382 | cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); |
613d5eb9 | 383 | |
0f65733b VM |
384 | /* Clean up previously pushed branches. Fails if receive.denyDeletes is |
385 | * set on the remote. Also, on Git 1.7.0 and newer, you must run | |
386 | * 'git config receive.denyDeleteCurrent ignore' in the remote repo in | |
387 | * order to delete the remote branch pointed to by HEAD (usually master). | |
388 | * See: https://raw.github.com/git/git/master/Documentation/RelNotes/1.7.0.txt | |
389 | */ | |
390 | cl_git_pass(git_remote_ls(&heads, &heads_len, _remote)); | |
391 | cl_git_pass(create_deletion_refspecs(&delete_specs, heads, heads_len)); | |
392 | if (delete_specs.length) { | |
393 | git_push *push; | |
613d5eb9 | 394 | |
0f65733b | 395 | cl_git_pass(git_push_new(&push, _remote)); |
613d5eb9 | 396 | |
0f65733b VM |
397 | git_vector_foreach(&delete_specs, i, curr_del_spec) { |
398 | git_push_add_refspec(push, curr_del_spec); | |
399 | git__free(curr_del_spec); | |
613d5eb9 PK |
400 | } |
401 | ||
0f65733b VM |
402 | cl_git_pass(git_push_finish(push)); |
403 | git_push_free(push); | |
404 | } | |
405 | ||
406 | git_remote_disconnect(_remote); | |
407 | git_vector_free(&delete_specs); | |
613d5eb9 | 408 | |
0f65733b VM |
409 | /* Now that we've deleted everything, fetch from the remote */ |
410 | cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_FETCH)); | |
3f894205 | 411 | cl_git_pass(git_remote_download(_remote, NULL)); |
0f65733b VM |
412 | cl_git_pass(git_remote_update_tips(_remote, NULL, NULL)); |
413 | git_remote_disconnect(_remote); | |
613d5eb9 PK |
414 | } |
415 | ||
6443eaf2 | 416 | void test_online_push__cleanup(void) |
613d5eb9 PK |
417 | { |
418 | if (_remote) | |
419 | git_remote_free(_remote); | |
c4e3e797 BS |
420 | _remote = NULL; |
421 | ||
422 | /* Freed by cl_git_sandbox_cleanup */ | |
423 | _repo = NULL; | |
613d5eb9 PK |
424 | |
425 | record_callbacks_data_clear(&_record_cbs_data); | |
426 | ||
427 | cl_fixture_cleanup("testrepo.git"); | |
428 | cl_git_sandbox_cleanup(); | |
429 | } | |
430 | ||
11bd7a03 RB |
431 | static int push_pack_progress_cb( |
432 | int stage, unsigned int current, unsigned int total, void* payload) | |
b176eded | 433 | { |
11bd7a03 | 434 | int *calls = (int *)payload; |
7baa7631 | 435 | GIT_UNUSED(stage); GIT_UNUSED(current); GIT_UNUSED(total); |
11bd7a03 RB |
436 | if (*calls < 0) |
437 | return *calls; | |
438 | (*calls)++; | |
5b188225 | 439 | return 0; |
b176eded JM |
440 | } |
441 | ||
11bd7a03 RB |
442 | static int push_transfer_progress_cb( |
443 | unsigned int current, unsigned int total, size_t bytes, void* payload) | |
b176eded | 444 | { |
11bd7a03 | 445 | int *calls = (int *)payload; |
af302aca | 446 | GIT_UNUSED(current); GIT_UNUSED(total); GIT_UNUSED(bytes); |
11bd7a03 RB |
447 | if (*calls < 0) |
448 | return *calls; | |
449 | (*calls)++; | |
5b188225 | 450 | return 0; |
b176eded JM |
451 | } |
452 | ||
613d5eb9 PK |
453 | /** |
454 | * Calls push and relists refs on remote to verify success. | |
156cfec0 | 455 | * |
613d5eb9 PK |
456 | * @param refspecs refspecs to push |
457 | * @param refspecs_len length of refspecs | |
458 | * @param expected_refs expected remote refs after push | |
459 | * @param expected_refs_len length of expected_refs | |
460 | * @param expected_ret expected return value from git_push_finish() | |
b176eded | 461 | * @param check_progress_cb Check that the push progress callbacks are called |
613d5eb9 | 462 | */ |
11bd7a03 RB |
463 | static void do_push( |
464 | const char *refspecs[], size_t refspecs_len, | |
613d5eb9 | 465 | push_status expected_statuses[], size_t expected_statuses_len, |
11bd7a03 | 466 | expected_ref expected_refs[], size_t expected_refs_len, |
f70cfd34 | 467 | int expected_ret, int check_progress_cb, int check_update_tips_cb) |
613d5eb9 PK |
468 | { |
469 | git_push *push; | |
b8b897bb | 470 | git_push_options opts = GIT_PUSH_OPTIONS_INIT; |
613d5eb9 | 471 | size_t i; |
11bd7a03 | 472 | int pack_progress_calls = 0, transfer_progress_calls = 0; |
491cecfe | 473 | git_signature *pusher; |
613d5eb9 PK |
474 | |
475 | if (_remote) { | |
b8b897bb PK |
476 | /* Auto-detect the number of threads to use */ |
477 | opts.pb_parallelism = 0; | |
478 | ||
491cecfe | 479 | cl_git_pass(git_signature_now(&pusher, "Foo Bar", "foo@example.com")); |
613d5eb9 PK |
480 | cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); |
481 | ||
482 | cl_git_pass(git_push_new(&push, _remote)); | |
b8b897bb | 483 | cl_git_pass(git_push_set_options(push, &opts)); |
613d5eb9 | 484 | |
11bd7a03 RB |
485 | if (check_progress_cb) { |
486 | /* if EUSER, then abort in transfer */ | |
487 | if (expected_ret == GIT_EUSER) | |
488 | transfer_progress_calls = GIT_EUSER; | |
489 | ||
490 | cl_git_pass( | |
491 | git_push_set_callbacks( | |
492 | push, push_pack_progress_cb, &pack_progress_calls, | |
493 | push_transfer_progress_cb, &transfer_progress_calls)); | |
494 | } | |
b176eded | 495 | |
613d5eb9 PK |
496 | for (i = 0; i < refspecs_len; i++) |
497 | cl_git_pass(git_push_add_refspec(push, refspecs[i])); | |
498 | ||
499 | if (expected_ret < 0) { | |
11bd7a03 | 500 | cl_git_fail_with(git_push_finish(push), expected_ret); |
613d5eb9 | 501 | cl_assert_equal_i(0, git_push_unpack_ok(push)); |
11bd7a03 RB |
502 | } else { |
503 | cl_git_pass(git_push_finish(push)); | |
613d5eb9 PK |
504 | cl_assert_equal_i(1, git_push_unpack_ok(push)); |
505 | } | |
506 | ||
11bd7a03 RB |
507 | if (check_progress_cb && !expected_ret) { |
508 | cl_assert(pack_progress_calls > 0); | |
509 | cl_assert(transfer_progress_calls > 0); | |
b176eded JM |
510 | } |
511 | ||
613d5eb9 PK |
512 | do_verify_push_status(push, expected_statuses, expected_statuses_len); |
513 | ||
613d5eb9 PK |
514 | verify_refs(_remote, expected_refs, expected_refs_len); |
515 | ||
491cecfe | 516 | cl_git_pass(git_push_update_tips(push, pusher, "test push")); |
1d645aab JM |
517 | verify_tracking_branches(_remote, expected_refs, expected_refs_len); |
518 | ||
f70cfd34 JG |
519 | if (check_update_tips_cb) |
520 | verify_update_tips_callback(_remote, expected_refs, expected_refs_len); | |
521 | ||
1d645aab | 522 | git_push_free(push); |
613d5eb9 PK |
523 | |
524 | git_remote_disconnect(_remote); | |
491cecfe | 525 | git_signature_free(pusher); |
613d5eb9 | 526 | } |
491cecfe | 527 | |
613d5eb9 PK |
528 | } |
529 | ||
530 | /* Call push_finish() without ever calling git_push_add_refspec() */ | |
6443eaf2 | 531 | void test_online_push__noop(void) |
613d5eb9 | 532 | { |
f70cfd34 | 533 | do_push(NULL, 0, NULL, 0, NULL, 0, 0, 0, 1); |
613d5eb9 PK |
534 | } |
535 | ||
6443eaf2 | 536 | void test_online_push__b1(void) |
613d5eb9 PK |
537 | { |
538 | const char *specs[] = { "refs/heads/b1:refs/heads/b1" }; | |
9d41984c | 539 | push_status exp_stats[] = { { "refs/heads/b1", 1 } }; |
613d5eb9 PK |
540 | expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } }; |
541 | do_push(specs, ARRAY_SIZE(specs), | |
542 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 543 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
613d5eb9 PK |
544 | } |
545 | ||
6443eaf2 | 546 | void test_online_push__b2(void) |
613d5eb9 PK |
547 | { |
548 | const char *specs[] = { "refs/heads/b2:refs/heads/b2" }; | |
9d41984c | 549 | push_status exp_stats[] = { { "refs/heads/b2", 1 } }; |
613d5eb9 PK |
550 | expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } }; |
551 | do_push(specs, ARRAY_SIZE(specs), | |
552 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 553 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
613d5eb9 PK |
554 | } |
555 | ||
6443eaf2 | 556 | void test_online_push__b3(void) |
613d5eb9 PK |
557 | { |
558 | const char *specs[] = { "refs/heads/b3:refs/heads/b3" }; | |
9d41984c | 559 | push_status exp_stats[] = { { "refs/heads/b3", 1 } }; |
613d5eb9 PK |
560 | expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } }; |
561 | do_push(specs, ARRAY_SIZE(specs), | |
562 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 563 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
613d5eb9 PK |
564 | } |
565 | ||
6443eaf2 | 566 | void test_online_push__b4(void) |
613d5eb9 PK |
567 | { |
568 | const char *specs[] = { "refs/heads/b4:refs/heads/b4" }; | |
9d41984c | 569 | push_status exp_stats[] = { { "refs/heads/b4", 1 } }; |
613d5eb9 PK |
570 | expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } }; |
571 | do_push(specs, ARRAY_SIZE(specs), | |
572 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 573 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
613d5eb9 PK |
574 | } |
575 | ||
6443eaf2 | 576 | void test_online_push__b5(void) |
613d5eb9 PK |
577 | { |
578 | const char *specs[] = { "refs/heads/b5:refs/heads/b5" }; | |
9d41984c | 579 | push_status exp_stats[] = { { "refs/heads/b5", 1 } }; |
613d5eb9 PK |
580 | expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } }; |
581 | do_push(specs, ARRAY_SIZE(specs), | |
582 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 583 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
613d5eb9 PK |
584 | } |
585 | ||
11bd7a03 RB |
586 | void test_online_push__b5_cancel(void) |
587 | { | |
588 | const char *specs[] = { "refs/heads/b5:refs/heads/b5" }; | |
f70cfd34 | 589 | do_push(specs, ARRAY_SIZE(specs), NULL, 0, NULL, 0, GIT_EUSER, 1, 1); |
11bd7a03 RB |
590 | } |
591 | ||
6443eaf2 | 592 | void test_online_push__multi(void) |
613d5eb9 | 593 | { |
491cecfe BS |
594 | git_reflog *log; |
595 | const git_reflog_entry *entry; | |
596 | ||
613d5eb9 PK |
597 | const char *specs[] = { |
598 | "refs/heads/b1:refs/heads/b1", | |
599 | "refs/heads/b2:refs/heads/b2", | |
600 | "refs/heads/b3:refs/heads/b3", | |
601 | "refs/heads/b4:refs/heads/b4", | |
602 | "refs/heads/b5:refs/heads/b5" | |
603 | }; | |
604 | push_status exp_stats[] = { | |
9d41984c ET |
605 | { "refs/heads/b1", 1 }, |
606 | { "refs/heads/b2", 1 }, | |
607 | { "refs/heads/b3", 1 }, | |
608 | { "refs/heads/b4", 1 }, | |
609 | { "refs/heads/b5", 1 } | |
613d5eb9 PK |
610 | }; |
611 | expected_ref exp_refs[] = { | |
612 | { "refs/heads/b1", &_oid_b1 }, | |
613 | { "refs/heads/b2", &_oid_b2 }, | |
614 | { "refs/heads/b3", &_oid_b3 }, | |
615 | { "refs/heads/b4", &_oid_b4 }, | |
616 | { "refs/heads/b5", &_oid_b5 } | |
617 | }; | |
618 | do_push(specs, ARRAY_SIZE(specs), | |
619 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 620 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
491cecfe BS |
621 | |
622 | cl_git_pass(git_reflog_read(&log, _repo, "refs/remotes/test/b1")); | |
623 | entry = git_reflog_entry_byindex(log, 0); | |
3094102f BS |
624 | if (entry) { |
625 | cl_assert_equal_s("test push", git_reflog_entry_message(entry)); | |
626 | cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email); | |
627 | } | |
491cecfe BS |
628 | |
629 | git_reflog_free(log); | |
613d5eb9 PK |
630 | } |
631 | ||
6443eaf2 | 632 | void test_online_push__implicit_tgt(void) |
613d5eb9 PK |
633 | { |
634 | const char *specs1[] = { "refs/heads/b1:" }; | |
9d41984c | 635 | push_status exp_stats1[] = { { "refs/heads/b1", 1 } }; |
613d5eb9 PK |
636 | expected_ref exp_refs1[] = { { "refs/heads/b1", &_oid_b1 } }; |
637 | ||
638 | const char *specs2[] = { "refs/heads/b2:" }; | |
9d41984c | 639 | push_status exp_stats2[] = { { "refs/heads/b2", 1 } }; |
613d5eb9 PK |
640 | expected_ref exp_refs2[] = { |
641 | { "refs/heads/b1", &_oid_b1 }, | |
642 | { "refs/heads/b2", &_oid_b2 } | |
643 | }; | |
644 | ||
645 | do_push(specs1, ARRAY_SIZE(specs1), | |
646 | exp_stats1, ARRAY_SIZE(exp_stats1), | |
f70cfd34 | 647 | exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1, 1); |
613d5eb9 PK |
648 | do_push(specs2, ARRAY_SIZE(specs2), |
649 | exp_stats2, ARRAY_SIZE(exp_stats2), | |
f70cfd34 | 650 | exp_refs2, ARRAY_SIZE(exp_refs2), 0, 0, 0); |
613d5eb9 PK |
651 | } |
652 | ||
6443eaf2 | 653 | void test_online_push__fast_fwd(void) |
613d5eb9 PK |
654 | { |
655 | /* Fast forward b1 in tgt from _oid_b1 to _oid_b6. */ | |
656 | ||
657 | const char *specs_init[] = { "refs/heads/b1:refs/heads/b1" }; | |
9d41984c | 658 | push_status exp_stats_init[] = { { "refs/heads/b1", 1 } }; |
613d5eb9 PK |
659 | expected_ref exp_refs_init[] = { { "refs/heads/b1", &_oid_b1 } }; |
660 | ||
661 | const char *specs_ff[] = { "refs/heads/b6:refs/heads/b1" }; | |
9d41984c | 662 | push_status exp_stats_ff[] = { { "refs/heads/b1", 1 } }; |
613d5eb9 PK |
663 | expected_ref exp_refs_ff[] = { { "refs/heads/b1", &_oid_b6 } }; |
664 | ||
665 | /* Do a force push to reset b1 in target back to _oid_b1 */ | |
666 | const char *specs_reset[] = { "+refs/heads/b1:refs/heads/b1" }; | |
667 | /* Force should have no effect on a fast forward push */ | |
668 | const char *specs_ff_force[] = { "+refs/heads/b6:refs/heads/b1" }; | |
669 | ||
670 | do_push(specs_init, ARRAY_SIZE(specs_init), | |
671 | exp_stats_init, ARRAY_SIZE(exp_stats_init), | |
f70cfd34 | 672 | exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 1, 1); |
613d5eb9 PK |
673 | |
674 | do_push(specs_ff, ARRAY_SIZE(specs_ff), | |
675 | exp_stats_ff, ARRAY_SIZE(exp_stats_ff), | |
f70cfd34 | 676 | exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0, 0); |
613d5eb9 PK |
677 | |
678 | do_push(specs_reset, ARRAY_SIZE(specs_reset), | |
679 | exp_stats_init, ARRAY_SIZE(exp_stats_init), | |
f70cfd34 | 680 | exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 0, 0); |
613d5eb9 PK |
681 | |
682 | do_push(specs_ff_force, ARRAY_SIZE(specs_ff_force), | |
683 | exp_stats_ff, ARRAY_SIZE(exp_stats_ff), | |
f70cfd34 | 684 | exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0, 0); |
613d5eb9 PK |
685 | } |
686 | ||
abeefbbe MS |
687 | void test_online_push__tag_commit(void) |
688 | { | |
689 | const char *specs[] = { "refs/tags/tag-commit:refs/tags/tag-commit" }; | |
9d41984c | 690 | push_status exp_stats[] = { { "refs/tags/tag-commit", 1 } }; |
abeefbbe MS |
691 | expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } }; |
692 | do_push(specs, ARRAY_SIZE(specs), | |
693 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 694 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
abeefbbe MS |
695 | } |
696 | ||
697 | void test_online_push__tag_tree(void) | |
698 | { | |
699 | const char *specs[] = { "refs/tags/tag-tree:refs/tags/tag-tree" }; | |
9d41984c | 700 | push_status exp_stats[] = { { "refs/tags/tag-tree", 1 } }; |
abeefbbe MS |
701 | expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } }; |
702 | do_push(specs, ARRAY_SIZE(specs), | |
703 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 704 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
abeefbbe MS |
705 | } |
706 | ||
707 | void test_online_push__tag_blob(void) | |
708 | { | |
709 | const char *specs[] = { "refs/tags/tag-blob:refs/tags/tag-blob" }; | |
9d41984c | 710 | push_status exp_stats[] = { { "refs/tags/tag-blob", 1 } }; |
abeefbbe MS |
711 | expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } }; |
712 | do_push(specs, ARRAY_SIZE(specs), | |
713 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 714 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
abeefbbe MS |
715 | } |
716 | ||
717 | void test_online_push__tag_lightweight(void) | |
718 | { | |
719 | const char *specs[] = { "refs/tags/tag-lightweight:refs/tags/tag-lightweight" }; | |
9d41984c | 720 | push_status exp_stats[] = { { "refs/tags/tag-lightweight", 1 } }; |
abeefbbe MS |
721 | expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } }; |
722 | do_push(specs, ARRAY_SIZE(specs), | |
723 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 724 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
abeefbbe MS |
725 | } |
726 | ||
1c13b0bf ET |
727 | void test_online_push__tag_to_tag(void) |
728 | { | |
729 | const char *specs[] = { "refs/tags/tag-tag:refs/tags/tag-tag" }; | |
9d41984c | 730 | push_status exp_stats[] = { { "refs/tags/tag-tag", 1 } }; |
1c13b0bf ET |
731 | expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } }; |
732 | do_push(specs, ARRAY_SIZE(specs), | |
733 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 734 | exp_refs, ARRAY_SIZE(exp_refs), 0, 0, 0); |
1c13b0bf ET |
735 | } |
736 | ||
6443eaf2 | 737 | void test_online_push__force(void) |
613d5eb9 PK |
738 | { |
739 | const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"}; | |
9d41984c | 740 | push_status exp_stats1[] = { { "refs/heads/tgt", 1 } }; |
613d5eb9 PK |
741 | expected_ref exp_refs1[] = { { "refs/heads/tgt", &_oid_b3 } }; |
742 | ||
743 | const char *specs2[] = {"refs/heads/b4:refs/heads/tgt"}; | |
744 | ||
745 | const char *specs2_force[] = {"+refs/heads/b4:refs/heads/tgt"}; | |
9d41984c | 746 | push_status exp_stats2_force[] = { { "refs/heads/tgt", 1 } }; |
613d5eb9 PK |
747 | expected_ref exp_refs2_force[] = { { "refs/heads/tgt", &_oid_b4 } }; |
748 | ||
749 | do_push(specs1, ARRAY_SIZE(specs1), | |
750 | exp_stats1, ARRAY_SIZE(exp_stats1), | |
f70cfd34 | 751 | exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1, 1); |
613d5eb9 PK |
752 | |
753 | do_push(specs2, ARRAY_SIZE(specs2), | |
754 | NULL, 0, | |
f70cfd34 | 755 | exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD, 0, 0); |
613d5eb9 PK |
756 | |
757 | /* Non-fast-forward update with force should pass. */ | |
f70cfd34 | 758 | record_callbacks_data_clear(&_record_cbs_data); |
613d5eb9 PK |
759 | do_push(specs2_force, ARRAY_SIZE(specs2_force), |
760 | exp_stats2_force, ARRAY_SIZE(exp_stats2_force), | |
f70cfd34 | 761 | exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0, 1, 1); |
613d5eb9 PK |
762 | } |
763 | ||
6443eaf2 | 764 | void test_online_push__delete(void) |
613d5eb9 PK |
765 | { |
766 | const char *specs1[] = { | |
767 | "refs/heads/b1:refs/heads/tgt1", | |
768 | "refs/heads/b1:refs/heads/tgt2" | |
769 | }; | |
770 | push_status exp_stats1[] = { | |
9d41984c ET |
771 | { "refs/heads/tgt1", 1 }, |
772 | { "refs/heads/tgt2", 1 } | |
613d5eb9 PK |
773 | }; |
774 | expected_ref exp_refs1[] = { | |
775 | { "refs/heads/tgt1", &_oid_b1 }, | |
776 | { "refs/heads/tgt2", &_oid_b1 } | |
777 | }; | |
778 | ||
779 | const char *specs_del_fake[] = { ":refs/heads/fake" }; | |
780 | /* Force has no effect for delete. */ | |
781 | const char *specs_del_fake_force[] = { "+:refs/heads/fake" }; | |
9d41984c | 782 | push_status exp_stats_fake[] = { { "refs/heads/fake", 1 } }; |
613d5eb9 PK |
783 | |
784 | const char *specs_delete[] = { ":refs/heads/tgt1" }; | |
9d41984c | 785 | push_status exp_stats_delete[] = { { "refs/heads/tgt1", 1 } }; |
613d5eb9 PK |
786 | expected_ref exp_refs_delete[] = { { "refs/heads/tgt2", &_oid_b1 } }; |
787 | /* Force has no effect for delete. */ | |
788 | const char *specs_delete_force[] = { "+:refs/heads/tgt1" }; | |
789 | ||
790 | do_push(specs1, ARRAY_SIZE(specs1), | |
791 | exp_stats1, ARRAY_SIZE(exp_stats1), | |
f70cfd34 | 792 | exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1, 1); |
613d5eb9 | 793 | |
d73d52df CW |
794 | /* When deleting a non-existent branch, the git client sends zero for both |
795 | * the old and new commit id. This should succeed on the server with the | |
796 | * same status report as if the branch were actually deleted. The server | |
797 | * returns a warning on the side-band iff the side-band is supported. | |
798 | * Since libgit2 doesn't support the side-band yet, there are no warnings. | |
613d5eb9 PK |
799 | */ |
800 | do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake), | |
d73d52df | 801 | exp_stats_fake, 1, |
f70cfd34 | 802 | exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0, 0); |
613d5eb9 | 803 | do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force), |
d73d52df | 804 | exp_stats_fake, 1, |
f70cfd34 | 805 | exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0, 0); |
613d5eb9 PK |
806 | |
807 | /* Delete one of the pushed branches. */ | |
808 | do_push(specs_delete, ARRAY_SIZE(specs_delete), | |
809 | exp_stats_delete, ARRAY_SIZE(exp_stats_delete), | |
f70cfd34 | 810 | exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0, 0); |
613d5eb9 PK |
811 | |
812 | /* Re-push branches and retry delete with force. */ | |
813 | do_push(specs1, ARRAY_SIZE(specs1), | |
814 | exp_stats1, ARRAY_SIZE(exp_stats1), | |
f70cfd34 | 815 | exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0, 0); |
613d5eb9 PK |
816 | do_push(specs_delete_force, ARRAY_SIZE(specs_delete_force), |
817 | exp_stats_delete, ARRAY_SIZE(exp_stats_delete), | |
f70cfd34 | 818 | exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0, 0); |
613d5eb9 PK |
819 | } |
820 | ||
6443eaf2 | 821 | void test_online_push__bad_refspecs(void) |
613d5eb9 PK |
822 | { |
823 | /* All classes of refspecs that should be rejected by | |
824 | * git_push_add_refspec() should go in this test. | |
825 | */ | |
826 | git_push *push; | |
827 | ||
828 | if (_remote) { | |
11bd7a03 | 829 | /* cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); */ |
613d5eb9 PK |
830 | cl_git_pass(git_push_new(&push, _remote)); |
831 | ||
832 | /* Unexpanded branch names not supported */ | |
833 | cl_git_fail(git_push_add_refspec(push, "b6:b6")); | |
834 | ||
835 | git_push_free(push); | |
836 | } | |
837 | } | |
838 | ||
6443eaf2 | 839 | void test_online_push__expressions(void) |
613d5eb9 PK |
840 | { |
841 | /* TODO: Expressions in refspecs doesn't actually work yet */ | |
842 | const char *specs_left_expr[] = { "refs/heads/b2~1:refs/heads/b2" }; | |
843 | ||
9d41984c ET |
844 | /* expect not NULL to indicate failure (core git replies "funny refname", |
845 | * other servers may be less pithy. */ | |
613d5eb9 | 846 | const char *specs_right_expr[] = { "refs/heads/b2:refs/heads/b2~1" }; |
9d41984c | 847 | push_status exp_stats_right_expr[] = { { "refs/heads/b2~1", 0 } }; |
613d5eb9 PK |
848 | |
849 | /* TODO: Find a more precise way of checking errors than a exit code of -1. */ | |
850 | do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr), | |
851 | NULL, 0, | |
f70cfd34 | 852 | NULL, 0, -1, 0, 0); |
613d5eb9 PK |
853 | |
854 | do_push(specs_right_expr, ARRAY_SIZE(specs_right_expr), | |
855 | exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr), | |
f70cfd34 | 856 | NULL, 0, 0, 1, 1); |
613d5eb9 | 857 | } |
087f64d3 | 858 | |
abeefbbe | 859 | void test_online_push__notes(void) |
087f64d3 JM |
860 | { |
861 | git_oid note_oid, *target_oid, expected_oid; | |
862 | git_signature *signature; | |
863 | const char *specs[] = { "refs/notes/commits:refs/notes/commits" }; | |
9d41984c | 864 | push_status exp_stats[] = { { "refs/notes/commits", 1 } }; |
087f64d3 | 865 | expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } }; |
0f29e967 | 866 | const char *specs_del[] = { ":refs/notes/commits" }; |
0f29e967 | 867 | |
087f64d3 JM |
868 | git_oid_fromstr(&expected_oid, "8461a99b27b7043e58ff6e1f5d2cf07d282534fb"); |
869 | ||
870 | target_oid = &_oid_b6; | |
871 | ||
872 | /* Create note to push */ | |
873 | cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ | |
abeefbbe | 874 | cl_git_pass(git_note_create(¬e_oid, _repo, signature, signature, NULL, target_oid, "hello world\n", 0)); |
087f64d3 JM |
875 | |
876 | do_push(specs, ARRAY_SIZE(specs), | |
877 | exp_stats, ARRAY_SIZE(exp_stats), | |
f70cfd34 | 878 | exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1); |
087f64d3 | 879 | |
0f29e967 ET |
880 | /* And make sure to delete the note */ |
881 | ||
882 | do_push(specs_del, ARRAY_SIZE(specs_del), | |
883 | exp_stats, 1, | |
aff70018 | 884 | NULL, 0, 0, 0, 0); |
0f29e967 | 885 | |
087f64d3 JM |
886 | git_signature_free(signature); |
887 | } |