gitpages

A collection of scripts to securely webhost and publish git repositories.
git clone https://scm.kuandu.systems/git-raw/gitpages.git
Log | Files | Refs | README | LICENSE

commit bde318c4f7b575c5034fe4767ca237f03e8505b3
parent 80f3dbe21de07d95c49de6c135832e171c49241a
Author: Fred Großkopf <fred@kuandu.systems>
Date:   Fri, 18 Sep 2026 13:00:17 +0200

shfmted

Diffstat:
Mgitpages.post-receive.hook | 20++++++++++++--------
Mgitpages.sh | 4++--
Mtest-all.sh | 26+++++++++++++-------------
Mtest-gitpages-generate.sh | 86++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest-gitpages-setup.sh | 21++++++++++++++-------
5 files changed, 84 insertions(+), 73 deletions(-)

diff --git a/gitpages.post-receive.hook b/gitpages.post-receive.hook @@ -20,26 +20,30 @@ QUEUE_DIR="/var/spool/gitpages/queue" sanitize_repo_name() { name="$1" - + # WHITELIST: ONLY these chars allowed name=$(printf '%s' "$name" | tr -cd 'A-Za-z0-9_-') - + # Reject if invalid length or format if [ ${#name} -lt 1 ] || [ ${#name} -gt 32 ]; then printf '%s\n' "invalid" >&2 exit 1 fi - + # Reject if just separators or ending with seperators case "$name" in - "-" | "_" | *"-" | *"_") printf '%s\n' "invalid" >&2; exit 1 ;; + "-" | "_" | *"-" | *"_") + printf '%s\n' "invalid" >&2 + exit 1 + ;; esac # No leading digits - if echo "$name" | grep -q '^[0-9]' ; then - printf '%s\n' "invalid" >&2; exit 1 - fi - + if echo "$name" | grep -q '^[0-9]'; then + printf '%s\n' "invalid" >&2 + exit 1 + fi + printf '%s\n' "$name" } diff --git a/gitpages.sh b/gitpages.sh @@ -338,8 +338,8 @@ mirror() { src="$1" dst_dir="$2" - [ "$dst_dir" != "/" ] || - error "refusing to use / as destination" + [ "$dst_dir" != "/" ] \ + || error "refusing to use / as destination" [ -d "$dst_dir" ] && [ -w "$dst_dir" ] \ || error "DST_DIR '$dst_dir' not writable" diff --git a/test-all.sh b/test-all.sh @@ -5,22 +5,22 @@ set -u failed=0 for test in ./test-gitpages-*.sh; do - printf '\n========================================\n' - printf 'Running %s\n' "$test" - printf '========================================\n' + printf '\n========================================\n' + printf 'Running %s\n' "$test" + printf '========================================\n' - if "$test"; then - printf 'PASS: %s\n' "$test" - else - printf 'FAIL: %s\n' "$test" - failed=1 - fi + if "$test"; then + printf 'PASS: %s\n' "$test" + else + printf 'FAIL: %s\n' "$test" + failed=1 + fi done if [ "$failed" -eq 0 ]; then - printf '\nALL TESTS PASSED\n' - exit 0 + printf '\nALL TESTS PASSED\n' + exit 0 else - printf '\nSOME TESTS FAILED\n' - exit 1 + printf '\nSOME TESTS FAILED\n' + exit 1 fi diff --git a/test-gitpages-generate.sh b/test-gitpages-generate.sh @@ -19,11 +19,11 @@ CONFIG="$TEST_ROOT/gitpages.conf" export GITPAGES_VAR_DIR mkdir -p \ - "$GIT_SRC" \ - "$GIT_RAW" \ - "$GIT_HTML" \ - "$ASSETS_DIR" \ - "$GITPAGES_VAR_DIR" + "$GIT_SRC" \ + "$GIT_RAW" \ + "$GIT_HTML" \ + "$ASSETS_DIR" \ + "$GITPAGES_VAR_DIR" # # Mock stagit and stagit-index. @@ -31,7 +31,7 @@ mkdir -p \ mkdir -p "$TEST_ROOT/bin" export PATH="$TEST_ROOT/bin:$PATH" -cat > "$TEST_ROOT/bin/stagit" <<'EOF' +cat > "$TEST_ROOT/bin/stagit" << 'EOF' #!/bin/sh set -eu @@ -39,7 +39,7 @@ set -eu touch index.html EOF -cat > "$TEST_ROOT/bin/stagit-index" <<'EOF' +cat > "$TEST_ROOT/bin/stagit-index" << 'EOF' #!/bin/sh set -eu @@ -47,13 +47,13 @@ printf '%s\n' '<html><body>Repositories</body></html>' EOF chmod +x \ - "$TEST_ROOT/bin/stagit" \ - "$TEST_ROOT/bin/stagit-index" + "$TEST_ROOT/bin/stagit" \ + "$TEST_ROOT/bin/stagit-index" # # Configuration. # -cat > "$CONFIG" <<EOF +cat > "$CONFIG" << EOF WEB_ROOT=$WEB_ROOT GIT_SRC=$GIT_SRC GIT_RAW=raw @@ -62,43 +62,43 @@ ASSETS_DIR=$ASSETS_DIR EOF fail() { - printf 'FAIL: %s\n' "$1" >&2 - exit 1 + printf 'FAIL: %s\n' "$1" >&2 + exit 1 } assert_dir() { - [ -d "$1" ] || fail "$2" + [ -d "$1" ] || fail "$2" } assert_file() { - [ -f "$1" ] || fail "$2" + [ -f "$1" ] || fail "$2" } # # Create a real bare repository in GIT_SRC. # create_repo() { - name="$1" - work="$TEST_ROOT/work-$name" + name="$1" + work="$TEST_ROOT/work-$name" - mkdir -p "$work" + mkdir -p "$work" - ( - cd "$work" + ( + cd "$work" - git init >/dev/null - git config user.name "Test User" - git config user.email "test@example.com" + git init > /dev/null + git config user.name "Test User" + git config user.email "test@example.com" - printf 'test\n' > README - git add README - git commit -m "Initial commit" >/dev/null + printf 'test\n' > README + git add README + git commit -m "Initial commit" > /dev/null - git clone --bare . "$GIT_SRC/$name.git" >/dev/null - ) + git clone --bare . "$GIT_SRC/$name.git" > /dev/null + ) - git --git-dir="$GIT_SRC/$name.git" \ - symbolic-ref HEAD refs/heads/main + git --git-dir="$GIT_SRC/$name.git" \ + symbolic-ref HEAD refs/heads/main } echo "Testing $SCRIPT generate" @@ -113,20 +113,20 @@ create_repo myrepo "$SCRIPT" generate -c "$CONFIG" assert_dir \ - "$GIT_RAW/myrepo.git" \ - "myrepo.git was mirrored" + "$GIT_RAW/myrepo.git" \ + "myrepo.git was mirrored" assert_dir \ - "$GIT_HTML/myrepo" \ - "HTML directory was generated" + "$GIT_HTML/myrepo" \ + "HTML directory was generated" assert_file \ - "$GIT_HTML/myrepo/index.html" \ - "repository index.html was generated" + "$GIT_HTML/myrepo/index.html" \ + "repository index.html was generated" assert_file \ - "$GIT_HTML/index.html" \ - "repository index was generated" + "$GIT_HTML/index.html" \ + "repository index was generated" echo "PASS: generate all repositories" @@ -140,12 +140,12 @@ rm -rf "$GIT_HTML/myrepo" "$SCRIPT" generate -c "$CONFIG" "$GIT_RAW/myrepo.git" assert_dir \ - "$GIT_HTML/myrepo" \ - "HTML directory was generated for single repository" + "$GIT_HTML/myrepo" \ + "HTML directory was generated for single repository" assert_file \ - "$GIT_HTML/myrepo/index.html" \ - "repository index.html was generated for single repository" + "$GIT_HTML/myrepo/index.html" \ + "repository index.html was generated for single repository" echo "PASS: generate single repository" @@ -154,8 +154,8 @@ echo "PASS: generate single repository" # echo "=== Test: invalid arguments ===" -if "$SCRIPT" generate -c "$CONFIG" -x >/dev/null 2>&1; then - fail "unknown option was accepted" +if "$SCRIPT" generate -c "$CONFIG" -x > /dev/null 2>&1; then + fail "unknown option was accepted" fi echo "PASS: invalid arguments" diff --git a/test-gitpages-setup.sh b/test-gitpages-setup.sh @@ -6,11 +6,14 @@ WORKDIR="" TARGET="" log() { printf 'test: %s\n' "$1"; } -die() { printf 'test: error: %s\n' "$1" >&2; exit 1; } +die() { + printf 'test: error: %s\n' "$1" >&2 + exit 1 +} setup_dirs() { - WORKDIR="$(mktemp -d -t gitpages_test.XXXXXX)" || - die "mktemp failed" + WORKDIR="$(mktemp -d -t gitpages_test.XXXXXX)" \ + || die "mktemp failed" TARGET="$WORKDIR/repos" mkdir "$TARGET" @@ -51,26 +54,30 @@ inspect_repos() { printf '\n== %s ==\n' "$repo_name" if [ -f "$repo/description" ]; then - printf 'desc:\n'; cat "$repo/description" + printf 'desc:\n' + cat "$repo/description" else printf 'desc: (MISSING!)\n' fi if [ -f "$repo/owner" ]; then - printf '\nowner:\n'; cat "$repo/owner" + printf '\nowner:\n' + cat "$repo/owner" else printf 'owner: (MISSING!)\n' fi if [ -f "$repo/url" ]; then - printf '\nurl:\n'; cat "$repo/url" + printf '\nurl:\n' + cat "$repo/url" else printf 'url: (MISSING!)\n' fi hook="$repo/hooks/post-receive" if [ -f "$hook" ]; then - printf '\npost-receive (head 10):\n'; head -10 "$hook" + printf '\npost-receive (head 10):\n' + head -10 "$hook" else printf 'post-receive hook: (MISSING!)\n' fi