]>
git.proxmox.com Git - libgit2.git/blob - tests/repo/head.c
1 #include "clar_libgit2.h"
3 #include "repo_helpers.h"
5 #include "git2/annotated_commit.h"
7 static const char * g_email
= "foo@example.com" ;
8 static git_repository
* repo
;
10 void test_repo_head__initialize ( void )
12 repo
= cl_git_sandbox_init ( "testrepo.git" );
13 cl_git_pass ( git_repository_set_ident ( repo
, "Foo Bar" , g_email
));
16 void test_repo_head__cleanup ( void )
18 cl_git_sandbox_cleanup ();
21 static void check_last_reflog_entry ( const char * email
, const char * message
)
24 const git_reflog_entry
* entry
;
26 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
27 cl_assert ( git_reflog_entrycount ( log
) > 0 );
28 entry
= git_reflog_entry_byindex ( log
, 0 );
30 cl_assert_equal_s ( email
, git_reflog_entry_committer ( entry
)-> email
);
32 cl_assert_equal_s ( message
, git_reflog_entry_message ( entry
));
36 void test_repo_head__head_detached ( void )
40 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
42 cl_git_pass ( git_repository_detach_head ( repo
));
43 check_last_reflog_entry ( g_email
, "checkout: moving from master to a65fedf39aefe402d3bb6e24df4d4f5fe4547750" );
44 cl_assert_equal_i ( true , git_repository_head_detached ( repo
));
46 /* take the repo back to it's original state */
47 cl_git_pass ( git_reference_symbolic_create (& ref
, repo
, "HEAD" , "refs/heads/master" ,
49 git_reference_free ( ref
);
51 check_last_reflog_entry ( g_email
, "REATTACH" );
52 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
55 void test_repo_head__unborn_head ( void )
59 cl_git_pass ( git_repository_head_detached ( repo
));
61 make_head_unborn ( repo
, NON_EXISTING_HEAD
);
63 cl_assert ( git_repository_head_unborn ( repo
) == 1 );
66 /* take the repo back to it's original state */
67 cl_git_pass ( git_reference_symbolic_create (& ref
, repo
, "HEAD" , "refs/heads/master" , 1 , NULL
));
68 cl_assert ( git_repository_head_unborn ( repo
) == 0 );
70 git_reference_free ( ref
);
73 void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_doesnt_exist ( void )
77 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/doesnt/exist/yet" ));
79 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
81 cl_assert_equal_i ( GIT_EUNBORNBRANCH
, git_repository_head (& head
, repo
));
84 void test_repo_head__set_head_Returns_ENOTFOUND_when_the_reference_doesnt_exist ( void )
86 cl_assert_equal_i ( GIT_ENOTFOUND
, git_repository_set_head ( repo
, "refs/tags/doesnt/exist/yet" ));
89 void test_repo_head__set_head_Fails_when_the_reference_points_to_a_non_commitish ( void )
91 cl_git_fail ( git_repository_set_head ( repo
, "refs/tags/point_to_blob" ));
94 void test_repo_head__set_head_Attaches_HEAD_when_the_reference_points_to_a_branch ( void )
98 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/br2" ));
100 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
102 cl_git_pass ( git_repository_head (& head
, repo
));
103 cl_assert_equal_s ( "refs/heads/br2" , git_reference_name ( head
));
105 git_reference_free ( head
);
108 static void assert_head_is_correctly_detached ( void )
113 cl_assert_equal_i ( true , git_repository_head_detached ( repo
));
115 cl_git_pass ( git_repository_head (& head
, repo
));
117 cl_git_pass ( git_object_lookup (& commit
, repo
, git_reference_target ( head
), GIT_OBJ_COMMIT
));
119 git_object_free ( commit
);
120 git_reference_free ( head
);
123 void test_repo_head__set_head_Detaches_HEAD_when_the_reference_doesnt_point_to_a_branch ( void )
125 cl_git_pass ( git_repository_set_head ( repo
, "refs/tags/test" ));
127 cl_assert_equal_i ( true , git_repository_head_detached ( repo
));
129 assert_head_is_correctly_detached ();
132 void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_exist ( void )
136 cl_git_pass ( git_oid_fromstr (& oid
, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ));
138 cl_assert_equal_i ( GIT_ENOTFOUND
, git_repository_set_head_detached ( repo
, & oid
));
141 void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish ( void )
145 cl_git_pass ( git_revparse_single (& blob
, repo
, "point_to_blob" ));
147 cl_git_fail ( git_repository_set_head_detached ( repo
, git_object_id ( blob
)));
149 git_object_free ( blob
);
152 void test_repo_head__set_head_detached_Detaches_HEAD_and_make_it_point_to_the_peeled_commit ( void )
156 cl_git_pass ( git_revparse_single (& tag
, repo
, "tags/test" ));
157 cl_assert_equal_i ( GIT_OBJ_TAG
, git_object_type ( tag
));
159 cl_git_pass ( git_repository_set_head_detached ( repo
, git_object_id ( tag
)));
161 assert_head_is_correctly_detached ();
163 git_object_free ( tag
);
166 void test_repo_head__detach_head_Detaches_HEAD_and_make_it_point_to_the_peeled_commit ( void )
168 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
170 cl_git_pass ( git_repository_detach_head ( repo
));
172 assert_head_is_correctly_detached ();
175 void test_repo_head__detach_head_Fails_if_HEAD_and_point_to_a_non_commitish ( void )
179 cl_git_pass ( git_reference_symbolic_create (& head
, repo
, GIT_HEAD_FILE
, "refs/tags/point_to_blob" , 1 , NULL
));
181 cl_git_fail ( git_repository_detach_head ( repo
));
183 git_reference_free ( head
);
186 void test_repo_head__detaching_an_unborn_branch_returns_GIT_EUNBORNBRANCH ( void )
188 make_head_unborn ( repo
, NON_EXISTING_HEAD
);
190 cl_assert_equal_i ( GIT_EUNBORNBRANCH
, git_repository_detach_head ( repo
));
193 void test_repo_head__retrieving_an_unborn_branch_returns_GIT_EUNBORNBRANCH ( void )
197 make_head_unborn ( repo
, NON_EXISTING_HEAD
);
199 cl_assert_equal_i ( GIT_EUNBORNBRANCH
, git_repository_head (& head
, repo
));
202 void test_repo_head__retrieving_a_missing_head_returns_GIT_ENOTFOUND ( void )
208 cl_assert_equal_i ( GIT_ENOTFOUND
, git_repository_head (& head
, repo
));
211 void test_repo_head__can_tell_if_an_unborn_head_is_detached ( void )
213 make_head_unborn ( repo
, NON_EXISTING_HEAD
);
215 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
218 static void test_reflog ( git_repository
* repo
, size_t idx
,
219 const char * old_spec
, const char * new_spec
,
220 const char * email
, const char * message
)
223 const git_reflog_entry
* entry
;
225 cl_git_pass ( git_reflog_read (& log
, repo
, "HEAD" ));
226 entry
= git_reflog_entry_byindex ( log
, idx
);
230 cl_git_pass ( git_revparse_single (& obj
, repo
, old_spec
));
231 cl_assert_equal_oid ( git_object_id ( obj
), git_reflog_entry_id_old ( entry
));
232 git_object_free ( obj
);
236 cl_git_pass ( git_revparse_single (& obj
, repo
, new_spec
));
237 cl_assert_equal_oid ( git_object_id ( obj
), git_reflog_entry_id_new ( entry
));
238 git_object_free ( obj
);
242 cl_assert_equal_s ( email
, git_reflog_entry_committer ( entry
)-> email
);
245 cl_assert_equal_s ( message
, git_reflog_entry_message ( entry
));
248 git_reflog_free ( log
);
251 void test_repo_head__setting_head_updates_reflog ( void )
255 git_annotated_commit
* annotated
;
257 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
259 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
260 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/unborn" ));
261 cl_git_pass ( git_revparse_single (& tag
, repo
, "tags/test" ));
262 cl_git_pass ( git_repository_set_head_detached ( repo
, git_object_id ( tag
)));
263 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
264 cl_git_pass ( git_repository_set_head ( repo
, "refs/tags/test" ));
265 cl_git_pass ( git_repository_set_head ( repo
, "refs/remotes/test/master" ));
267 test_reflog ( repo
, 4 , NULL
, "refs/heads/haacked" , "foo@example.com" , "checkout: moving from master to haacked" );
268 test_reflog ( repo
, 3 , NULL
, "tags/test^{commit}" , "foo@example.com" , "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d" );
269 test_reflog ( repo
, 2 , "tags/test^{commit}" , "refs/heads/haacked" , "foo@example.com" , "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked" );
270 test_reflog ( repo
, 1 , "refs/heads/haacked" , "tags/test^{commit}" , "foo@example.com" , "checkout: moving from haacked to test" );
271 test_reflog ( repo
, 0 , "tags/test^{commit}" , "refs/remotes/test/master" , "foo@example.com" , "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to test/master" );
273 cl_git_pass ( git_annotated_commit_from_revspec (& annotated
, repo
, "haacked~0" ));
274 cl_git_pass ( git_repository_set_head_detached_from_annotated ( repo
, annotated
));
276 test_reflog ( repo
, 0 , NULL
, "refs/heads/haacked" , "foo@example.com" , "checkout: moving from be3563ae3f795b2b4353bcce3a527ad0a4f7f644 to haacked~0" );
278 git_annotated_commit_free ( annotated
);
279 git_object_free ( tag
);
280 git_signature_free ( sig
);
283 static void assert_head_reflog ( git_repository
* repo
, size_t idx
,
284 const char * old_id
, const char * new_id
, const char * message
)
287 const git_reflog_entry
* entry
;
288 char id_str
[ GIT_OID_HEXSZ
+ 1 ] = { 0 };
290 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
291 entry
= git_reflog_entry_byindex ( log
, idx
);
293 git_oid_fmt ( id_str
, git_reflog_entry_id_old ( entry
));
294 cl_assert_equal_s ( old_id
, id_str
);
296 git_oid_fmt ( id_str
, git_reflog_entry_id_new ( entry
));
297 cl_assert_equal_s ( new_id
, id_str
);
299 cl_assert_equal_s ( message
, git_reflog_entry_message ( entry
));
301 git_reflog_free ( log
);
304 void test_repo_head__detaching_writes_reflog ( void )
310 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
312 msg
= "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d" ;
313 git_oid_fromstr (& id
, "e90810b8df3e80c413d903f631643c716887138d" );
314 cl_git_pass ( git_repository_set_head_detached ( repo
, & id
));
315 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
316 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
318 msg
= "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked" ;
319 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
320 assert_head_reflog ( repo
, 0 , "e90810b8df3e80c413d903f631643c716887138d" ,
321 "258f0e2a959a364e40ed6603d5d44fbb24765b10" , msg
);
323 git_signature_free ( sig
);
326 void test_repo_head__orphan_branch_does_not_count ( void )
331 /* Have something known */
332 msg
= "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d" ;
333 git_oid_fromstr (& id
, "e90810b8df3e80c413d903f631643c716887138d" );
334 cl_git_pass ( git_repository_set_head_detached ( repo
, & id
));
335 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
336 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
338 /* Switching to an orphan branch does not write tot he reflog */
339 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/orphan" ));
340 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
341 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
343 /* And coming back, we set the source to zero */
344 msg
= "checkout: moving from orphan to haacked" ;
345 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
346 assert_head_reflog ( repo
, 0 , "0000000000000000000000000000000000000000" ,
347 "258f0e2a959a364e40ed6603d5d44fbb24765b10" , msg
);
350 void test_repo_head__set_to_current_target ( void )
353 size_t nentries
, nentries_after
;
355 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
356 nentries
= git_reflog_entrycount ( log
);
357 git_reflog_free ( log
);
359 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
360 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
362 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
363 nentries_after
= git_reflog_entrycount ( log
);
364 git_reflog_free ( log
);
366 cl_assert_equal_i ( nentries
+ 1 , nentries_after
);
369 void test_repo_head__branch_birth ( void )
377 size_t nentries
, nentries_after
;
379 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
380 nentries
= git_reflog_entrycount ( log
);
381 git_reflog_free ( log
);
383 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
385 cl_git_pass ( git_repository_head (& ref
, repo
));
386 cl_git_pass ( git_reference_peel (( git_object
**) & tree
, ref
, GIT_OBJ_TREE
));
387 git_reference_free ( ref
);
389 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/orphan" ));
391 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
392 nentries_after
= git_reflog_entrycount ( log
);
393 git_reflog_free ( log
);
395 cl_assert_equal_i ( nentries
, nentries_after
);
398 cl_git_pass ( git_commit_create (& id
, repo
, "HEAD" , sig
, sig
, NULL
, msg
, tree
, 0 , NULL
));
402 cl_git_pass ( git_reflog_read (& log
, repo
, "refs/heads/orphan" ));
403 cl_assert_equal_i ( 1 , git_reflog_entrycount ( log
));
404 git_reflog_free ( log
);
406 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
407 nentries_after
= git_reflog_entrycount ( log
);
408 git_reflog_free ( log
);
410 cl_assert_equal_i ( nentries
+ 1 , nentries_after
);
412 git_signature_free ( sig
);
416 static size_t entrycount ( git_repository
* repo
, const char * name
)
421 cl_git_pass ( git_reflog_read (& log
, repo
, name
));
422 ret
= git_reflog_entrycount ( log
);
423 git_reflog_free ( log
);
428 void test_repo_head__symref_chain ( void )
435 size_t nentries
, nentries_master
;
437 nentries
= entrycount ( repo
, GIT_HEAD_FILE
);
439 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
441 cl_git_pass ( git_repository_head (& ref
, repo
));
442 cl_git_pass ( git_reference_peel (( git_object
**) & tree
, ref
, GIT_OBJ_TREE
));
443 git_reference_free ( ref
);
445 nentries_master
= entrycount ( repo
, "refs/heads/master" );
448 cl_git_pass ( git_reference_symbolic_create (& ref
, repo
, "refs/heads/master" , "refs/heads/foo" , 1 , msg
));
449 git_reference_free ( ref
);
451 cl_assert_equal_i ( 0 , entrycount ( repo
, "refs/heads/foo" ));
452 cl_assert_equal_i ( nentries
, entrycount ( repo
, GIT_HEAD_FILE
));
453 cl_assert_equal_i ( nentries_master
, entrycount ( repo
, "refs/heads/master" ));
456 cl_git_pass ( git_commit_create (& id
, repo
, "HEAD" , sig
, sig
, NULL
, msg
, tree
, 0 , NULL
));
459 cl_assert_equal_i ( 1 , entrycount ( repo
, "refs/heads/foo" ));
460 cl_assert_equal_i ( nentries
+ 1 , entrycount ( repo
, GIT_HEAD_FILE
));
461 cl_assert_equal_i ( nentries_master
, entrycount ( repo
, "refs/heads/master" ));
463 git_signature_free ( sig
);