Skip to content

Commit 9d46f16

Browse files
committed
repository: do not initialize HEAD if it's provided by templates
When using templates to initialize a git repository, then git-init(1) will copy over all contents of the template directory. These will be preferred over the default ones created by git-init(1). While we mostly do the same, there is the exception of "HEAD". While we do copy over the template's HEAD file, afterwards we'll immediately re-initialize its contents with either the default "ref: refs/origin/master" or the init option's `initial_head` field. Let's fix the inconsistency with upstream git-init(1) by not overwriting the template HEAD, but only if the user hasn't set `opts.initial_head`. If the `initial_head` field has been supplied, we should use that indifferent from whether the template contained a HEAD file or not. Add tests to verify we correctly use the template directory's HEAD file and that `initial_head` overrides the template.
1 parent f3134a8 commit 9d46f16

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

src/repository.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2056,7 +2056,8 @@ int git_repository_init_ext(
20562056
const char *given_repo,
20572057
git_repository_init_options *opts)
20582058
{
2059-
git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT, common_path = GIT_BUF_INIT;
2059+
git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT,
2060+
common_path = GIT_BUF_INIT, head_path = GIT_BUF_INIT;
20602061
const char *wd;
20612062
int error;
20622063

@@ -2086,6 +2087,15 @@ int git_repository_init_ext(
20862087
} else {
20872088
if ((error = repo_init_structure(repo_path.ptr, wd, opts)) < 0 ||
20882089
(error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0 ||
2090+
(error = git_buf_joinpath(&head_path, repo_path.ptr, GIT_HEAD_FILE)) < 0)
2091+
goto out;
2092+
2093+
/*
2094+
* Only set the new HEAD if the file does not exist already via
2095+
* a template or if the caller has explicitly supplied an
2096+
* initial HEAD value.
2097+
*/
2098+
if ((!git_path_exists(head_path.ptr) || opts->initial_head) &&
20892099
(error = git_repository_create_head(repo_path.ptr, opts->initial_head)) < 0)
20902100
goto out;
20912101
}
@@ -2098,6 +2108,7 @@ int git_repository_init_ext(
20982108
goto out;
20992109

21002110
out:
2111+
git_buf_dispose(&head_path);
21012112
git_buf_dispose(&common_path);
21022113
git_buf_dispose(&repo_path);
21032114
git_buf_dispose(&wd_path);

tests/repo/template.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,41 @@ void test_repo_template__extended_with_template_and_shared_mode(void)
249249
validate_templates(_repo, "template");
250250
}
251251

252+
void test_repo_template__templated_head_is_used(void)
253+
{
254+
git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
255+
git_buf head = GIT_BUF_INIT;
256+
257+
opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
258+
259+
setup_templates("template", true);
260+
cl_git_mkfile("template/HEAD", "foobar\n");
261+
setup_repo("repo", &opts);
262+
263+
cl_git_pass(git_futils_readbuffer(&head, "repo/.git/HEAD"));
264+
cl_assert_equal_s("foobar\n", head.ptr);
265+
266+
git_buf_dispose(&head);
267+
}
268+
269+
void test_repo_template__initial_head_option_overrides_template_head(void)
270+
{
271+
git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
272+
git_buf head = GIT_BUF_INIT;
273+
274+
opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
275+
opts.initial_head = "manual";
276+
277+
setup_templates("template", true);
278+
cl_git_mkfile("template/HEAD", "foobar\n");
279+
setup_repo("repo", &opts);
280+
281+
cl_git_pass(git_futils_readbuffer(&head, "repo/.git/HEAD"));
282+
cl_assert_equal_s("ref: refs/heads/manual\n", head.ptr);
283+
284+
git_buf_dispose(&head);
285+
}
286+
252287
void test_repo_template__empty_template_path(void)
253288
{
254289
git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;

0 commit comments

Comments
 (0)