blob: 8a45f810c25bbcc2ce70af1eacd8fde5c8ea294f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/bin/sh

# Checks the post-receive hooks under custom/hooks. The cache hook runs from a
# copy pointed at a cache and a scan path in the trash directory, since the
# shipped one names the system's own, and the hooks run inside bare
# repositories the way git runs them after a push.

test_description='Check the shipped post-receive hooks'
CGIT_TEST_NO_CREATE_REPOS=YesPlease
. ./setup.sh

HOOK_DIRECTORY="$TEST_OUTPUT_DIRECTORY/../custom/hooks"

# A cache that cgit itself filled, for two scanned repositories and the
# index, so the hook reads the keys cgit really writes.
test_expect_success 'set up a cache of two repositories and the index' '
	test_create_repo pusher &&
	test_commit -C pusher cached &&
	mkdir scan slots &&
	git init -q --bare scan/a.git &&
	git init -q --bare scan/b.git &&
	git -C pusher push -q ../scan/a.git HEAD:refs/heads/main &&
	git -C pusher push -q ../scan/b.git HEAD:refs/heads/main &&
	{
		echo "cache-root=$PWD/slots" &&
		echo "cache-size=1000" &&
		echo "virtual-root=/" &&
		echo "scan-path=$PWD/scan"
	} >cachedrc &&
	for page in / /a.git/ /a.git/log/ /b.git/ /b.git/log/
	do
		CGIT_CONFIG="$PWD/cachedrc" PATH_INFO="$page" QUERY_STRING= cgit >/dev/null ||
		return 1
	done &&
	CGIT_CONFIG="$PWD/cachedrc" QUERY_STRING="url=a.git/refs/" cgit >/dev/null &&
	CGIT_CONFIG="$PWD/cachedrc" QUERY_STRING="url=b.git/refs/" cgit >/dev/null &&
	echo writer >slots/0123abcd.lock &&
	cp -R slots pristine &&
	sed -e "s|^cache_root=.*|cache_root='\''$PWD/slots'\''|" \
		-e "s|^scan_path=.*|scan_path='\''$PWD/scan'\''|" \
		"$HOOK_DIRECTORY/post-receive.cgit-cache" >cache-hook
'

# The request each slot answers, read off its head the way the hook reads it.
cached_requests() {
	for slot in slots/*
	do
		dd if="$slot" bs=4096 count=1 2>/dev/null | tr "\0" "\n" | sed -n 1p
	done
}

# The hooks are POSIX sh, so each runs under every such shell that is here.
shells=
for shell in sh dash ksh bash
do
	command -v $shell >/dev/null && shells="$shells $shell"
done

for shell in $shells
do
	test_expect_success "a push drops its own pages and the index under $shell" "
		rm -rf slots && cp -R pristine slots &&
		(cd scan/a.git && $shell ../../cache-hook) &&
		cached_requests >left &&
		grep '|/b.git/log/' left &&
		grep 'url=b.git/refs/' left &&
		! grep 'a.git' left &&
		! grep '1|/0|' left &&
		test_path_is_file slots/0123abcd.lock &&
		! ls slots | grep '^rc-'
	"
done

test_expect_success 'a repository named in cgitrc gives the hook its url' '
	rm -rf slots && cp -R pristine slots &&
	git -C scan/b.git config hooks.cgiturl b.git &&
	sed "s|^scan_path=.*|scan_path=/nonexistent|" cache-hook >named-hook &&
	(cd scan/b.git && sh ../../named-hook) &&
	cached_requests >left &&
	grep "|/a.git/log/" left &&
	! grep "b.git" left
'

test_expect_success 'with no url to go on the whole cache goes' '
	rm -rf slots && cp -R pristine slots &&
	(cd scan/a.git && sh ../../named-hook) &&
	test "$(ls slots)" = 0123abcd.lock
'

test_expect_success SANITY 'the cache hook shows a pusher no error' '
	rm -rf slots && cp -R pristine slots &&
	test_when_finished "chmod 755 slots" &&
	chmod 555 slots &&
	(cd scan/a.git && sh ../../cache-hook 2>../../err) &&
	cached_requests | grep "a.git" &&
	test_must_be_empty err
'

test_expect_success 'the age hook writes the newest branch date' '
	test_create_repo work &&
	test_commit -C work first &&
	git init -q --bare plain.git &&
	git -C work push -q ../plain.git HEAD:refs/heads/main &&
	(cd plain.git && sh "$HOOK_DIRECTORY/post-receive.cgit-age") &&
	git -C plain.git for-each-ref --format="%(committerdate:iso8601)" refs/heads/main >expect &&
	test_cmp expect plain.git/info/web/last-modified
'

for shell in $shells
do
	test_expect_success "the age hook writes the same date under $shell" "
		rm -f plain.git/info/web/last-modified &&
		(cd plain.git && $shell \"\$HOOK_DIRECTORY/post-receive.cgit-age\") &&
		test_cmp expect plain.git/info/web/last-modified
	"
done

# git keeps a shared repository group writable whatever the pusher's umask,
# and the next member to push has to be able to replace the file.
test_expect_success SANITY 'the age hook keeps a shared directory group writable' '
	git init -q --bare --shared=group shared.git &&
	git -C work push -q ../shared.git HEAD:refs/heads/main &&
	(cd shared.git && umask 022 && sh "$HOOK_DIRECTORY/post-receive.cgit-age") &&
	ls -ld shared.git/info/web >mode &&
	grep "^drwxrw[xs]" mode
'

test_expect_success 'the commit-graph hook writes a graph with path filters' '
	git init -q --bare graph.git &&
	git -C work push -q ../graph.git HEAD:refs/heads/main &&
	(cd graph.git && sh "$HOOK_DIRECTORY/post-receive.commit-graph" 2>../graph-err) &&
	test_must_be_empty graph-err &&
	test_path_is_file graph.git/objects/info/commit-graphs/commit-graph-chain &&
	grep -q BDAT graph.git/objects/info/commit-graphs/*.graph &&
	git -C graph.git commit-graph verify
'

for shell in $shells
do
	test_expect_success "a later push moves the graph on under $shell" "
		cat graph.git/objects/info/commit-graphs/commit-graph-chain >chain-$shell &&
		test_commit -C work graph-$shell &&
		git -C work push -q ../graph.git HEAD:refs/heads/main &&
		(cd graph.git && $shell \"\$HOOK_DIRECTORY/post-receive.commit-graph\") &&
		! test_cmp chain-$shell graph.git/objects/info/commit-graphs/commit-graph-chain &&
		git -C graph.git commit-graph verify
	"
done

test_done