]>
git.proxmox.com Git - libgit2.git/blob - tests/repo/head.c
1 #include "clar_libgit2.h"
3 #include "repo_helpers.h"
6 static const char * g_email
= "foo@example.com" ;
7 static git_repository
* repo
;
9 void test_repo_head__initialize ( void )
11 repo
= cl_git_sandbox_init ( "testrepo.git" );
12 cl_git_pass ( git_repository_set_ident ( repo
, "Foo Bar" , g_email
));
15 void test_repo_head__cleanup ( void )
17 cl_git_sandbox_cleanup ();
20 static void check_last_reflog_entry ( const char * email
, const char * message
)
23 const git_reflog_entry
* entry
;
25 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
26 cl_assert ( git_reflog_entrycount ( log
) > 0 );
27 entry
= git_reflog_entry_byindex ( log
, 0 );
29 cl_assert_equal_s ( email
, git_reflog_entry_committer ( entry
)-> email
);
31 cl_assert_equal_s ( message
, git_reflog_entry_message ( entry
));
35 void test_repo_head__head_detached ( void )
39 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
41 cl_git_pass ( git_repository_detach_head ( repo
));
42 check_last_reflog_entry ( g_email
, "checkout: moving from master to a65fedf39aefe402d3bb6e24df4d4f5fe4547750" );
43 cl_assert_equal_i ( true , git_repository_head_detached ( repo
));
45 /* take the repo back to it's original state */
46 cl_git_pass ( git_reference_symbolic_create (& ref
, repo
, "HEAD" , "refs/heads/master" ,
48 git_reference_free ( ref
);
50 check_last_reflog_entry ( g_email
, "REATTACH" );
51 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
54 void test_repo_head__unborn_head ( void )
58 cl_git_pass ( git_repository_head_detached ( repo
));
60 make_head_unborn ( repo
, NON_EXISTING_HEAD
);
62 cl_assert ( git_repository_head_unborn ( repo
) == 1 );
65 /* take the repo back to it's original state */
66 cl_git_pass ( git_reference_symbolic_create (& ref
, repo
, "HEAD" , "refs/heads/master" , 1 , NULL
));
67 cl_assert ( git_repository_head_unborn ( repo
) == 0 );
69 git_reference_free ( ref
);
72 void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_doesnt_exist ( void )
76 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/doesnt/exist/yet" ));
78 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
80 cl_assert_equal_i ( GIT_EUNBORNBRANCH
, git_repository_head (& head
, repo
));
83 void test_repo_head__set_head_Returns_ENOTFOUND_when_the_reference_doesnt_exist ( void )
85 cl_assert_equal_i ( GIT_ENOTFOUND
, git_repository_set_head ( repo
, "refs/tags/doesnt/exist/yet" ));
88 void test_repo_head__set_head_Fails_when_the_reference_points_to_a_non_commitish ( void )
90 cl_git_fail ( git_repository_set_head ( repo
, "refs/tags/point_to_blob" ));
93 void test_repo_head__set_head_Attaches_HEAD_when_the_reference_points_to_a_branch ( void )
97 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/br2" ));
99 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
101 cl_git_pass ( git_repository_head (& head
, repo
));
102 cl_assert_equal_s ( "refs/heads/br2" , git_reference_name ( head
));
104 git_reference_free ( head
);
107 static void assert_head_is_correctly_detached ( void )
112 cl_assert_equal_i ( true , git_repository_head_detached ( repo
));
114 cl_git_pass ( git_repository_head (& head
, repo
));
116 cl_git_pass ( git_object_lookup (& commit
, repo
, git_reference_target ( head
), GIT_OBJ_COMMIT
));
118 git_object_free ( commit
);
119 git_reference_free ( head
);
122 void test_repo_head__set_head_Detaches_HEAD_when_the_reference_doesnt_point_to_a_branch ( void )
124 cl_git_pass ( git_repository_set_head ( repo
, "refs/tags/test" ));
126 cl_assert_equal_i ( true , git_repository_head_detached ( repo
));
128 assert_head_is_correctly_detached ();
131 void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_exist ( void )
135 cl_git_pass ( git_oid_fromstr (& oid
, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ));
137 cl_assert_equal_i ( GIT_ENOTFOUND
, git_repository_set_head_detached ( repo
, & oid
));
140 void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish ( void )
144 cl_git_pass ( git_revparse_single (& blob
, repo
, "point_to_blob" ));
146 cl_git_fail ( git_repository_set_head_detached ( repo
, git_object_id ( blob
)));
148 git_object_free ( blob
);
151 void test_repo_head__set_head_detached_Detaches_HEAD_and_make_it_point_to_the_peeled_commit ( void )
155 cl_git_pass ( git_revparse_single (& tag
, repo
, "tags/test" ));
156 cl_assert_equal_i ( GIT_OBJ_TAG
, git_object_type ( tag
));
158 cl_git_pass ( git_repository_set_head_detached ( repo
, git_object_id ( tag
)));
160 assert_head_is_correctly_detached ();
162 git_object_free ( tag
);
165 void test_repo_head__detach_head_Detaches_HEAD_and_make_it_point_to_the_peeled_commit ( void )
167 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
169 cl_git_pass ( git_repository_detach_head ( repo
));
171 assert_head_is_correctly_detached ();
174 void test_repo_head__detach_head_Fails_if_HEAD_and_point_to_a_non_commitish ( void )
178 cl_git_pass ( git_reference_symbolic_create (& head
, repo
, GIT_HEAD_FILE
, "refs/tags/point_to_blob" , 1 , NULL
));
180 cl_git_fail ( git_repository_detach_head ( repo
));
182 git_reference_free ( head
);
185 void test_repo_head__detaching_an_unborn_branch_returns_GIT_EUNBORNBRANCH ( void )
187 make_head_unborn ( repo
, NON_EXISTING_HEAD
);
189 cl_assert_equal_i ( GIT_EUNBORNBRANCH
, git_repository_detach_head ( repo
));
192 void test_repo_head__retrieving_an_unborn_branch_returns_GIT_EUNBORNBRANCH ( void )
196 make_head_unborn ( repo
, NON_EXISTING_HEAD
);
198 cl_assert_equal_i ( GIT_EUNBORNBRANCH
, git_repository_head (& head
, repo
));
201 void test_repo_head__retrieving_a_missing_head_returns_GIT_ENOTFOUND ( void )
207 cl_assert_equal_i ( GIT_ENOTFOUND
, git_repository_head (& head
, repo
));
210 void test_repo_head__can_tell_if_an_unborn_head_is_detached ( void )
212 make_head_unborn ( repo
, NON_EXISTING_HEAD
);
214 cl_assert_equal_i ( false , git_repository_head_detached ( repo
));
217 static void test_reflog ( git_repository
* repo
, size_t idx
,
218 const char * old_spec
, const char * new_spec
,
219 const char * email
, const char * message
)
222 const git_reflog_entry
* entry
;
224 cl_git_pass ( git_reflog_read (& log
, repo
, "HEAD" ));
225 entry
= git_reflog_entry_byindex ( log
, idx
);
229 cl_git_pass ( git_revparse_single (& obj
, repo
, old_spec
));
230 cl_assert_equal_oid ( git_object_id ( obj
), git_reflog_entry_id_old ( entry
));
231 git_object_free ( obj
);
235 cl_git_pass ( git_revparse_single (& obj
, repo
, new_spec
));
236 cl_assert_equal_oid ( git_object_id ( obj
), git_reflog_entry_id_new ( entry
));
237 git_object_free ( obj
);
241 cl_assert_equal_s ( email
, git_reflog_entry_committer ( entry
)-> email
);
244 cl_assert_equal_s ( message
, git_reflog_entry_message ( entry
));
247 git_reflog_free ( log
);
250 void test_repo_head__setting_head_updates_reflog ( void )
255 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
257 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
258 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/unborn" ));
259 cl_git_pass ( git_revparse_single (& tag
, repo
, "tags/test" ));
260 cl_git_pass ( git_repository_set_head_detached ( repo
, git_object_id ( tag
)));
261 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
263 test_reflog ( repo
, 2 , NULL
, "refs/heads/haacked" , "foo@example.com" , "checkout: moving from master to haacked" );
264 test_reflog ( repo
, 1 , NULL
, "tags/test^{commit}" , "foo@example.com" , "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d" );
265 test_reflog ( repo
, 0 , "tags/test^{commit}" , "refs/heads/haacked" , "foo@example.com" , "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked" );
267 git_object_free ( tag
);
268 git_signature_free ( sig
);
271 static void assert_head_reflog ( git_repository
* repo
, size_t idx
,
272 const char * old_id
, const char * new_id
, const char * message
)
275 const git_reflog_entry
* entry
;
276 char id_str
[ GIT_OID_HEXSZ
+ 1 ] = { 0 };
278 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
279 entry
= git_reflog_entry_byindex ( log
, idx
);
281 git_oid_fmt ( id_str
, git_reflog_entry_id_old ( entry
));
282 cl_assert_equal_s ( old_id
, id_str
);
284 git_oid_fmt ( id_str
, git_reflog_entry_id_new ( entry
));
285 cl_assert_equal_s ( new_id
, id_str
);
287 cl_assert_equal_s ( message
, git_reflog_entry_message ( entry
));
289 git_reflog_free ( log
);
292 void test_repo_head__detaching_writes_reflog ( void )
298 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
300 msg
= "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d" ;
301 git_oid_fromstr (& id
, "e90810b8df3e80c413d903f631643c716887138d" );
302 cl_git_pass ( git_repository_set_head_detached ( repo
, & id
));
303 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
304 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
306 msg
= "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked" ;
307 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
308 assert_head_reflog ( repo
, 0 , "e90810b8df3e80c413d903f631643c716887138d" ,
309 "258f0e2a959a364e40ed6603d5d44fbb24765b10" , msg
);
311 git_signature_free ( sig
);
314 void test_repo_head__orphan_branch_does_not_count ( void )
319 /* Have something known */
320 msg
= "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d" ;
321 git_oid_fromstr (& id
, "e90810b8df3e80c413d903f631643c716887138d" );
322 cl_git_pass ( git_repository_set_head_detached ( repo
, & id
));
323 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
324 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
326 /* Switching to an orphan branch does not write tot he reflog */
327 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/orphan" ));
328 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
329 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
331 /* And coming back, we set the source to zero */
332 msg
= "checkout: moving from orphan to haacked" ;
333 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
334 assert_head_reflog ( repo
, 0 , "0000000000000000000000000000000000000000" ,
335 "258f0e2a959a364e40ed6603d5d44fbb24765b10" , msg
);
338 void test_repo_head__set_to_current_target ( void )
341 size_t nentries
, nentries_after
;
343 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
344 nentries
= git_reflog_entrycount ( log
);
345 git_reflog_free ( log
);
347 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
348 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
350 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
351 nentries_after
= git_reflog_entrycount ( log
);
352 git_reflog_free ( log
);
354 cl_assert_equal_i ( nentries
+ 1 , nentries_after
);
357 void test_repo_head__branch_birth ( void )
365 size_t nentries
, nentries_after
;
367 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
368 nentries
= git_reflog_entrycount ( log
);
369 git_reflog_free ( log
);
371 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
373 cl_git_pass ( git_repository_head (& ref
, repo
));
374 cl_git_pass ( git_reference_peel (( git_object
**) & tree
, ref
, GIT_OBJ_TREE
));
375 git_reference_free ( ref
);
377 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/orphan" ));
379 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
380 nentries_after
= git_reflog_entrycount ( log
);
381 git_reflog_free ( log
);
383 cl_assert_equal_i ( nentries
, nentries_after
);
386 cl_git_pass ( git_commit_create (& id
, repo
, "HEAD" , sig
, sig
, NULL
, msg
, tree
, 0 , NULL
));
390 cl_git_pass ( git_reflog_read (& log
, repo
, "refs/heads/orphan" ));
391 cl_assert_equal_i ( 1 , git_reflog_entrycount ( log
));
392 git_reflog_free ( log
);
394 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
395 nentries_after
= git_reflog_entrycount ( log
);
396 git_reflog_free ( log
);
398 cl_assert_equal_i ( nentries
+ 1 , nentries_after
);
400 git_signature_free ( sig
);
404 static size_t entrycount ( git_repository
* repo
, const char * name
)
409 cl_git_pass ( git_reflog_read (& log
, repo
, name
));
410 ret
= git_reflog_entrycount ( log
);
411 git_reflog_free ( log
);
416 void test_repo_head__symref_chain ( void )
423 size_t nentries
, nentries_master
;
425 nentries
= entrycount ( repo
, GIT_HEAD_FILE
);
427 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
429 cl_git_pass ( git_repository_head (& ref
, repo
));
430 cl_git_pass ( git_reference_peel (( git_object
**) & tree
, ref
, GIT_OBJ_TREE
));
431 git_reference_free ( ref
);
433 nentries_master
= entrycount ( repo
, "refs/heads/master" );
436 cl_git_pass ( git_reference_symbolic_create (& ref
, repo
, "refs/heads/master" , "refs/heads/foo" , 1 , msg
));
437 git_reference_free ( ref
);
439 cl_assert_equal_i ( 0 , entrycount ( repo
, "refs/heads/foo" ));
440 cl_assert_equal_i ( nentries
, entrycount ( repo
, GIT_HEAD_FILE
));
441 cl_assert_equal_i ( nentries_master
, entrycount ( repo
, "refs/heads/master" ));
444 cl_git_pass ( git_commit_create (& id
, repo
, "HEAD" , sig
, sig
, NULL
, msg
, tree
, 0 , NULL
));
447 cl_assert_equal_i ( 1 , entrycount ( repo
, "refs/heads/foo" ));
448 cl_assert_equal_i ( nentries
+ 1 , entrycount ( repo
, GIT_HEAD_FILE
));
449 cl_assert_equal_i ( nentries_master
, entrycount ( repo
, "refs/heads/master" ));
451 git_signature_free ( sig
);