blob: 8802cccfaba74989907b3e9d541025acb13fd5e8 (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
#!/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 both 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_done