]>
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" ));
265 test_reflog ( repo
, 2 , NULL
, "refs/heads/haacked" , "foo@example.com" , "checkout: moving from master to haacked" );
266 test_reflog ( repo
, 1 , NULL
, "tags/test^{commit}" , "foo@example.com" , "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d" );
267 test_reflog ( repo
, 0 , "tags/test^{commit}" , "refs/heads/haacked" , "foo@example.com" , "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked" );
269 cl_git_pass ( git_annotated_commit_from_revspec (& annotated
, repo
, "haacked~0" ));
270 cl_git_pass ( git_repository_set_head_detached_from_annotated ( repo
, annotated
));
272 test_reflog ( repo
, 0 , NULL
, "refs/heads/haacked" , "foo@example.com" , "checkout: moving from haacked to haacked~0" );
274 git_annotated_commit_free ( annotated
);
275 git_object_free ( tag
);
276 git_signature_free ( sig
);
279 static void assert_head_reflog ( git_repository
* repo
, size_t idx
,
280 const char * old_id
, const char * new_id
, const char * message
)
283 const git_reflog_entry
* entry
;
284 char id_str
[ GIT_OID_HEXSZ
+ 1 ] = { 0 };
286 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
287 entry
= git_reflog_entry_byindex ( log
, idx
);
289 git_oid_fmt ( id_str
, git_reflog_entry_id_old ( entry
));
290 cl_assert_equal_s ( old_id
, id_str
);
292 git_oid_fmt ( id_str
, git_reflog_entry_id_new ( entry
));
293 cl_assert_equal_s ( new_id
, id_str
);
295 cl_assert_equal_s ( message
, git_reflog_entry_message ( entry
));
297 git_reflog_free ( log
);
300 void test_repo_head__detaching_writes_reflog ( void )
306 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
308 msg
= "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d" ;
309 git_oid_fromstr (& id
, "e90810b8df3e80c413d903f631643c716887138d" );
310 cl_git_pass ( git_repository_set_head_detached ( repo
, & id
));
311 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
312 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
314 msg
= "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked" ;
315 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
316 assert_head_reflog ( repo
, 0 , "e90810b8df3e80c413d903f631643c716887138d" ,
317 "258f0e2a959a364e40ed6603d5d44fbb24765b10" , msg
);
319 git_signature_free ( sig
);
322 void test_repo_head__orphan_branch_does_not_count ( void )
327 /* Have something known */
328 msg
= "checkout: moving from master to e90810b8df3e80c413d903f631643c716887138d" ;
329 git_oid_fromstr (& id
, "e90810b8df3e80c413d903f631643c716887138d" );
330 cl_git_pass ( git_repository_set_head_detached ( repo
, & id
));
331 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
332 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
334 /* Switching to an orphan branch does not write tot he reflog */
335 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/orphan" ));
336 assert_head_reflog ( repo
, 0 , "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" ,
337 "e90810b8df3e80c413d903f631643c716887138d" , msg
);
339 /* And coming back, we set the source to zero */
340 msg
= "checkout: moving from orphan to haacked" ;
341 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
342 assert_head_reflog ( repo
, 0 , "0000000000000000000000000000000000000000" ,
343 "258f0e2a959a364e40ed6603d5d44fbb24765b10" , msg
);
346 void test_repo_head__set_to_current_target ( void )
349 size_t nentries
, nentries_after
;
351 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
352 nentries
= git_reflog_entrycount ( log
);
353 git_reflog_free ( log
);
355 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
356 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/haacked" ));
358 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
359 nentries_after
= git_reflog_entrycount ( log
);
360 git_reflog_free ( log
);
362 cl_assert_equal_i ( nentries
+ 1 , nentries_after
);
365 void test_repo_head__branch_birth ( void )
373 size_t nentries
, nentries_after
;
375 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
376 nentries
= git_reflog_entrycount ( log
);
377 git_reflog_free ( log
);
379 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
381 cl_git_pass ( git_repository_head (& ref
, repo
));
382 cl_git_pass ( git_reference_peel (( git_object
**) & tree
, ref
, GIT_OBJ_TREE
));
383 git_reference_free ( ref
);
385 cl_git_pass ( git_repository_set_head ( repo
, "refs/heads/orphan" ));
387 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
388 nentries_after
= git_reflog_entrycount ( log
);
389 git_reflog_free ( log
);
391 cl_assert_equal_i ( nentries
, nentries_after
);
394 cl_git_pass ( git_commit_create (& id
, repo
, "HEAD" , sig
, sig
, NULL
, msg
, tree
, 0 , NULL
));
398 cl_git_pass ( git_reflog_read (& log
, repo
, "refs/heads/orphan" ));
399 cl_assert_equal_i ( 1 , git_reflog_entrycount ( log
));
400 git_reflog_free ( log
);
402 cl_git_pass ( git_reflog_read (& log
, repo
, GIT_HEAD_FILE
));
403 nentries_after
= git_reflog_entrycount ( log
);
404 git_reflog_free ( log
);
406 cl_assert_equal_i ( nentries
+ 1 , nentries_after
);
408 git_signature_free ( sig
);
412 static size_t entrycount ( git_repository
* repo
, const char * name
)
417 cl_git_pass ( git_reflog_read (& log
, repo
, name
));
418 ret
= git_reflog_entrycount ( log
);
419 git_reflog_free ( log
);
424 void test_repo_head__symref_chain ( void )
431 size_t nentries
, nentries_master
;
433 nentries
= entrycount ( repo
, GIT_HEAD_FILE
);
435 cl_git_pass ( git_signature_now (& sig
, "me" , "foo@example.com" ));
437 cl_git_pass ( git_repository_head (& ref
, repo
));
438 cl_git_pass ( git_reference_peel (( git_object
**) & tree
, ref
, GIT_OBJ_TREE
));
439 git_reference_free ( ref
);
441 nentries_master
= entrycount ( repo
, "refs/heads/master" );
444 cl_git_pass ( git_reference_symbolic_create (& ref
, repo
, "refs/heads/master" , "refs/heads/foo" , 1 , msg
));
445 git_reference_free ( ref
);
447 cl_assert_equal_i ( 0 , entrycount ( repo
, "refs/heads/foo" ));
448 cl_assert_equal_i ( nentries
, entrycount ( repo
, GIT_HEAD_FILE
));
449 cl_assert_equal_i ( nentries_master
, entrycount ( repo
, "refs/heads/master" ));
452 cl_git_pass ( git_commit_create (& id
, repo
, "HEAD" , sig
, sig
, NULL
, msg
, tree
, 0 , NULL
));
455 cl_assert_equal_i ( 1 , entrycount ( repo
, "refs/heads/foo" ));
456 cl_assert_equal_i ( nentries
+ 1 , entrycount ( repo
, GIT_HEAD_FILE
));
457 cl_assert_equal_i ( nentries_master
, entrycount ( repo
, "refs/heads/master" ));
459 git_signature_free ( sig
);