summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2019-07-20 11:02:30 +0100
committerGitHub <noreply@github.com>2019-07-20 11:02:30 +0100
commit964c1c60011322a16a593f034a8466614f183742 (patch)
tree2bed73f99c71e06c3b8e6d2ae9a4792b3cf426bb
parent3424c21057441e9d592d1edfb5744c56cc29a30b (diff)
parent9d46f1675989c20663de80c003256bc586496771 (diff)
downloadlibgit2-964c1c60011322a16a593f034a8466614f183742.tar.gz
Merge pull request #5176 from pks-t/pks/repo-template-head
repository: do not initialize HEAD if it's provided by templates
-rw-r--r--src/repository.c72
-rw-r--r--tests/repo/init.c269
-rw-r--r--tests/repo/template.c295
3 files changed, 335 insertions, 301 deletions
diff --git a/src/repository.c b/src/repository.c
index d8eb4ba07..002e84f91 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1360,10 +1360,11 @@ int git_repository_create_head(const char *git_dir, const char *ref_name)
git_buf ref_path = GIT_BUF_INIT;
git_filebuf ref = GIT_FILEBUF_INIT;
const char *fmt;
+ int error;
- if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 ||
- git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE) < 0)
- goto fail;
+ if ((error = git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE)) < 0 ||
+ (error = git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE)) < 0)
+ goto out;
if (!ref_name)
ref_name = GIT_BRANCH_MASTER;
@@ -1373,17 +1374,14 @@ int git_repository_create_head(const char *git_dir, const char *ref_name)
else
fmt = "ref: " GIT_REFS_HEADS_DIR "%s\n";
- if (git_filebuf_printf(&ref, fmt, ref_name) < 0 ||
- git_filebuf_commit(&ref) < 0)
- goto fail;
-
- git_buf_dispose(&ref_path);
- return 0;
+ if ((error = git_filebuf_printf(&ref, fmt, ref_name)) < 0 ||
+ (error = git_filebuf_commit(&ref)) < 0)
+ goto out;
-fail:
+out:
git_buf_dispose(&ref_path);
git_filebuf_cleanup(&ref);
- return -1;
+ return error;
}
static bool is_chmod_supported(const char *file_path)
@@ -2058,53 +2056,59 @@ int git_repository_init_ext(
const char *given_repo,
git_repository_init_options *opts)
{
- int error;
git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT,
- common_path = GIT_BUF_INIT;
+ common_path = GIT_BUF_INIT, head_path = GIT_BUF_INIT;
const char *wd;
+ int error;
assert(out && given_repo && opts);
GIT_ERROR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options");
- error = repo_init_directories(&repo_path, &wd_path, given_repo, opts);
- if (error < 0)
- goto cleanup;
+ if ((error = repo_init_directories(&repo_path, &wd_path, given_repo, opts)) < 0)
+ goto out;
wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_buf_cstr(&wd_path);
- if (valid_repository_path(&repo_path, &common_path)) {
+ if (valid_repository_path(&repo_path, &common_path)) {
if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) {
git_error_set(GIT_ERROR_REPOSITORY,
"attempt to reinitialize '%s'", given_repo);
error = GIT_EEXISTS;
- goto cleanup;
+ goto out;
}
opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT;
- error = repo_init_config(
- repo_path.ptr, wd, opts->flags, opts->mode);
+ if ((error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0)
+ goto out;
/* TODO: reinitialize the templates */
+ } else {
+ if ((error = repo_init_structure(repo_path.ptr, wd, opts)) < 0 ||
+ (error = repo_init_config(repo_path.ptr, wd, opts->flags, opts->mode)) < 0 ||
+ (error = git_buf_joinpath(&head_path, repo_path.ptr, GIT_HEAD_FILE)) < 0)
+ goto out;
+
+ /*
+ * Only set the new HEAD if the file does not exist already via
+ * a template or if the caller has explicitly supplied an
+ * initial HEAD value.
+ */
+ if ((!git_path_exists(head_path.ptr) || opts->initial_head) &&
+ (error = git_repository_create_head(repo_path.ptr, opts->initial_head)) < 0)
+ goto out;
}
- else {
- if (!(error = repo_init_structure(
- repo_path.ptr, wd, opts)) &&
- !(error = repo_init_config(
- repo_path.ptr, wd, opts->flags, opts->mode)))
- error = git_repository_create_head(
- repo_path.ptr, opts->initial_head);
- }
- if (error < 0)
- goto cleanup;
- error = git_repository_open(out, repo_path.ptr);
+ if ((error = git_repository_open(out, repo_path.ptr)) < 0)
+ goto out;
- if (!error && opts->origin_url)
- error = repo_init_create_origin(*out, opts->origin_url);
+ if (opts->origin_url &&
+ (error = repo_init_create_origin(*out, opts->origin_url)) < 0)
+ goto out;
-cleanup:
+out:
+ git_buf_dispose(&head_path);
git_buf_dispose(&common_path);
git_buf_dispose(&repo_path);
git_buf_dispose(&wd_path);
diff --git a/tests/repo/init.c b/tests/repo/init.c
index f2155b4cd..9879ef1f7 100644
--- a/tests/repo/init.c
+++ b/tests/repo/init.c
@@ -13,20 +13,13 @@ enum repo_mode {
static git_repository *_repo = NULL;
static git_buf _global_path = GIT_BUF_INIT;
-static mode_t g_umask = 0;
void test_repo_init__initialize(void)
{
_repo = NULL;
- /* load umask if not already loaded */
- if (!g_umask) {
- g_umask = p_umask(022);
- (void)p_umask(g_umask);
- }
-
- git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
- &_global_path);
+ git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
+ &_global_path);
}
void test_repo_init__cleanup(void)
@@ -380,17 +373,6 @@ void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void)
assert_config_entry_on_init_bytype("core.logallrefupdates", true, false);
}
-void test_repo_init__empty_template_path(void)
-{
- git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
- opts.template_path = "";
-
- cl_git_pass(git_futils_mkdir("foo", 0755, 0));
- cl_git_pass(git_repository_init_ext(&_repo, "foo", &opts));
-
- cleanup_repository("foo");
-}
-
void test_repo_init__extended_0(void)
{
git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
@@ -524,253 +506,6 @@ void test_repo_init__relative_gitdir_2(void)
cleanup_repository("root");
}
-#define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177)
-
-static void assert_hooks_match(
- const char *template_dir,
- const char *repo_dir,
- const char *hook_path,
- bool core_filemode)
-{
- git_buf expected = GIT_BUF_INIT;
- git_buf actual = GIT_BUF_INIT;
- struct stat expected_st, st;
-
- cl_git_pass(git_buf_joinpath(&expected, template_dir, hook_path));
- cl_git_pass(git_path_lstat(expected.ptr, &expected_st));
-
- cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path));
- cl_git_pass(git_path_lstat(actual.ptr, &st));
-
- cl_assert(expected_st.st_size == st.st_size);
-
- if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) {
- mode_t expected_mode =
- GIT_MODE_TYPE(expected_st.st_mode) |
- (GIT_PERMS_FOR_WRITE(expected_st.st_mode) & ~g_umask);
-
- if (!core_filemode) {
- CLEAR_FOR_CORE_FILEMODE(expected_mode);
- CLEAR_FOR_CORE_FILEMODE(st.st_mode);
- }
-
- cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o");
- }
-
- git_buf_dispose(&expected);
- git_buf_dispose(&actual);
-}
-
-static void assert_mode_seems_okay(
- const char *base, const char *path,
- git_filemode_t expect_mode, bool expect_setgid, bool core_filemode)
-{
- git_buf full = GIT_BUF_INIT;
- struct stat st;
-
- cl_git_pass(git_buf_joinpath(&full, base, path));
- cl_git_pass(git_path_lstat(full.ptr, &st));
- git_buf_dispose(&full);
-
- if (!core_filemode) {
- CLEAR_FOR_CORE_FILEMODE(expect_mode);
- CLEAR_FOR_CORE_FILEMODE(st.st_mode);
- expect_setgid = false;
- }
-
- if (S_ISGID != 0)
- cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0);
-
- cl_assert_equal_b(
- GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode));
-
- cl_assert_equal_i_fmt(
- GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o");
-}
-
-static const char *template_sandbox(const char *name)
-{
- git_buf hooks_path = GIT_BUF_INIT, link_path = GIT_BUF_INIT,
- dotfile_path = GIT_BUF_INIT;
- const char *path = cl_fixture(name);
-
- cl_fixture_sandbox(name);
-
- /* create a symlink from link.sample to update.sample if the filesystem
- * supports it.
- */
-
- cl_git_pass(git_buf_joinpath(&hooks_path, name, "hooks"));
- cl_git_pass(git_buf_joinpath(&link_path, hooks_path.ptr, "link.sample"));
-
-#ifdef GIT_WIN32
- cl_git_mkfile(link_path.ptr, "#!/bin/sh\necho hello, world\n");
-#else
- cl_must_pass(symlink("update.sample", link_path.ptr));
-#endif
-
- /* create a file starting with a dot */
- cl_git_pass(git_buf_joinpath(&dotfile_path, hooks_path.ptr, ".dotfile"));
- cl_git_mkfile(dotfile_path.ptr, "something\n");
- git_buf_dispose(&dotfile_path);
-
- git_buf_dispose(&dotfile_path);
- git_buf_dispose(&link_path);
- git_buf_dispose(&hooks_path);
-
- return path;
-}
-
-static void configure_templatedir(const char *template_path)
-{
- create_tmp_global_config("tmp_global_path", "init.templatedir", template_path);
-}
-
-static void validate_templates(git_repository *repo, const char *template_path)
-{
- git_buf template_description = GIT_BUF_INIT;
- git_buf repo_description = GIT_BUF_INIT;
- git_buf expected = GIT_BUF_INIT;
- git_buf actual = GIT_BUF_INIT;
- int filemode;
-
- cl_git_pass(git_buf_joinpath(&template_description, template_path,
- "description"));
- cl_git_pass(git_buf_joinpath(&repo_description, git_repository_path(repo),
- "description"));
-
- cl_git_pass(git_futils_readbuffer(&expected, template_description.ptr));
- cl_git_pass(git_futils_readbuffer(&actual, repo_description.ptr));
-
- cl_assert_equal_s(expected.ptr, actual.ptr);
-
- filemode = cl_repo_get_bool(repo, "core.filemode");
-
- assert_hooks_match(
- template_path, git_repository_path(repo),
- "hooks/update.sample", filemode);
-
- assert_hooks_match(
- template_path, git_repository_path(repo),
- "hooks/link.sample", filemode);
-
- assert_hooks_match(
- template_path, git_repository_path(repo),
- "hooks/.dotfile", filemode);
-
- git_buf_dispose(&expected);
- git_buf_dispose(&actual);
- git_buf_dispose(&repo_description);
- git_buf_dispose(&template_description);
-}
-
-void test_repo_init__external_templates_specified_in_options(void)
-{
- git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
-
- cl_set_cleanup(&cleanup_repository, "templated.git");
- template_sandbox("template");
-
- opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE |
- GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
- opts.template_path = "template";
-
- cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts));
-
- cl_assert(git_repository_is_bare(_repo));
-
- cl_assert(!git__suffixcmp(git_repository_path(_repo), "/templated.git/"));
-
- validate_templates(_repo, "template");
- cl_fixture_cleanup("template");
-}
-
-void test_repo_init__external_templates_specified_in_config(void)
-{
- git_buf template_path = GIT_BUF_INIT;
-
- git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
-
- cl_set_cleanup(&cleanup_repository, "templated.git");
- template_sandbox("template");
-
- cl_git_pass(git_buf_joinpath(&template_path, clar_sandbox_path(),
- "template"));
-
- configure_templatedir(template_path.ptr);
-
- opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE |
- GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
-
- cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts));
-
- validate_templates(_repo, "template");
- cl_fixture_cleanup("template");
-
- git_buf_dispose(&template_path);
-}
-
-void test_repo_init__external_templates_with_leading_dot(void)
-{
- git_buf template_path = GIT_BUF_INIT;
-
- git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
-
- cl_set_cleanup(&cleanup_repository, "templated.git");
- template_sandbox("template");
-
- cl_must_pass(p_rename("template", ".template_with_leading_dot"));
-
- cl_git_pass(git_buf_joinpath(&template_path, clar_sandbox_path(),
- ".template_with_leading_dot"));
-
- configure_templatedir(template_path.ptr);
-
- opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE |
- GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
-
- cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts));
-
- validate_templates(_repo, ".template_with_leading_dot");
- cl_fixture_cleanup(".template_with_leading_dot");
-
- git_buf_dispose(&template_path);
-}
-
-void test_repo_init__extended_with_template_and_shared_mode(void)
-{
- git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
- int filemode = true;
- const char *repo_path = NULL;
-
- cl_set_cleanup(&cleanup_repository, "init_shared_from_tpl");
- template_sandbox("template");
-
- opts.flags = GIT_REPOSITORY_INIT_MKPATH |
- GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
- opts.template_path = "template";
- opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP;
-
- cl_git_pass(git_repository_init_ext(&_repo, "init_shared_from_tpl", &opts));
-
- cl_assert(!git_repository_is_bare(_repo));
- cl_assert(!git__suffixcmp(git_repository_path(_repo), "/init_shared_from_tpl/.git/"));
-
- filemode = cl_repo_get_bool(_repo, "core.filemode");
-
- repo_path = git_repository_path(_repo);
- assert_mode_seems_okay(repo_path, "hooks",
- GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode);
- assert_mode_seems_okay(repo_path, "info",
- GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode);
- assert_mode_seems_okay(repo_path, "description",
- GIT_FILEMODE_BLOB, false, filemode);
-
- validate_templates(_repo, "template");
-
- cl_fixture_cleanup("template");
-}
-
void test_repo_init__can_reinit_an_initialized_repository(void)
{
git_repository *reinit;
diff --git a/tests/repo/template.c b/tests/repo/template.c
new file mode 100644
index 000000000..7ccd93521
--- /dev/null
+++ b/tests/repo/template.c
@@ -0,0 +1,295 @@
+#include "clar_libgit2.h"
+
+#include "fileops.h"
+#include "repo/repo_helpers.h"
+
+#define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177)
+
+static git_repository *_repo = NULL;
+static mode_t g_umask = 0;
+static git_buf _global_path = GIT_BUF_INIT;
+
+static const char *fixture_repo;
+static const char *fixture_templates;
+
+void test_repo_template__initialize(void)
+{
+ _repo = NULL;
+
+ /* load umask if not already loaded */
+ if (!g_umask) {
+ g_umask = p_umask(022);
+ (void)p_umask(g_umask);
+ }
+}
+
+void test_repo_template__cleanup(void)
+{
+ git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
+ _global_path.ptr);
+ git_buf_dispose(&_global_path);
+
+ cl_fixture_cleanup("tmp_global_path");
+
+ if (fixture_repo) {
+ cl_fixture_cleanup(fixture_repo);
+ fixture_repo = NULL;
+ }
+
+ if (fixture_templates) {
+ cl_fixture_cleanup(fixture_templates);
+ fixture_templates = NULL;
+ }
+
+ git_repository_free(_repo);
+ _repo = NULL;
+}
+
+static void assert_hooks_match(
+ const char *template_dir,
+ const char *repo_dir,
+ const char *hook_path,
+ bool core_filemode)
+{
+ git_buf expected = GIT_BUF_INIT;
+ git_buf actual = GIT_BUF_INIT;
+ struct stat expected_st, st;
+
+ cl_git_pass(git_buf_joinpath(&expected, template_dir, hook_path));
+ cl_git_pass(git_path_lstat(expected.ptr, &expected_st));
+
+ cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path));
+ cl_git_pass(git_path_lstat(actual.ptr, &st));
+
+ cl_assert(expected_st.st_size == st.st_size);
+
+ if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) {
+ mode_t expected_mode =
+ GIT_MODE_TYPE(expected_st.st_mode) |
+ (GIT_PERMS_FOR_WRITE(expected_st.st_mode) & ~g_umask);
+
+ if (!core_filemode) {
+ CLEAR_FOR_CORE_FILEMODE(expected_mode);
+ CLEAR_FOR_CORE_FILEMODE(st.st_mode);
+ }
+
+ cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o");
+ }
+
+ git_buf_dispose(&expected);
+ git_buf_dispose(&actual);
+}
+
+static void assert_mode_seems_okay(
+ const char *base, const char *path,
+ git_filemode_t expect_mode, bool expect_setgid, bool core_filemode)
+{
+ git_buf full = GIT_BUF_INIT;
+ struct stat st;
+
+ cl_git_pass(git_buf_joinpath(&full, base, path));
+ cl_git_pass(git_path_lstat(full.ptr, &st));
+ git_buf_dispose(&full);
+
+ if (!core_filemode) {
+ CLEAR_FOR_CORE_FILEMODE(expect_mode);
+ CLEAR_FOR_CORE_FILEMODE(st.st_mode);
+ expect_setgid = false;
+ }
+
+ if (S_ISGID != 0)
+ cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0);
+
+ cl_assert_equal_b(
+ GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode));
+
+ cl_assert_equal_i_fmt(
+ GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o");
+}
+
+static void setup_repo(const char *name, git_repository_init_options *opts)
+{
+ cl_git_pass(git_repository_init_ext(&_repo, name, opts));
+ fixture_repo = name;
+}
+
+static void setup_templates(const char *name, bool setup_globally)
+{
+ git_buf path = GIT_BUF_INIT;
+
+ cl_fixture_sandbox("template");
+ if (strcmp(name, "template"))
+ cl_must_pass(p_rename("template", name));
+
+ fixture_templates = name;
+
+ /*
+ * Create a symlink from link.sample to update.sample if the filesystem
+ * supports it.
+ */
+ cl_git_pass(git_buf_join3(&path, '/', name, "hooks", "link.sample"));
+#ifdef GIT_WIN32
+ cl_git_mkfile(path.ptr, "#!/bin/sh\necho hello, world\n");
+#else
+ cl_must_pass(p_symlink("update.sample", path.ptr));
+#endif
+
+ git_buf_clear(&path);
+
+ /* Create a file starting with a dot */
+ cl_git_pass(git_buf_join3(&path, '/', name, "hooks", ".dotfile"));
+ cl_git_mkfile(path.ptr, "something\n");
+
+ git_buf_clear(&path);
+
+ if (setup_globally) {
+ cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), name));
+ create_tmp_global_config("tmp_global_path", "init.templatedir", path.ptr);
+ }
+
+ git_buf_dispose(&path);
+}
+
+static void validate_templates(git_repository *repo, const char *template_path)
+{
+ git_buf path = GIT_BUF_INIT, expected = GIT_BUF_INIT, actual = GIT_BUF_INIT;
+ int filemode;
+
+ cl_git_pass(git_buf_joinpath(&path, template_path, "description"));
+ cl_git_pass(git_futils_readbuffer(&expected, path.ptr));
+
+ git_buf_clear(&path);
+
+ cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "description"));
+ cl_git_pass(git_futils_readbuffer(&actual, path.ptr));
+
+ cl_assert_equal_s(expected.ptr, actual.ptr);
+
+ filemode = cl_repo_get_bool(repo, "core.filemode");
+
+ assert_hooks_match(
+ template_path, git_repository_path(repo),
+ "hooks/update.sample", filemode);
+ assert_hooks_match(
+ template_path, git_repository_path(repo),
+ "hooks/link.sample", filemode);
+ assert_hooks_match(
+ template_path, git_repository_path(repo),
+ "hooks/.dotfile", filemode);
+
+ git_buf_dispose(&expected);
+ git_buf_dispose(&actual);
+ git_buf_dispose(&path);
+}
+
+void test_repo_template__external_templates_specified_in_options(void)
+{
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+
+ opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE |
+ GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+ opts.template_path = "template";
+
+ setup_templates("template", false);
+ setup_repo("templated.git", &opts);
+
+ validate_templates(_repo, "template");
+}
+
+void test_repo_template__external_templates_specified_in_config(void)
+{
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+
+ opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE |
+ GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+
+ setup_templates("template", true);
+ setup_repo("templated.git", &opts);
+
+ validate_templates(_repo, "template");
+}
+
+void test_repo_template__external_templates_with_leading_dot(void)
+{
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+
+ opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE |
+ GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+
+ setup_templates(".template_with_leading_dot", true);
+ setup_repo("templated.git", &opts);
+
+ validate_templates(_repo, ".template_with_leading_dot");
+}
+
+void test_repo_template__extended_with_template_and_shared_mode(void)
+{
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+ const char *repo_path;
+ int filemode;
+
+ opts.flags = GIT_REPOSITORY_INIT_MKPATH |
+ GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+ opts.template_path = "template";
+ opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP;
+
+ setup_templates("template", false);
+ setup_repo("init_shared_from_tpl", &opts);
+
+ filemode = cl_repo_get_bool(_repo, "core.filemode");
+
+ repo_path = git_repository_path(_repo);
+ assert_mode_seems_okay(repo_path, "hooks",
+ GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode);
+ assert_mode_seems_okay(repo_path, "info",
+ GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode);
+ assert_mode_seems_okay(repo_path, "description",
+ GIT_FILEMODE_BLOB, false, filemode);
+
+ validate_templates(_repo, "template");
+}
+
+void test_repo_template__templated_head_is_used(void)
+{
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+ git_buf head = GIT_BUF_INIT;
+
+ opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+
+ setup_templates("template", true);
+ cl_git_mkfile("template/HEAD", "foobar\n");
+ setup_repo("repo", &opts);
+
+ cl_git_pass(git_futils_readbuffer(&head, "repo/.git/HEAD"));
+ cl_assert_equal_s("foobar\n", head.ptr);
+
+ git_buf_dispose(&head);
+}
+
+void test_repo_template__initial_head_option_overrides_template_head(void)
+{
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+ git_buf head = GIT_BUF_INIT;
+
+ opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+ opts.initial_head = "manual";
+
+ setup_templates("template", true);
+ cl_git_mkfile("template/HEAD", "foobar\n");
+ setup_repo("repo", &opts);
+
+ cl_git_pass(git_futils_readbuffer(&head, "repo/.git/HEAD"));
+ cl_assert_equal_s("ref: refs/heads/manual\n", head.ptr);
+
+ git_buf_dispose(&head);
+}
+
+void test_repo_template__empty_template_path(void)
+{
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+
+ opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
+ opts.template_path = "";
+
+ setup_repo("foo", &opts);
+}