{"thread":{"id":"1403","subject":"[PATCH] Install sample hooks","startedAt":"2005-08-03T06:23:24Z","lastAt":"2005-08-03T06:23:24Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"6744","messageId":"7vbr4fk083.fsf@assigned-by-dhcp.cox.net","threadId":"1403","inReplyTo":null,"subject":"[PATCH] Install sample hooks","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-03T06:23:24Z","receivedAt":"2005-08-03T06:23:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Josef Weidendorfer made a good suggestion to throw in sample\nhooks, disabled by default, to newly created repositories.  Here\nis a proposed patch.  I will advance it to the master branch if\nI do not hear objections, probably by the end of the week.\n\n------------\nA template mechanism to populate newly initialized repository\nwith default set of files is introduced.  Use it to ship example\nhooks that can be used for update and post update checks, as\nJosef Weidendorfer suggests.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n Makefile                     |    5 +\n cache.h                      |    4 +\n init-db.c                    |  142 ++++++++++++++++++++++++++++++++++++++++++\n templates/Makefile           |   19 ++++++\n templates/hooks--post-update |    8 ++\n templates/hooks--update      |   21 ++++++\n 6 files changed, 199 insertions(+), 0 deletions(-)\n create mode 100644 templates/Makefile\n create mode 100644 templates/hooks--post-update\n create mode 100644 templates/hooks--update\n\na03cd67d2ff5dd0cf43a0be53e6f35e4cb684b8e\ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -39,6 +39,8 @@ CFLAGS+=$(COPTS) -Wall $(DEFINES)\n \n prefix=$(HOME)\n bindir=$(prefix)/bin\n+etcdir=$(prefix)/etc\n+etcgitdir=$(etcdir)/git-core\n # dest=\n \n CC?=gcc\n@@ -143,6 +145,7 @@ endif\n endif\n \n CFLAGS += '-DSHA1_HEADER=$(SHA1_HEADER)'\n+CFLAGS += '-DDEFAULT_GIT_TEMPLATE_ENVIRONMENT=\"$(etcgitdir)/templates\"'\n \n \n \n@@ -195,6 +198,7 @@ check:\n install: $(PROG) $(SCRIPTS)\n \t$(INSTALL) -m755 -d $(dest)$(bindir)\n \t$(INSTALL) $(PROG) $(SCRIPTS) $(dest)$(bindir)\n+\t$(MAKE) -C templates install\n \n install-tools:\n \t$(MAKE) -C tools install\n@@ -235,4 +239,5 @@ clean:\n \trm -f git-core-*.tar.gz git-core.spec\n \t$(MAKE) -C tools/ clean\n \t$(MAKE) -C Documentation/ clean\n+\t$(MAKE) -C templates/ clean\n \t$(MAKE) -C t/ clean\ndiff --git a/cache.h b/cache.h\n--- a/cache.h\n+++ b/cache.h\n@@ -128,6 +128,10 @@ extern unsigned int active_nr, active_al\n #define DB_ENVIRONMENT \"GIT_OBJECT_DIRECTORY\"\n #define INDEX_ENVIRONMENT \"GIT_INDEX_FILE\"\n #define GRAFT_ENVIRONMENT \"GIT_GRAFT_FILE\"\n+#define TEMPLATE_DIR_ENVIRONMENT \"GIT_TEMPLATE_DIRECTORY\"\n+#ifndef DEFAULT_GIT_TEMPLATE_ENVIRONMENT\n+#define DEFAULT_GIT_TEMPLATE_ENVIRONMENT \"/etc/git-core/templates\"\n+#endif\n \n extern char *get_object_directory(void);\n extern char *get_refs_directory(void);\ndiff --git a/init-db.c b/init-db.c\n--- a/init-db.c\n+++ b/init-db.c\n@@ -15,6 +15,147 @@ static void safe_create_dir(const char *\n \t}\n }\n \n+static int copy_file(const char *dst, const char *src, int mode)\n+{\n+\tint fdi, fdo;\n+\n+\tmode = (mode & 0111) ? 0777 : 0666;\n+\tif ((fdi = open(src, O_RDONLY)) < 0)\n+\t\treturn fdi;\n+\tif ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {\n+\t\tclose(fdi);\n+\t\treturn fdo;\n+\t}\n+\twhile (1) {\n+\t\tchar buf[BUFSIZ];\n+\t\tssize_t leni, leno, ofs;\n+\t\tleni = read(fdi, buf, sizeof(buf));\n+\t\tif (leni < 0) {\n+\t\terror_return:\n+\t\t\tclose(fdo);\n+\t\t\tclose(fdi);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (!leni)\n+\t\t\tbreak;\n+\t\tofs = 0;\n+\t\tdo {\n+\t\t\tleno = write(fdo, buf+ofs, leni);\n+\t\t\tif (leno < 0)\n+\t\t\t\tgoto error_return;\n+\t\t\tleni -= leno;\n+\t\t\tofs += leno;\n+\t\t} while (0 < leni);\n+\t}\n+\tclose(fdo);\n+\tclose(fdi);\n+\treturn 0;\n+}\n+\n+static void copy_templates_1(char *path, int baselen,\n+\t\t\t     char *template, int template_baselen,\n+\t\t\t     DIR *dir)\n+{\n+\tstruct dirent *de;\n+\n+\t/* Note: if \".git/hooks\" file exists in the repository being\n+\t * re-initialized, /etc/core-git/templates/hooks/update would\n+\t * cause git-init-db to fail here.  I think this is sane but\n+\t * it means that the set of templates we ship by default, along\n+\t * with the way the namespace under .git/ is organized, should\n+\t * be really carefully chosen.\n+\t */\n+\tsafe_create_dir(path);\n+\twhile ((de = readdir(dir)) != NULL) {\n+\t\tstruct stat st_git, st_template;\n+\t\tint namelen;\n+\t\tint exists = 0;\n+\n+\t\tif (de->d_name[0] == '.')\n+\t\t\tcontinue;\n+\t\tnamelen = strlen(de->d_name);\n+\t\tif ((PATH_MAX <= baselen + namelen) ||\n+\t\t    (PATH_MAX <= template_baselen + namelen))\n+\t\t\tdie(\"insanely long template name %s\", de->d_name);\n+\t\tmemcpy(path + baselen, de->d_name, namelen+1);\n+\t\tmemcpy(template + template_baselen, de->d_name, namelen+1);\n+\t\tif (lstat(path, &st_git)) {\n+\t\t\tif (errno != ENOENT)\n+\t\t\t\tdie(\"cannot stat %s\", path);\n+\t\t}\n+\t\telse\n+\t\t\texists = 1;\n+\n+\t\tif (lstat(template, &st_template))\n+\t\t\tdie(\"cannot stat template %s\", template);\n+\n+\t\tif (S_ISDIR(st_template.st_mode)) {\n+\t\t\tDIR *subdir = opendir(template);\n+\t\t\tint baselen_sub = baselen + namelen;\n+\t\t\tint template_baselen_sub = template_baselen + namelen;\n+\t\t\tif (!subdir)\n+\t\t\t\tdie(\"cannot opendir %s\", template);\n+\t\t\tpath[baselen_sub++] =\n+\t\t\t\ttemplate[template_baselen_sub++] = '/';\n+\t\t\tpath[baselen_sub] =\n+\t\t\t\ttemplate[template_baselen_sub] = 0;\n+\t\t\tcopy_templates_1(path, baselen_sub,\n+\t\t\t\t\t template, template_baselen_sub,\n+\t\t\t\t\t subdir);\n+\t\t\tclosedir(subdir);\n+\t\t}\n+\t\telse if (exists)\n+\t\t\tcontinue;\n+\t\telse if (S_ISLNK(st_template.st_mode)) {\n+\t\t\tchar lnk[256];\n+\t\t\tint len;\n+\t\t\tlen = readlink(template, lnk, sizeof(lnk));\n+\t\t\tif (len < 0)\n+\t\t\t\tdie(\"cannot readlink %s\", template);\n+\t\t\tif (sizeof(lnk) <= len)\n+\t\t\t\tdie(\"insanely long symlink %s\", template);\n+\t\t\tlnk[len] = 0;\n+\t\t\tif (symlink(lnk, path))\n+\t\t\t\tdie(\"cannot symlink %s %s\", lnk, path);\n+\t\t}\n+\t\telse if (S_ISREG(st_template.st_mode)) {\n+\t\t\tif (copy_file(path, template, st_template.st_mode))\n+\t\t\t\tdie(\"cannot copy %s to %s\", template, path);\n+\t\t}\n+\t\telse\n+\t\t\terror(\"ignoring template %s\", template);\n+\t}\n+}\n+\n+static void copy_templates(const char *git_dir)\n+{\n+\tchar path[PATH_MAX];\n+\tchar template_path[PATH_MAX];\n+\tchar *template_dir;\n+\tint len, template_len;\n+\tDIR *dir;\n+\n+\tstrcpy(path, git_dir);\n+\tlen = strlen(path);\n+\ttemplate_dir = gitenv(TEMPLATE_DIR_ENVIRONMENT);\n+\tif (!template_dir)\n+\t\ttemplate_dir = DEFAULT_GIT_TEMPLATE_ENVIRONMENT;\n+\tstrcpy(template_path, template_dir);\n+\ttemplate_len = strlen(template_path);\n+\tif (template_path[template_len-1] != '/') {\n+\t\ttemplate_path[template_len++] = '/';\n+\t\ttemplate_path[template_len] = 0;\n+\t}\n+\n+\tdir = opendir(template_path);\n+\tif (!dir)\n+\t\treturn;\n+\tcopy_templates_1(path, len,\n+\t\t\t template_path, template_len,\n+\t\t\t dir);\n+\tclosedir(dir);\n+}\n+\n static void create_default_files(const char *git_dir)\n {\n \tunsigned len = strlen(git_dir);\n@@ -48,6 +189,7 @@ static void create_default_files(const c\n \t\t\texit(1);\n \t\t}\n \t}\n+\tcopy_templates(path);\n }\n \n /*\ndiff --git a/templates/Makefile b/templates/Makefile\nnew file mode 100644\n--- /dev/null\n+++ b/templates/Makefile\n@@ -0,0 +1,19 @@\n+# make\n+\n+INSTALL=install\n+prefix=$(HOME)\n+etcdir=$(prefix)/etc\n+etcgitdir=$(etcdir)/git-core\n+templatedir=$(etcgitdir)/templates\n+# dest=\n+\n+all:\n+clean:\n+\n+install:\n+\t$(INSTALL) -d -m755 $(dest)$(templatedir)/hooks/\n+\t$(foreach s,$(wildcard hooks--*),\\\n+\t\t$(INSTALL) -m644 $s \\\n+\t\t$(dest)$(templatedir)/hooks/$(patsubst hooks--%,%,$s);)\n+\t$(INSTALL) -d -m755 $(dest)$(templatedir)/info\n+\t$(INSTALL) -d -m755 $(dest)$(templatedir)/branches\ndiff --git a/templates/hooks--post-update b/templates/hooks--post-update\nnew file mode 100644\n--- /dev/null\n+++ b/templates/hooks--post-update\n@@ -0,0 +1,8 @@\n+#!/bin/sh\n+#\n+# An example hook script to prepare a packed repository for use over\n+# dumb transports.\n+#\n+# To enable this hook, make this file executable by \"chmod +x post-update\".\n+\n+exec git-update-server-info\ndiff --git a/templates/hooks--update b/templates/hooks--update\nnew file mode 100644\n--- /dev/null\n+++ b/templates/hooks--update\n@@ -0,0 +1,21 @@\n+#!/bin/sh\n+#\n+# An example hook script to mail out commit update information.\n+#\n+# To enable this hook:\n+# (1) change the recipient e-mail address\n+# (2) make this file executable by \"chmod +x update\".\n+#\n+\n+recipient=\"commit-list@mydomain.xz\"\n+\n+if expr \"$2\" : '0*$' >/dev/null\n+then\n+\techo \"Created a new ref, with the following commits:\"\n+\tgit-rev-list --pretty \"$2\"\n+else\n+\techo \"New commits:\"\n+\tgit-rev-list --pretty \"$3\" \"^$2\"\n+fi |\n+mail -s \"Changes to ref $1\" \"$recipient\"\n+exit 0\n"}]}