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