diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | cache.h | 4 | ||||
-rw-r--r-- | init-db.c | 142 | ||||
-rw-r--r-- | templates/Makefile | 19 | ||||
-rw-r--r-- | templates/hooks--post-update | 8 | ||||
-rw-r--r-- | templates/hooks--update | 21 |
6 files changed, 199 insertions, 0 deletions
@@ -39,6 +39,8 @@ CFLAGS+=$(COPTS) -Wall $(DEFINES) prefix=$(HOME) bindir=$(prefix)/bin +etcdir=$(prefix)/etc +etcgitdir=$(etcdir)/git-core # dest= CC?=gcc @@ -144,6 +146,7 @@ endif endif CFLAGS += '-DSHA1_HEADER=$(SHA1_HEADER)' +CFLAGS += '-DDEFAULT_GIT_TEMPLATE_ENVIRONMENT="$(etcgitdir)/templates"' @@ -196,6 +199,7 @@ check: install: $(PROG) $(SCRIPTS) $(INSTALL) -m755 -d $(dest)$(bindir) $(INSTALL) $(PROG) $(SCRIPTS) $(dest)$(bindir) + $(MAKE) -C templates install install-tools: $(MAKE) -C tools install @@ -236,4 +240,5 @@ clean: rm -f git-core-*.tar.gz git-core.spec $(MAKE) -C tools/ clean $(MAKE) -C Documentation/ clean + $(MAKE) -C templates/ clean $(MAKE) -C t/ clean @@ -128,6 +128,10 @@ extern unsigned int active_nr, active_alloc, active_cache_changed; #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY" #define INDEX_ENVIRONMENT "GIT_INDEX_FILE" #define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE" +#define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIRECTORY" +#ifndef DEFAULT_GIT_TEMPLATE_ENVIRONMENT +#define DEFAULT_GIT_TEMPLATE_ENVIRONMENT "/etc/git-core/templates" +#endif extern char *get_object_directory(void); extern char *get_refs_directory(void); @@ -15,6 +15,147 @@ static void safe_create_dir(const char *dir) } } +static int copy_file(const char *dst, const char *src, int mode) +{ + int fdi, fdo; + + mode = (mode & 0111) ? 0777 : 0666; + if ((fdi = open(src, O_RDONLY)) < 0) + return fdi; + if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { + close(fdi); + return fdo; + } + while (1) { + char buf[BUFSIZ]; + ssize_t leni, leno, ofs; + leni = read(fdi, buf, sizeof(buf)); + if (leni < 0) { + error_return: + close(fdo); + close(fdi); + return -1; + } + if (!leni) + break; + ofs = 0; + do { + leno = write(fdo, buf+ofs, leni); + if (leno < 0) + goto error_return; + leni -= leno; + ofs += leno; + } while (0 < leni); + } + close(fdo); + close(fdi); + return 0; +} + +static void copy_templates_1(char *path, int baselen, + char *template, int template_baselen, + DIR *dir) +{ + struct dirent *de; + + /* Note: if ".git/hooks" file exists in the repository being + * re-initialized, /etc/core-git/templates/hooks/update would + * cause git-init-db to fail here. I think this is sane but + * it means that the set of templates we ship by default, along + * with the way the namespace under .git/ is organized, should + * be really carefully chosen. + */ + safe_create_dir(path); + while ((de = readdir(dir)) != NULL) { + struct stat st_git, st_template; + int namelen; + int exists = 0; + + if (de->d_name[0] == '.') + continue; + namelen = strlen(de->d_name); + if ((PATH_MAX <= baselen + namelen) || + (PATH_MAX <= template_baselen + namelen)) + die("insanely long template name %s", de->d_name); + memcpy(path + baselen, de->d_name, namelen+1); + memcpy(template + template_baselen, de->d_name, namelen+1); + if (lstat(path, &st_git)) { + if (errno != ENOENT) + die("cannot stat %s", path); + } + else + exists = 1; + + if (lstat(template, &st_template)) + die("cannot stat template %s", template); + + if (S_ISDIR(st_template.st_mode)) { + DIR *subdir = opendir(template); + int baselen_sub = baselen + namelen; + int template_baselen_sub = template_baselen + namelen; + if (!subdir) + die("cannot opendir %s", template); + path[baselen_sub++] = + template[template_baselen_sub++] = '/'; + path[baselen_sub] = + template[template_baselen_sub] = 0; + copy_templates_1(path, baselen_sub, + template, template_baselen_sub, + subdir); + closedir(subdir); + } + else if (exists) + continue; + else if (S_ISLNK(st_template.st_mode)) { + char lnk[256]; + int len; + len = readlink(template, lnk, sizeof(lnk)); + if (len < 0) + die("cannot readlink %s", template); + if (sizeof(lnk) <= len) + die("insanely long symlink %s", template); + lnk[len] = 0; + if (symlink(lnk, path)) + die("cannot symlink %s %s", lnk, path); + } + else if (S_ISREG(st_template.st_mode)) { + if (copy_file(path, template, st_template.st_mode)) + die("cannot copy %s to %s", template, path); + } + else + error("ignoring template %s", template); + } +} + +static void copy_templates(const char *git_dir) +{ + char path[PATH_MAX]; + char template_path[PATH_MAX]; + char *template_dir; + int len, template_len; + DIR *dir; + + strcpy(path, git_dir); + len = strlen(path); + template_dir = gitenv(TEMPLATE_DIR_ENVIRONMENT); + if (!template_dir) + template_dir = DEFAULT_GIT_TEMPLATE_ENVIRONMENT; + strcpy(template_path, template_dir); + template_len = strlen(template_path); + if (template_path[template_len-1] != '/') { + template_path[template_len++] = '/'; + template_path[template_len] = 0; + } + + dir = opendir(template_path); + if (!dir) + return; + copy_templates_1(path, len, + template_path, template_len, + dir); + closedir(dir); +} + static void create_default_files(const char *git_dir) { unsigned len = strlen(git_dir); @@ -48,6 +189,7 @@ static void create_default_files(const char *git_dir) exit(1); } } + copy_templates(path); } /* diff --git a/templates/Makefile b/templates/Makefile new file mode 100644 index 000000000..12433519e --- /dev/null +++ b/templates/Makefile @@ -0,0 +1,19 @@ +# make + +INSTALL=install +prefix=$(HOME) +etcdir=$(prefix)/etc +etcgitdir=$(etcdir)/git-core +templatedir=$(etcgitdir)/templates +# dest= + +all: +clean: + +install: + $(INSTALL) -d -m755 $(dest)$(templatedir)/hooks/ + $(foreach s,$(wildcard hooks--*),\ + $(INSTALL) -m644 $s \ + $(dest)$(templatedir)/hooks/$(patsubst hooks--%,%,$s);) + $(INSTALL) -d -m755 $(dest)$(templatedir)/info + $(INSTALL) -d -m755 $(dest)$(templatedir)/branches diff --git a/templates/hooks--post-update b/templates/hooks--post-update new file mode 100644 index 000000000..bcba8937b --- /dev/null +++ b/templates/hooks--post-update @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, make this file executable by "chmod +x post-update". + +exec git-update-server-info diff --git a/templates/hooks--update b/templates/hooks--update new file mode 100644 index 000000000..540ade0d5 --- /dev/null +++ b/templates/hooks--update @@ -0,0 +1,21 @@ +#!/bin/sh +# +# An example hook script to mail out commit update information. +# +# To enable this hook: +# (1) change the recipient e-mail address +# (2) make this file executable by "chmod +x update". +# + +recipient="commit-list@mydomain.xz" + +if expr "$2" : '0*$' >/dev/null +then + echo "Created a new ref, with the following commits:" + git-rev-list --pretty "$2" +else + echo "New commits:" + git-rev-list --pretty "$3" "^$2" +fi | +mail -s "Changes to ref $1" "$recipient" +exit 0 |