Skip to content

Commit 8d5afef

Browse files
author
Junio C Hamano
committed
Install sample hooks
A template mechanism to populate newly initialized repository with default set of files is introduced. Use it to ship example hooks that can be used for update and post update checks, as Josef Weidendorfer suggests. Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent ee63914 commit 8d5afef

File tree

6 files changed

+199
-0
lines changed

6 files changed

+199
-0
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ CFLAGS+=$(COPTS) -Wall $(DEFINES)
3939

4040
prefix=$(HOME)
4141
bindir=$(prefix)/bin
42+
etcdir=$(prefix)/etc
43+
etcgitdir=$(etcdir)/git-core
4244
# dest=
4345

4446
CC?=gcc
@@ -144,6 +146,7 @@ endif
144146
endif
145147

146148
CFLAGS += '-DSHA1_HEADER=$(SHA1_HEADER)'
149+
CFLAGS += '-DDEFAULT_GIT_TEMPLATE_ENVIRONMENT="$(etcgitdir)/templates"'
147150

148151

149152

@@ -196,6 +199,7 @@ check:
196199
install: $(PROG) $(SCRIPTS)
197200
$(INSTALL) -m755 -d $(dest)$(bindir)
198201
$(INSTALL) $(PROG) $(SCRIPTS) $(dest)$(bindir)
202+
$(MAKE) -C templates install
199203

200204
install-tools:
201205
$(MAKE) -C tools install
@@ -236,4 +240,5 @@ clean:
236240
rm -f git-core-*.tar.gz git-core.spec
237241
$(MAKE) -C tools/ clean
238242
$(MAKE) -C Documentation/ clean
243+
$(MAKE) -C templates/ clean
239244
$(MAKE) -C t/ clean

cache.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ extern unsigned int active_nr, active_alloc, active_cache_changed;
128128
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
129129
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
130130
#define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
131+
#define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIRECTORY"
132+
#ifndef DEFAULT_GIT_TEMPLATE_ENVIRONMENT
133+
#define DEFAULT_GIT_TEMPLATE_ENVIRONMENT "/etc/git-core/templates"
134+
#endif
131135

132136
extern char *get_object_directory(void);
133137
extern char *get_refs_directory(void);

init-db.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,147 @@ static void safe_create_dir(const char *dir)
1515
}
1616
}
1717

18+
static int copy_file(const char *dst, const char *src, int mode)
19+
{
20+
int fdi, fdo;
21+
22+
mode = (mode & 0111) ? 0777 : 0666;
23+
if ((fdi = open(src, O_RDONLY)) < 0)
24+
return fdi;
25+
if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {
26+
close(fdi);
27+
return fdo;
28+
}
29+
while (1) {
30+
char buf[BUFSIZ];
31+
ssize_t leni, leno, ofs;
32+
leni = read(fdi, buf, sizeof(buf));
33+
if (leni < 0) {
34+
error_return:
35+
close(fdo);
36+
close(fdi);
37+
return -1;
38+
}
39+
if (!leni)
40+
break;
41+
ofs = 0;
42+
do {
43+
leno = write(fdo, buf+ofs, leni);
44+
if (leno < 0)
45+
goto error_return;
46+
leni -= leno;
47+
ofs += leno;
48+
} while (0 < leni);
49+
}
50+
close(fdo);
51+
close(fdi);
52+
return 0;
53+
}
54+
55+
static void copy_templates_1(char *path, int baselen,
56+
char *template, int template_baselen,
57+
DIR *dir)
58+
{
59+
struct dirent *de;
60+
61+
/* Note: if ".git/hooks" file exists in the repository being
62+
* re-initialized, /etc/core-git/templates/hooks/update would
63+
* cause git-init-db to fail here. I think this is sane but
64+
* it means that the set of templates we ship by default, along
65+
* with the way the namespace under .git/ is organized, should
66+
* be really carefully chosen.
67+
*/
68+
safe_create_dir(path);
69+
while ((de = readdir(dir)) != NULL) {
70+
struct stat st_git, st_template;
71+
int namelen;
72+
int exists = 0;
73+
74+
if (de->d_name[0] == '.')
75+
continue;
76+
namelen = strlen(de->d_name);
77+
if ((PATH_MAX <= baselen + namelen) ||
78+
(PATH_MAX <= template_baselen + namelen))
79+
die("insanely long template name %s", de->d_name);
80+
memcpy(path + baselen, de->d_name, namelen+1);
81+
memcpy(template + template_baselen, de->d_name, namelen+1);
82+
if (lstat(path, &st_git)) {
83+
if (errno != ENOENT)
84+
die("cannot stat %s", path);
85+
}
86+
else
87+
exists = 1;
88+
89+
if (lstat(template, &st_template))
90+
die("cannot stat template %s", template);
91+
92+
if (S_ISDIR(st_template.st_mode)) {
93+
DIR *subdir = opendir(template);
94+
int baselen_sub = baselen + namelen;
95+
int template_baselen_sub = template_baselen + namelen;
96+
if (!subdir)
97+
die("cannot opendir %s", template);
98+
path[baselen_sub++] =
99+
template[template_baselen_sub++] = '/';
100+
path[baselen_sub] =
101+
template[template_baselen_sub] = 0;
102+
copy_templates_1(path, baselen_sub,
103+
template, template_baselen_sub,
104+
subdir);
105+
closedir(subdir);
106+
}
107+
else if (exists)
108+
continue;
109+
else if (S_ISLNK(st_template.st_mode)) {
110+
char lnk[256];
111+
int len;
112+
len = readlink(template, lnk, sizeof(lnk));
113+
if (len < 0)
114+
die("cannot readlink %s", template);
115+
if (sizeof(lnk) <= len)
116+
die("insanely long symlink %s", template);
117+
lnk[len] = 0;
118+
if (symlink(lnk, path))
119+
die("cannot symlink %s %s", lnk, path);
120+
}
121+
else if (S_ISREG(st_template.st_mode)) {
122+
if (copy_file(path, template, st_template.st_mode))
123+
die("cannot copy %s to %s", template, path);
124+
}
125+
else
126+
error("ignoring template %s", template);
127+
}
128+
}
129+
130+
static void copy_templates(const char *git_dir)
131+
{
132+
char path[PATH_MAX];
133+
char template_path[PATH_MAX];
134+
char *template_dir;
135+
int len, template_len;
136+
DIR *dir;
137+
138+
strcpy(path, git_dir);
139+
len = strlen(path);
140+
template_dir = gitenv(TEMPLATE_DIR_ENVIRONMENT);
141+
if (!template_dir)
142+
template_dir = DEFAULT_GIT_TEMPLATE_ENVIRONMENT;
143+
strcpy(template_path, template_dir);
144+
template_len = strlen(template_path);
145+
if (template_path[template_len-1] != '/') {
146+
template_path[template_len++] = '/';
147+
template_path[template_len] = 0;
148+
}
149+
150+
dir = opendir(template_path);
151+
if (!dir)
152+
return;
153+
copy_templates_1(path, len,
154+
template_path, template_len,
155+
dir);
156+
closedir(dir);
157+
}
158+
18159
static void create_default_files(const char *git_dir)
19160
{
20161
unsigned len = strlen(git_dir);
@@ -48,6 +189,7 @@ static void create_default_files(const char *git_dir)
48189
exit(1);
49190
}
50191
}
192+
copy_templates(path);
51193
}
52194

53195
/*

templates/Makefile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# make
2+
3+
INSTALL=install
4+
prefix=$(HOME)
5+
etcdir=$(prefix)/etc
6+
etcgitdir=$(etcdir)/git-core
7+
templatedir=$(etcgitdir)/templates
8+
# dest=
9+
10+
all:
11+
clean:
12+
13+
install:
14+
$(INSTALL) -d -m755 $(dest)$(templatedir)/hooks/
15+
$(foreach s,$(wildcard hooks--*),\
16+
$(INSTALL) -m644 $s \
17+
$(dest)$(templatedir)/hooks/$(patsubst hooks--%,%,$s);)
18+
$(INSTALL) -d -m755 $(dest)$(templatedir)/info
19+
$(INSTALL) -d -m755 $(dest)$(templatedir)/branches

templates/hooks--post-update

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/sh
2+
#
3+
# An example hook script to prepare a packed repository for use over
4+
# dumb transports.
5+
#
6+
# To enable this hook, make this file executable by "chmod +x post-update".
7+
8+
exec git-update-server-info

templates/hooks--update

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/sh
2+
#
3+
# An example hook script to mail out commit update information.
4+
#
5+
# To enable this hook:
6+
# (1) change the recipient e-mail address
7+
# (2) make this file executable by "chmod +x update".
8+
#
9+
10+
recipient="commit-list@mydomain.xz"
11+
12+
if expr "$2" : '0*$' >/dev/null
13+
then
14+
echo "Created a new ref, with the following commits:"
15+
git-rev-list --pretty "$2"
16+
else
17+
echo "New commits:"
18+
git-rev-list --pretty "$3" "^$2"
19+
fi |
20+
mail -s "Changes to ref $1" "$recipient"
21+
exit 0

0 commit comments

Comments
 (0)