From dc34da6e8140c034c3673d0f82c896be9d66ef1c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 8 May 2012 13:50:40 -0700 Subject: [PATCH 1/2] Improve repo initialization to be more like git This adds a bunch of template files to the initialization for hooks, info/exclude, and description. This makes our initialized repo look more like core gits. --- src/repository.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/src/repository.c b/src/repository.c index 886de5806..9031c5956 100644 --- a/src/repository.c +++ b/src/repository.c @@ -684,6 +684,62 @@ static int repo_init_config(const char *git_dir, int is_bare) return 0; } +#define GIT_HOOKS_DIR "hooks/" +#define GIT_HOOKS_DIR_MODE 0755 + +#define GIT_HOOKS_README_FILE GIT_HOOKS_DIR "README.sample" +#define GIT_HOOKS_README_MODE 0755 +#define GIT_HOOKS_README_CONTENT \ +"#!/bin/sh\n"\ +"#\n"\ +"# Place appropriately named executable hook scripts into this directory\n"\ +"# to intercept various actions that git takes. See `git help hooks` for\n"\ +"# more information.\n" + +#define GIT_INFO_DIR "info/" +#define GIT_INFO_DIR_MODE 0755 + +#define GIT_INFO_EXCLUDE_FILE GIT_INFO_DIR "exclude" +#define GIT_INFO_EXCLUDE_MODE 0644 +#define GIT_INFO_EXCLUDE_CONTENT \ +"# File patterns to ignore; see `git help ignore` for more information.\n"\ +"# Lines that start with '#' are comments.\n" + +#define GIT_DESC_FILE "description" +#define GIT_DESC_MODE 0644 +#define GIT_DESC_CONTENT "Unnamed repository; edit this file 'description' to name the repository.\n" + +static int repo_write_template( + const char *git_dir, const char *file, mode_t mode, const char *content) +{ + git_buf path = GIT_BUF_INIT; + int fd; + + if (git_buf_joinpath(&path, git_dir, file) < 0) + return -1; + + fd = p_open(git_buf_cstr(&path), O_WRONLY | O_CREAT | O_EXCL, mode); + if (fd < 0) { + git_buf_free(&path); + if (errno == EEXIST) + return 0; + goto fail; + } + + if (p_write(fd, content, strlen(content)) < 0) + goto fail; + + p_close(fd); + + return 0; + +fail: + git_buf_free(&path); + giterr_set(GITERR_OS, + "Failed to initialize repository with template '%s'", file); + return -1; +} + static int repo_init_structure(const char *git_dir, int is_bare) { int i; @@ -692,8 +748,16 @@ static int repo_init_structure(const char *git_dir, int is_bare) { GIT_OBJECTS_PACK_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/pack/' */ { GIT_REFS_HEADS_DIR, GIT_REFS_DIR_MODE }, /* '/refs/heads/' */ { GIT_REFS_TAGS_DIR, GIT_REFS_DIR_MODE }, /* '/refs/tags/' */ + { GIT_HOOKS_DIR, GIT_HOOKS_DIR_MODE }, /* '/hooks/' */ + { GIT_INFO_DIR, GIT_INFO_DIR_MODE }, /* '/info/' */ { NULL, 0 } }; + struct { const char *file; mode_t mode; const char *content; } tmpl[] = { + { GIT_DESC_FILE, GIT_DESC_MODE, GIT_DESC_CONTENT }, + { GIT_HOOKS_README_FILE, GIT_HOOKS_README_MODE, GIT_HOOKS_README_CONTENT }, + { GIT_INFO_EXCLUDE_FILE, GIT_INFO_EXCLUDE_MODE, GIT_INFO_EXCLUDE_CONTENT }, + { NULL, 0, NULL } + }; /* Make the base directory */ if (git_futils_mkdir_r(git_dir, NULL, is_bare ? GIT_BARE_DIR_MODE : GIT_DIR_MODE) < 0) @@ -716,7 +780,13 @@ static int repo_init_structure(const char *git_dir, int is_bare) return -1; } - /* TODO: what's left? templates? */ + /* Make template files as needed */ + for (i = 0; tmpl[i].file != NULL; ++i) { + if (repo_write_template( + git_dir, tmpl[i].file, tmpl[i].mode, tmpl[i].content) < 0) + return -1; + } + return 0; } From db62807215cbe26b83a354954b7433aa5d90c149 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 11 May 2012 12:16:19 -0700 Subject: [PATCH 2/2] Fixed leaks and added tests --- src/repository.c | 31 ++++++++++++++----------------- tests-clar/repo/init.c | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/repository.c b/src/repository.c index 9031c5956..c5eed531b 100644 --- a/src/repository.c +++ b/src/repository.c @@ -713,31 +713,28 @@ static int repo_write_template( const char *git_dir, const char *file, mode_t mode, const char *content) { git_buf path = GIT_BUF_INIT; - int fd; + int fd, error = 0; if (git_buf_joinpath(&path, git_dir, file) < 0) return -1; fd = p_open(git_buf_cstr(&path), O_WRONLY | O_CREAT | O_EXCL, mode); - if (fd < 0) { - git_buf_free(&path); - if (errno == EEXIST) - return 0; - goto fail; + + if (fd >= 0) { + error = p_write(fd, content, strlen(content)); + + p_close(fd); } + else if (errno != EEXIST) + error = fd; - if (p_write(fd, content, strlen(content)) < 0) - goto fail; - - p_close(fd); - - return 0; - -fail: git_buf_free(&path); - giterr_set(GITERR_OS, - "Failed to initialize repository with template '%s'", file); - return -1; + + if (error) + giterr_set(GITERR_OS, + "Failed to initialize repository with template '%s'", file); + + return error; } static int repo_init_structure(const char *git_dir, int is_bare) diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index a12a2c2fb..7f16b5b7c 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -141,3 +141,27 @@ void test_repo_init__reinit_too_recent_bare_repo(void) cl_fixture_cleanup("reinit.git"); } + +void test_repo_init__additional_templates(void) +{ + git_buf path = GIT_BUF_INIT; + + cl_set_cleanup(&cleanup_repository, "tester"); + + ensure_repository_init("tester", 0, "tester/.git/", "tester/"); + + cl_git_pass( + git_buf_joinpath(&path, git_repository_path(_repo), "description")); + cl_assert(git_path_isfile(git_buf_cstr(&path))); + + cl_git_pass( + git_buf_joinpath(&path, git_repository_path(_repo), "info/exclude")); + cl_assert(git_path_isfile(git_buf_cstr(&path))); + + cl_git_pass( + git_buf_joinpath(&path, git_repository_path(_repo), "hooks")); + cl_assert(git_path_isdir(git_buf_cstr(&path))); + /* won't confirm specific contents of hooks dir since it may vary */ + + git_buf_free(&path); +}