summaryrefslogtreecommitdiffstatshomepage
path: root/tests/setup.sh
blob: 5476cedde9580dcd7d2bdfe3403796ae6e7c0025 (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
# This file should be sourced by all test-scripts
#
# Main functions:
#   prepare_tests(description) - setup for testing, i.e. create repos+config
#   run_test(description, script) - run one test, i.e. eval script
#
# Helper functions
#   cgit_query(querystring) - call cgit with the specified querystring
#   cgit_url(url) - call cgit with the specified virtual url
#
# Example script:
#
# . setup.sh
# prepare_tests "html validation"
# run_test 'repo index' 'cgit_url "/" | tidy -e'
# run_test 'repo summary' 'cgit_url "/foo" | tidy -e'

# We don't want to run Git commands through Valgrind, so we filter out the
# --valgrind option here and handle it ourselves.  We copy the arguments
# assuming that none contain a newline, although other whitespace is
# preserved.
LF='
'
test_argv=

while test $# != 0
do
	case "$1" in
	--va|--val|--valg|--valgr|--valgri|--valgrin|--valgrind)
		cgit_valgrind=t
		test_argv="$test_argv${LF}--verbose"
		;;
	*)
		test_argv="$test_argv$LF$1"
		;;
	esac
	shift
done

OLDIFS=$IFS
IFS=$LF
set -- $test_argv
IFS=$OLDIFS

: ${TEST_DIRECTORY=$(pwd)/../git/t}
: ${TEST_OUTPUT_DIRECTORY=$(pwd)}
TEST_NO_CREATE_REPO=YesPlease
. "$TEST_DIRECTORY"/test-lib.sh

# Prepend the directory containing cgit to PATH.
if test -n "$cgit_valgrind"
then
	GIT_VALGRIND="$TEST_DIRECTORY/valgrind"
	CGIT_VALGRIND=$(cd ../valgrind && pwd)
	PATH="$CGIT_VALGRIND/bin:$PATH"
	export GIT_VALGRIND CGIT_VALGRIND
else
	PATH="$(pwd)/../..:$PATH"
fi

mkrepo() {
	name=$1
	count=$2
	test_create_repo "$name"
	(
		cd "$name"
		n=1
		while test $n -le $count
		do
			echo $n >file-$n
			git add file-$n
			git commit -m "commit $n"
			n=$(expr $n + 1)
		done
		if test "$3" = "testplus"
		then
			echo "hello" >a+b
			git add a+b
			git commit -m "add a+b"
			git branch "1+2"
		fi
	)
}

setup_repos()
{
	rm -rf cache
	mkdir -p cache
	mkrepo repos/foo 5 >/dev/null
	mkrepo repos/bar 50 >/dev/null
	mkrepo repos/foo+bar 10 testplus >/dev/null
	mkrepo "repos/with space" 2 >/dev/null
	cat >cgitrc <<EOF
virtual-root=/
cache-root=$PWD/cache

cache-size=1021
snapshots=tar.gz tar.bz zip
enable-log-filecount=1
enable-log-linecount=1
summary-log=5
summary-branches=5
summary-tags=5
clone-url=git://example.org/\$CGIT_REPO_URL.git

repo.url=foo
repo.path=$PWD/repos/foo/.git
# Do not specify a description for this repo, as it then will be assigned
# the constant value "[no description]" (which actually used to cause a
# segfault).

repo.url=bar
repo.path=$PWD/repos/bar/.git
repo.desc=the bar repo

repo.url=foo+bar
repo.path=$PWD/repos/foo+bar/.git
repo.desc=the foo+bar repo

repo.url=with space
repo.path=$PWD/repos/with space/.git
repo.desc=spaced repo
EOF
}

cgit_query()
{
	CGIT_CONFIG="$PWD/cgitrc" QUERY_STRING="$1" cgit
}

cgit_url()
{
	CGIT_CONFIG="$PWD/cgitrc" QUERY_STRING="url=$1" cgit
}

strip_headers () {
	while read -r line
	do
		test -z "$line" && break
	done
	cat
}

test -z "$CGIT_TEST_NO_CREATE_REPOS" && setup_repos
/span> void *cb) { const char *name; if (!strcmp(key, "gitweb.owner")) config_fn(repo, "owner", value); else if (!strcmp(key, "gitweb.description")) config_fn(repo, "desc", value); else if (!strcmp(key, "gitweb.category")) config_fn(repo, "section", value); else if (!strcmp(key, "gitweb.homepage")) config_fn(repo, "homepage", value); else if (skip_prefix(key, "cgit.", &name)) config_fn(repo, name, value); return 0; } static char *xstrrchr(char *s, char *from, int c) { while (from >= s && *from != c) from--; return from < s ? NULL : from; } static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) { struct stat st; struct passwd *pwd; size_t pathlen; struct strbuf rel = STRBUF_INIT; char *p, *slash; int n; size_t size; if (stat(path->buf, &st)) { fprintf(stderr, "Error accessing %s: %s (%d)\n", path->buf, strerror(errno), errno); return; } strbuf_addch(path, '/'); pathlen = path->len; if (ctx.cfg.strict_export) { strbuf_addstr(path, ctx.cfg.strict_export); if(stat(path->buf, &st)) return; strbuf_setlen(path, pathlen); } strbuf_addstr(path, "noweb"); if (!stat(path->buf, &st)) return; strbuf_setlen(path, pathlen); if (!starts_with(path->buf, base)) strbuf_addbuf(&rel, path); else strbuf_addstr(&rel, path->buf + strlen(base) + 1); if (!strcmp(rel.buf + rel.len - 5, "/.git")) strbuf_setlen(&rel, rel.len - 5); else if (rel.len && rel.buf[rel.len - 1] == '/') strbuf_setlen(&rel, rel.len - 1); repo = cgit_add_repo(rel.buf); config_fn = fn; if (ctx.cfg.enable_git_config) { strbuf_addstr(path, "config"); git_config_from_file(gitconfig_config, path->buf, NULL); strbuf_setlen(path, pathlen); } if (ctx.cfg.remove_suffix) { size_t urllen; strip_suffix(repo->url, ".git", &urllen); strip_suffix_mem(repo->url, &urllen, "/"); repo->url[urllen] = '\0'; } repo->path = xstrdup(path->buf); while (!repo->owner) { if ((pwd = getpwuid(st.st_uid)) == NULL) { fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", path->buf, strerror(errno), errno); break; } if (pwd->pw_gecos) if ((p = strchr(pwd->pw_gecos, ','))) *p = '\0'; repo->owner = xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name); } if (repo->desc == cgit_default_repo_desc || !repo->desc) { strbuf_addstr(path, "description"); if (!stat(path->buf, &st)) readfile(path->buf, &repo->desc, &size); strbuf_setlen(path, pathlen); } if (ctx.cfg.section_from_path) { n = ctx.cfg.section_from_path; if (n > 0) { slash = rel.buf - 1; while (slash && n && (slash = strchr(slash + 1, '/'))) n--; } else { slash = rel.buf + rel.len; while (slash && n && (slash = xstrrchr(rel.buf, slash - 1, '/'))) n++; } if (slash && !n) { *slash = '\0'; repo->section = xstrdup(rel.buf); *slash = '/'; if (starts_with(repo->name, repo->section)) { repo->name += strlen(repo->section); if (*repo->name == '/') repo->name++; } } } strbuf_addstr(path, "cgitrc"); if (!stat(path->buf, &st)) parse_configfile(path->buf, &scan_tree_repo_config); strbuf_release(&rel); } static void scan_path(const char *base, const char *path, repo_config_fn fn) { DIR *dir = opendir(path); struct dirent *ent; struct strbuf pathbuf = STRBUF_INIT; size_t pathlen = strlen(path); struct stat st; if (!dir) { fprintf(stderr, "Error opening directory %s: %s (%d)\n", path, strerror(errno), errno); return; } strbuf_add(&pathbuf, path, strlen(path)); if (is_git_dir(pathbuf.buf)) { add_repo(base, &pathbuf, fn); goto end; } strbuf_addstr(&pathbuf, "/.git"); if (is_git_dir(pathbuf.buf)) { add_repo(base, &pathbuf, fn); goto end; } /* * Add one because we don't want to lose the trailing '/' when we * reset the length of pathbuf in the loop below. */ pathlen++; while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') { if (ent->d_name[1] == '\0') continue; if (ent->d_name[1] == '.' && ent->d_name[2] == '\0') continue; if (!ctx.cfg.scan_hidden_path) continue; } strbuf_setlen(&pathbuf, pathlen); strbuf_addstr(&pathbuf, ent->d_name); if (stat(pathbuf.buf, &st)) { fprintf(stderr, "Error checking path %s: %s (%d)\n", pathbuf.buf, strerror(errno), errno); continue; } if (S_ISDIR(st.st_mode)) scan_path(base, pathbuf.buf, fn); } end: strbuf_release(&pathbuf); closedir(dir); } void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn) { struct strbuf line = STRBUF_INIT; FILE *projects; int err; projects = fopen(projectsfile, "r"); if (!projects) { fprintf(stderr, "Error opening projectsfile %s: %s (%d)\n", projectsfile, strerror(errno), errno); return; } while (strbuf_getline(&line, projects) != EOF) { if (!line.len) continue; strbuf_insert(&line, 0, "/", 1); strbuf_insert(&line, 0, path, strlen(path)); scan_path(path, line.buf, fn); } if ((err = ferror(projects))) { fprintf(stderr, "Error reading from projectsfile %s: %s (%d)\n", projectsfile, strerror(err), err); } fclose(projects); strbuf_release(&line); } void scan_tree(const char *path, repo_config_fn fn) { scan_path(path, path, fn); }