]>
git.proxmox.com Git - libgit2.git/blob - tests/refs/branches/create.c
1 #include "clar_libgit2.h"
5 static git_repository
*repo
;
6 static git_commit
*target
;
7 static git_reference
*branch
;
9 void test_refs_branches_create__initialize(void)
11 repo
= cl_git_sandbox_init("testrepo.git");
16 void test_refs_branches_create__cleanup(void)
18 git_reference_free(branch
);
21 git_commit_free(target
);
24 cl_git_sandbox_cleanup();
28 static void retrieve_target_from_oid(git_commit
**out
, git_repository
*repo
, const char *sha
)
32 cl_git_pass(git_revparse_single(&obj
, repo
, sha
));
33 cl_git_pass(git_commit_lookup(out
, repo
, git_object_id(obj
)));
37 static void retrieve_known_commit(git_commit
**commit
, git_repository
*repo
)
39 retrieve_target_from_oid(commit
, repo
, "e90810b8df3");
42 #define NEW_BRANCH_NAME "new-branch-on-the-block"
44 void test_refs_branches_create__can_create_a_local_branch(void)
46 retrieve_known_commit(&target
, repo
);
48 cl_git_pass(git_branch_create(&branch
, repo
, NEW_BRANCH_NAME
, target
, 0));
49 cl_git_pass(git_oid_cmp(git_reference_target(branch
), git_commit_id(target
)));
52 void test_refs_branches_create__can_not_create_a_branch_if_its_name_collide_with_an_existing_one(void)
54 retrieve_known_commit(&target
, repo
);
56 cl_assert_equal_i(GIT_EEXISTS
, git_branch_create(&branch
, repo
, "br2", target
, 0));
59 void test_refs_branches_create__can_force_create_over_an_existing_branch(void)
61 retrieve_known_commit(&target
, repo
);
63 cl_git_pass(git_branch_create(&branch
, repo
, "br2", target
, 1));
64 cl_git_pass(git_oid_cmp(git_reference_target(branch
), git_commit_id(target
)));
65 cl_assert_equal_s("refs/heads/br2", git_reference_name(branch
));
68 void test_refs_branches_create__cannot_force_create_over_current_branch(void)
71 git_reference
*branch2
;
72 retrieve_known_commit(&target
, repo
);
74 cl_git_pass(git_branch_lookup(&branch2
, repo
, "master", GIT_BRANCH_LOCAL
));
75 cl_assert_equal_s("refs/heads/master", git_reference_name(branch2
));
76 cl_assert_equal_i(true, git_branch_is_head(branch2
));
77 oid
= git_reference_target(branch2
);
79 cl_git_fail_with(-1, git_branch_create(&branch
, repo
, "master", target
, 1));
81 cl_git_pass(git_branch_lookup(&branch
, repo
, "master", GIT_BRANCH_LOCAL
));
82 cl_assert_equal_s("refs/heads/master", git_reference_name(branch
));
83 cl_git_pass(git_oid_cmp(git_reference_target(branch
), oid
));
84 git_reference_free(branch2
);
87 void test_refs_branches_create__creating_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void)
89 retrieve_known_commit(&target
, repo
);
91 cl_assert_equal_i(GIT_EINVALIDSPEC
,
92 git_branch_create(&branch
, repo
, "inv@{id", target
, 0));
95 void test_refs_branches_create__default_reflog_message(void)
98 git_buf buf
= GIT_BUF_INIT
;
99 const git_reflog_entry
*entry
;
103 cl_git_pass(git_repository_config(&cfg
, repo
));
104 cl_git_pass(git_config_set_string(cfg
, "user.name", "Foo Bar"));
105 cl_git_pass(git_config_set_string(cfg
, "user.email", "foo@example.com"));
106 git_config_free(cfg
);
108 cl_git_pass(git_signature_default(&sig
, repo
));
110 retrieve_known_commit(&target
, repo
);
111 cl_git_pass(git_branch_create(&branch
, repo
, NEW_BRANCH_NAME
, target
, false));
112 cl_git_pass(git_reflog_read(&log
, repo
, "refs/heads/" NEW_BRANCH_NAME
));
114 entry
= git_reflog_entry_byindex(log
, 0);
115 cl_git_pass(git_buf_printf(&buf
, "branch: Created from %s", git_oid_tostr_s(git_commit_id(target
))));
116 cl_assert_equal_s(git_buf_cstr(&buf
), git_reflog_entry_message(entry
));
117 cl_assert_equal_s(sig
->email
, git_reflog_entry_committer(entry
)->email
);
120 git_reflog_free(log
);
121 git_signature_free(sig
);
124 static void assert_branch_matches_name(
125 const char *expected
, const char *lookup_as
)
128 git_buf b
= GIT_BUF_INIT
;
130 cl_git_pass(git_branch_lookup(&ref
, repo
, lookup_as
, GIT_BRANCH_LOCAL
));
132 cl_git_pass(git_buf_sets(&b
, "refs/heads/"));
133 cl_git_pass(git_buf_puts(&b
, expected
));
134 cl_assert_equal_s(b
.ptr
, git_reference_name(ref
));
137 git_oid_cmp(git_reference_target(ref
), git_commit_id(target
)));
139 git_reference_free(ref
);
143 void test_refs_branches_create__can_create_branch_with_unicode(void)
145 const char *nfc
= "\xC3\x85\x73\x74\x72\xC3\xB6\x6D";
146 const char *nfd
= "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D";
147 const char *emoji
= "\xF0\x9F\x8D\xB7";
148 const char *names
[] = { nfc
, nfd
, emoji
};
149 const char *alt
[] = { nfd
, nfc
, NULL
};
150 const char *expected
[] = { nfc
, nfd
, emoji
};
152 bool fs_decompose_unicode
=
153 git_path_does_fs_decompose_unicode(git_repository_path(repo
));
155 retrieve_known_commit(&target
, repo
);
157 if (cl_repo_get_bool(repo
, "core.precomposeunicode"))
159 /* test decomp. because not all Mac filesystems decompose unicode */
160 else if (fs_decompose_unicode
)
163 for (i
= 0; i
< ARRAY_SIZE(names
); ++i
) {
165 cl_git_pass(git_branch_create(
166 &branch
, repo
, names
[i
], target
, 0));
167 cl_git_pass(git_oid_cmp(
168 git_reference_target(branch
), git_commit_id(target
)));
170 cl_git_pass(git_branch_name(&name
, branch
));
171 cl_assert_equal_s(expected
[i
], name
);
172 assert_branch_matches_name(expected
[i
], names
[i
]);
173 if (fs_decompose_unicode
&& alt
[i
])
174 assert_branch_matches_name(expected
[i
], alt
[i
]);
176 cl_git_pass(git_branch_delete(branch
));
177 git_reference_free(branch
);
183 * Verify that we can create a branch with a name that matches the
184 * namespace of a previously delete branch.
186 * git branch level_one/level_two
187 * git branch -D level_one/level_two
188 * git branch level_one
190 * We expect the delete to have deleted the files:
191 * ".git/refs/heads/level_one/level_two"
192 * ".git/logs/refs/heads/level_one/level_two"
193 * It may or may not have deleted the (now empty)
194 * containing directories. To match git.git behavior,
195 * the second create needs to implicilty delete the
196 * directories and create the new files.
197 * "refs/heads/level_one"
198 * "logs/refs/heads/level_one"
200 * We should not fail to create the branch or its
201 * reflog because of an obsolete namespace container
204 void test_refs_branches_create__name_vs_namespace(void)
211 static const struct item item
[] = {
212 { "level_one/level_two", "level_one" },
213 { "a/b/c/d/e", "a/b/c/d" },
214 { "ss/tt/uu/vv/ww", "ss" },
215 /* And one test case that is deeper. */
216 { "xx1/xx2/xx3/xx4", "xx1/xx2/xx3/xx4/xx5/xx6" },
219 const struct item
*p
;
221 retrieve_known_commit(&target
, repo
);
223 for (p
=item
; p
->first
; p
++) {
224 cl_git_pass(git_branch_create(&branch
, repo
, p
->first
, target
, 0));
225 cl_git_pass(git_oid_cmp(git_reference_target(branch
), git_commit_id(target
)));
226 cl_git_pass(git_branch_name(&name
, branch
));
227 cl_assert_equal_s(name
, p
->first
);
229 cl_git_pass(git_branch_delete(branch
));
230 git_reference_free(branch
);
233 cl_git_pass(git_branch_create(&branch
, repo
, p
->second
, target
, 0));
234 git_reference_free(branch
);
240 * We still need to fail if part of the namespace is
243 void test_refs_branches_create__name_vs_namespace_fail(void)
248 const char *first_alternate
;
251 static const struct item item
[] = {
252 { "level_one/level_two", "level_one/alternate", "level_one" },
253 { "a/b/c/d/e", "a/b/c/d/alternate", "a/b/c/d" },
254 { "ss/tt/uu/vv/ww", "ss/alternate", "ss" },
255 { NULL
, NULL
, NULL
},
257 const struct item
*p
;
259 retrieve_known_commit(&target
, repo
);
261 for (p
=item
; p
->first
; p
++) {
262 cl_git_pass(git_branch_create(&branch
, repo
, p
->first
, target
, 0));
263 cl_git_pass(git_oid_cmp(git_reference_target(branch
), git_commit_id(target
)));
264 cl_git_pass(git_branch_name(&name
, branch
));
265 cl_assert_equal_s(name
, p
->first
);
267 cl_git_pass(git_branch_delete(branch
));
268 git_reference_free(branch
);
271 cl_git_pass(git_branch_create(&branch
, repo
, p
->first_alternate
, target
, 0));
272 cl_git_pass(git_oid_cmp(git_reference_target(branch
), git_commit_id(target
)));
273 cl_git_pass(git_branch_name(&name
, branch
));
274 cl_assert_equal_s(name
, p
->first_alternate
);
276 /* we do not delete the alternate. */
277 git_reference_free(branch
);
280 cl_git_fail(git_branch_create(&branch
, repo
, p
->second
, target
, 0));
281 git_reference_free(branch
);