]>
Commit | Line | Data |
---|---|---|
eae0bfdc PP |
1 | #include "clar_libgit2.h" |
2 | ||
22a2d3d5 | 3 | #include "futils.h" |
eae0bfdc PP |
4 | #include "git2/reflog.h" |
5 | #include "reflog.h" | |
6 | #include "refs.h" | |
7 | #include "reflog_helpers.h" | |
8 | ||
9 | static const char *g_email = "foo@example.com"; | |
10 | static git_repository *g_repo; | |
11 | ||
12 | /* Fixture setup and teardown */ | |
13 | void test_refs_reflog_messages__initialize(void) | |
14 | { | |
15 | g_repo = cl_git_sandbox_init("testrepo.git"); | |
16 | cl_git_pass(git_repository_set_ident(g_repo, "Foo Bar", g_email)); | |
17 | } | |
18 | ||
19 | void test_refs_reflog_messages__cleanup(void) | |
20 | { | |
21 | cl_git_sandbox_cleanup(); | |
22 | } | |
23 | ||
24 | void test_refs_reflog_messages__setting_head_updates_reflog(void) | |
25 | { | |
26 | git_object *tag; | |
eae0bfdc PP |
27 | git_annotated_commit *annotated; |
28 | ||
eae0bfdc PP |
29 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); /* 4 */ |
30 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/unborn")); | |
31 | cl_git_pass(git_revparse_single(&tag, g_repo, "tags/test")); | |
32 | cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(tag))); /* 3 */ | |
33 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); /* 2 */ | |
34 | cl_git_pass(git_repository_set_head(g_repo, "refs/tags/test")); /* 1 */ | |
35 | cl_git_pass(git_repository_set_head(g_repo, "refs/remotes/test/master")); /* 0 */ | |
36 | ||
37 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 4, | |
38 | NULL, "refs/heads/haacked", | |
39 | "foo@example.com", | |
40 | "checkout: moving from master to haacked"); | |
41 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 3, | |
42 | NULL, "tags/test^{commit}", | |
43 | "foo@example.com", | |
44 | "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d"); | |
45 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 2, | |
46 | "tags/test^{commit}", "refs/heads/haacked", | |
47 | "foo@example.com", | |
48 | "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked"); | |
49 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 1, | |
50 | "refs/heads/haacked", "tags/test^{commit}", | |
51 | "foo@example.com", | |
52 | "checkout: moving from haacked to test"); | |
53 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
54 | "tags/test^{commit}", "refs/remotes/test/master", | |
55 | "foo@example.com", | |
56 | "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to test/master"); | |
57 | ||
58 | cl_git_pass(git_annotated_commit_from_revspec(&annotated, g_repo, "haacked~0")); | |
59 | cl_git_pass(git_repository_set_head_detached_from_annotated(g_repo, annotated)); | |
60 | ||
61 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
62 | NULL, "refs/heads/haacked", | |
63 | "foo@example.com", | |
64 | "checkout: moving from be3563ae3f795b2b4353bcce3a527ad0a4f7f644 to haacked~0"); | |
65 | ||
66 | git_annotated_commit_free(annotated); | |
67 | git_object_free(tag); | |
eae0bfdc PP |
68 | } |
69 | ||
70 | void test_refs_reflog_messages__setting_head_to_same_target_ignores_reflog(void) | |
71 | { | |
72 | size_t nentries, nentries_after; | |
73 | ||
74 | nentries = reflog_entrycount(g_repo, GIT_HEAD_FILE); | |
75 | ||
76 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); | |
77 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); | |
78 | ||
79 | nentries_after = reflog_entrycount(g_repo, GIT_HEAD_FILE); | |
80 | ||
81 | cl_assert_equal_i(nentries + 1, nentries_after); | |
82 | } | |
83 | ||
84 | void test_refs_reflog_messages__detaching_writes_reflog(void) | |
85 | { | |
eae0bfdc PP |
86 | git_oid id; |
87 | const char *msg; | |
88 | ||
eae0bfdc PP |
89 | msg = "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d"; |
90 | git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d"); | |
91 | cl_git_pass(git_repository_set_head_detached(g_repo, &id)); | |
92 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
93 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
94 | "e90810b8df3e80c413d903f631643c716887138d", | |
95 | NULL, msg); | |
96 | ||
97 | msg = "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked"; | |
98 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); | |
99 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
100 | "e90810b8df3e80c413d903f631643c716887138d", | |
101 | "258f0e2a959a364e40ed6603d5d44fbb24765b10", | |
102 | NULL, msg); | |
eae0bfdc PP |
103 | } |
104 | ||
105 | void test_refs_reflog_messages__orphan_branch_does_not_count(void) | |
106 | { | |
107 | git_oid id; | |
108 | const char *msg; | |
109 | ||
110 | /* Have something known */ | |
111 | msg = "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d"; | |
112 | git_oid_fromstr(&id, "e90810b8df3e80c413d903f631643c716887138d"); | |
113 | cl_git_pass(git_repository_set_head_detached(g_repo, &id)); | |
114 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
115 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
116 | "e90810b8df3e80c413d903f631643c716887138d", | |
117 | NULL, msg); | |
118 | ||
119 | /* Switching to an orphan branch does not write to the reflog */ | |
120 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/orphan")); | |
121 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
122 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
123 | "e90810b8df3e80c413d903f631643c716887138d", | |
124 | NULL, msg); | |
125 | ||
126 | /* And coming back, we set the source to zero */ | |
127 | msg = "checkout: moving from orphan to haacked"; | |
128 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/haacked")); | |
129 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
130 | "0000000000000000000000000000000000000000", | |
131 | "258f0e2a959a364e40ed6603d5d44fbb24765b10", | |
132 | NULL, msg); | |
133 | } | |
134 | ||
135 | void test_refs_reflog_messages__branch_birth(void) | |
136 | { | |
137 | git_signature *sig; | |
138 | git_oid id; | |
139 | git_tree *tree; | |
140 | git_reference *ref; | |
141 | const char *msg; | |
142 | size_t nentries, nentries_after; | |
143 | ||
144 | nentries = reflog_entrycount(g_repo, GIT_HEAD_FILE); | |
145 | ||
146 | cl_git_pass(git_signature_now(&sig, "me", "foo@example.com")); | |
147 | ||
148 | cl_git_pass(git_repository_head(&ref, g_repo)); | |
ac3d33df | 149 | cl_git_pass(git_reference_peel((git_object **) &tree, ref, GIT_OBJECT_TREE)); |
eae0bfdc PP |
150 | |
151 | cl_git_pass(git_repository_set_head(g_repo, "refs/heads/orphan")); | |
152 | ||
153 | nentries_after = reflog_entrycount(g_repo, GIT_HEAD_FILE); | |
154 | ||
155 | cl_assert_equal_i(nentries, nentries_after); | |
156 | ||
157 | msg = "message 2"; | |
158 | cl_git_pass(git_commit_create(&id, g_repo, "HEAD", sig, sig, NULL, msg, tree, 0, NULL)); | |
159 | ||
160 | cl_assert_equal_i(1, reflog_entrycount(g_repo, "refs/heads/orphan")); | |
161 | ||
162 | nentries_after = reflog_entrycount(g_repo, GIT_HEAD_FILE); | |
163 | ||
164 | cl_assert_equal_i(nentries + 1, nentries_after); | |
165 | ||
166 | git_signature_free(sig); | |
167 | git_tree_free(tree); | |
168 | git_reference_free(ref); | |
169 | } | |
170 | ||
171 | void test_refs_reflog_messages__commit_on_symbolic_ref_updates_head_reflog(void) | |
172 | { | |
173 | git_signature *sig; | |
174 | git_oid id; | |
175 | git_tree *tree; | |
176 | git_reference *ref1, *ref2; | |
177 | const char *msg; | |
178 | size_t nentries_head, nentries_master; | |
179 | ||
180 | nentries_head = reflog_entrycount(g_repo, GIT_HEAD_FILE); | |
181 | ||
182 | cl_git_pass(git_signature_now(&sig, "me", "foo@example.com")); | |
183 | ||
184 | cl_git_pass(git_repository_head(&ref1, g_repo)); | |
ac3d33df | 185 | cl_git_pass(git_reference_peel((git_object **) &tree, ref1, GIT_OBJECT_TREE)); |
eae0bfdc PP |
186 | |
187 | nentries_master = reflog_entrycount(g_repo, "refs/heads/master"); | |
188 | ||
189 | msg = "message 1"; | |
190 | cl_git_pass(git_reference_symbolic_create(&ref2, g_repo, "refs/heads/master", "refs/heads/foo", 1, msg)); | |
191 | ||
192 | cl_assert_equal_i(0, reflog_entrycount(g_repo, "refs/heads/foo")); | |
193 | cl_assert_equal_i(nentries_head, reflog_entrycount(g_repo, GIT_HEAD_FILE)); | |
194 | cl_assert_equal_i(nentries_master, reflog_entrycount(g_repo, "refs/heads/master")); | |
195 | ||
196 | msg = "message 2"; | |
197 | cl_git_pass(git_commit_create(&id, g_repo, "HEAD", sig, sig, NULL, msg, tree, 0, NULL)); | |
198 | ||
199 | cl_assert_equal_i(1, reflog_entrycount(g_repo, "refs/heads/foo")); | |
200 | cl_assert_equal_i(nentries_head + 1, reflog_entrycount(g_repo, GIT_HEAD_FILE)); | |
201 | cl_assert_equal_i(nentries_master, reflog_entrycount(g_repo, "refs/heads/master")); | |
202 | ||
203 | git_signature_free(sig); | |
204 | git_reference_free(ref1); | |
205 | git_reference_free(ref2); | |
206 | git_tree_free(tree); | |
207 | } | |
208 | ||
209 | void test_refs_reflog_messages__show_merge_for_merge_commits(void) | |
210 | { | |
211 | git_oid b1_oid; | |
212 | git_oid b2_oid; | |
213 | git_oid merge_commit_oid; | |
214 | git_commit *b1_commit; | |
215 | git_commit *b2_commit; | |
216 | git_signature *s; | |
217 | git_commit *parent_commits[2]; | |
218 | git_tree *tree; | |
219 | ||
220 | cl_git_pass(git_signature_now(&s, "alice", "alice@example.com")); | |
221 | ||
222 | cl_git_pass(git_reference_name_to_id(&b1_oid, g_repo, "HEAD")); | |
223 | cl_git_pass(git_reference_name_to_id(&b2_oid, g_repo, "refs/heads/test")); | |
224 | ||
225 | cl_git_pass(git_commit_lookup(&b1_commit, g_repo, &b1_oid)); | |
226 | cl_git_pass(git_commit_lookup(&b2_commit, g_repo, &b2_oid)); | |
227 | ||
228 | parent_commits[0] = b1_commit; | |
229 | parent_commits[1] = b2_commit; | |
230 | ||
231 | cl_git_pass(git_commit_tree(&tree, b1_commit)); | |
232 | ||
233 | cl_git_pass(git_commit_create(&merge_commit_oid, | |
234 | g_repo, "HEAD", s, s, NULL, | |
235 | "Merge commit", tree, | |
236 | 2, (const struct git_commit **) parent_commits)); | |
237 | ||
238 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
239 | NULL, | |
240 | git_oid_tostr_s(&merge_commit_oid), | |
241 | NULL, "commit (merge): Merge commit"); | |
242 | ||
243 | git_tree_free(tree); | |
244 | git_commit_free(b1_commit); | |
245 | git_commit_free(b2_commit); | |
246 | git_signature_free(s); | |
247 | } | |
248 | ||
249 | void test_refs_reflog_messages__creating_a_direct_reference(void) | |
250 | { | |
251 | git_reference *reference; | |
252 | git_oid id; | |
253 | git_reflog *reflog; | |
254 | const git_reflog_entry *entry; | |
255 | ||
256 | const char *name = "refs/heads/new-head"; | |
257 | const char *message = "You've been logged, mate!"; | |
258 | ||
259 | cl_git_pass(git_reference_name_to_id(&id, g_repo, "HEAD")); | |
260 | ||
261 | cl_git_pass(git_reference_create(&reference, g_repo, name, &id, 0, message)); | |
262 | ||
263 | cl_git_pass(git_reflog_read(&reflog, g_repo, name)); | |
264 | cl_assert_equal_sz(1, git_reflog_entrycount(reflog)); | |
265 | ||
266 | entry = git_reflog_entry_byindex(reflog, 0); | |
267 | cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); | |
268 | cl_assert_equal_oid(&id, &entry->oid_cur); | |
269 | cl_assert_equal_s(message, entry->msg); | |
270 | ||
271 | git_reflog_free(reflog); | |
272 | git_reference_free(reference); | |
273 | } | |
274 | ||
22a2d3d5 UG |
275 | void test_refs_reflog_messages__newline_gets_replaced(void) |
276 | { | |
277 | const git_reflog_entry *entry; | |
278 | git_signature *signature; | |
279 | git_reflog *reflog; | |
280 | git_oid oid; | |
281 | ||
282 | cl_git_pass(git_signature_now(&signature, "me", "foo@example.com")); | |
283 | cl_git_pass(git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); | |
284 | ||
285 | cl_git_pass(git_reflog_read(&reflog, g_repo, "HEAD")); | |
286 | cl_assert_equal_sz(7, git_reflog_entrycount(reflog)); | |
287 | cl_git_pass(git_reflog_append(reflog, &oid, signature, "inner\nnewline")); | |
288 | cl_assert_equal_sz(8, git_reflog_entrycount(reflog)); | |
289 | ||
290 | cl_assert(entry = git_reflog_entry_byindex(reflog, 0)); | |
291 | cl_assert_equal_s(git_reflog_entry_message(entry), "inner newline"); | |
292 | ||
293 | git_signature_free(signature); | |
294 | git_reflog_free(reflog); | |
295 | } | |
eae0bfdc PP |
296 | |
297 | void test_refs_reflog_messages__renaming_ref(void) | |
298 | { | |
299 | git_reference *ref, *new_ref; | |
300 | ||
301 | cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/heads/master")); | |
302 | cl_git_pass(git_reference_rename(&new_ref, ref, "refs/heads/renamed", false, | |
303 | "message")); | |
304 | ||
305 | cl_reflog_check_entry(g_repo, git_reference_name(new_ref), 0, | |
306 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
307 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
308 | "foo@example.com", "message"); | |
309 | ||
310 | git_reference_free(ref); | |
311 | git_reference_free(new_ref); | |
312 | } | |
313 | ||
314 | void test_refs_reflog_messages__updating_a_direct_reference(void) | |
315 | { | |
316 | git_reference *ref, *ref_out, *target_ref; | |
317 | git_oid target_id; | |
318 | const char *message = "You've been logged, mate!"; | |
319 | ||
320 | git_reference_name_to_id(&target_id, g_repo, "refs/heads/haacked"); | |
321 | cl_git_pass(git_reference_lookup(&target_ref, g_repo, "refs/heads/haacked")); | |
322 | ||
323 | cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/heads/master")); | |
324 | ||
325 | cl_git_pass(git_reference_set_target(&ref_out, ref, &target_id, message)); | |
326 | ||
327 | cl_reflog_check_entry(g_repo, "refs/heads/master", 0, | |
328 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
329 | "258f0e2a959a364e40ed6603d5d44fbb24765b10", | |
330 | NULL, message); | |
331 | ||
332 | git_reference_free(target_ref); | |
333 | git_reference_free(ref); | |
334 | git_reference_free(ref_out); | |
335 | } | |
336 | ||
337 | #define NEW_BRANCH_NAME "new-branch-on-the-block" | |
338 | ||
339 | void test_refs_reflog_messages__creating_branches_default_messages(void) | |
340 | { | |
341 | git_buf buf = GIT_BUF_INIT; | |
342 | git_annotated_commit *annotated; | |
343 | git_object *obj; | |
344 | git_commit *target; | |
345 | git_reference *branch1, *branch2; | |
346 | ||
347 | cl_git_pass(git_revparse_single(&obj, g_repo, "e90810b8df3")); | |
348 | cl_git_pass(git_commit_lookup(&target, g_repo, git_object_id(obj))); | |
349 | git_object_free(obj); | |
350 | ||
351 | cl_git_pass(git_branch_create(&branch1, g_repo, NEW_BRANCH_NAME, target, false)); | |
352 | ||
353 | cl_git_pass(git_buf_printf(&buf, "branch: Created from %s", git_oid_tostr_s(git_commit_id(target)))); | |
354 | cl_reflog_check_entry(g_repo, "refs/heads/" NEW_BRANCH_NAME, 0, | |
355 | GIT_OID_HEX_ZERO, | |
356 | git_oid_tostr_s(git_commit_id(target)), | |
357 | g_email, git_buf_cstr(&buf)); | |
358 | ||
359 | cl_git_pass(git_reference_remove(g_repo, "refs/heads/" NEW_BRANCH_NAME)); | |
360 | ||
361 | cl_git_pass(git_annotated_commit_from_revspec(&annotated, g_repo, "e90810b8df3")); | |
362 | cl_git_pass(git_branch_create_from_annotated(&branch2, g_repo, NEW_BRANCH_NAME, annotated, true)); | |
363 | ||
364 | cl_reflog_check_entry(g_repo, "refs/heads/" NEW_BRANCH_NAME, 0, | |
365 | GIT_OID_HEX_ZERO, | |
366 | git_oid_tostr_s(git_commit_id(target)), | |
367 | g_email, "branch: Created from e90810b8df3"); | |
368 | ||
369 | git_annotated_commit_free(annotated); | |
ac3d33df | 370 | git_buf_dispose(&buf); |
eae0bfdc PP |
371 | git_commit_free(target); |
372 | git_reference_free(branch1); | |
373 | git_reference_free(branch2); | |
374 | } | |
375 | ||
376 | void test_refs_reflog_messages__moving_branch_default_message(void) | |
377 | { | |
378 | git_reference *branch; | |
379 | git_reference *new_branch; | |
380 | git_oid id; | |
381 | ||
382 | cl_git_pass(git_reference_lookup(&branch, g_repo, "refs/heads/master")); | |
383 | git_oid_cpy(&id, git_reference_target(branch)); | |
384 | cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0)); | |
385 | ||
386 | cl_reflog_check_entry(g_repo, git_reference_name(new_branch), 0, | |
387 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
388 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
389 | g_email, | |
390 | "branch: renamed refs/heads/master to refs/heads/master2"); | |
391 | ||
392 | git_reference_free(branch); | |
393 | git_reference_free(new_branch); | |
394 | } | |
395 | ||
396 | void test_refs_reflog_messages__detaching_head_default_message(void) | |
397 | { | |
398 | git_reference *ref; | |
399 | ||
400 | cl_assert_equal_i(false, git_repository_head_detached(g_repo)); | |
401 | ||
402 | cl_git_pass(git_repository_detach_head(g_repo)); | |
403 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
404 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
405 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
406 | NULL, "checkout: moving from master to a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); | |
407 | cl_assert_equal_i(true, git_repository_head_detached(g_repo)); | |
408 | ||
409 | /* take the repo back to its original state */ | |
410 | cl_git_pass(git_reference_symbolic_create(&ref, g_repo, "HEAD", "refs/heads/master", | |
411 | true, "REATTACH")); | |
412 | ||
413 | cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0, | |
414 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
415 | "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", | |
416 | NULL, "REATTACH"); | |
417 | ||
418 | cl_assert_equal_i(false, git_repository_head_detached(g_repo)); | |
419 | ||
420 | git_reference_free(ref); | |
421 | } |