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 dfe49b3807593593713055092fc7cd2c0139dc86
parent cafc4603b6a5c4001aba9e9c2c0b0698e51fd89a
Author: Fred Großkopf <fred@kuandu.systems>
Date:   Thu, 17 Sep 2026 22:44:28 +0200

Migrate gitpate-update (process_queue)

Diffstat:
Mgitpages-cmd.sh | 112++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Dgitpages-update.sh | 105-------------------------------------------------------------------------------
Atest-gitpages-process-queue.sh | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dtest-gitpages-update.sh | 73-------------------------------------------------------------------------
4 files changed, 194 insertions(+), 179 deletions(-)

diff --git a/gitpages-cmd.sh b/gitpages-cmd.sh @@ -4,6 +4,8 @@ set -eu SCRIPT_DIR="$(dirname "$0")" DEFAULT_CONFIG="/etc/gitpages.conf" +LOCK_DIR="${GITPAGES_LOCK_DIR:-/tmp/gitpages-update.lock}" +QUEUE_DIR="${GITPAGES_QUEUE_DIR:-/var/spool/gitpages/queue}" usage() { cat << EOF @@ -342,6 +344,49 @@ mirror() { fi } +process_repo() { + CONFIG="$1" + repo_path="$2" + + repo_name=$(basename "$repo_path") + + [ -r "$CONFIG" ] || { + printf 'error: config %s not readable\n' "$CONFIG" >&2 + return 1 + } + + WEB_ROOT=$(get_config_val "WEB_ROOT") + GIT_RAW=$(get_config_val "GIT_RAW") + + [ -n "$WEB_ROOT" ] || { + printf 'error: WEB_ROOT missing in config\n' >&2 + return 1 + } + + [ -n "$GIT_RAW" ] || { + printf 'error: GIT_RAW missing in config\n' >&2 + return 1 + } + + GIT_RAW_DIR="$WEB_ROOT/$GIT_RAW" + + [ -d "$GIT_RAW_DIR" ] || { + printf 'error: GIT_RAW directory %s does not exist\n' "$GIT_RAW_DIR" >&2 + return 1 + } + + if ! mirror "$repo_path" "$GIT_RAW_DIR"; then + printf 'error: Failed to mirror %s\n' "$repo_name" >&2 + return 1 + fi + + if ! generate_repo "$CONFIG" "$GIT_RAW_DIR/$repo_name"; then + printf 'error: Failed to generate pages for %s\n' "$repo_name" >&2 + return 1 + fi +} + + cmd_setup() { case "$#" in 0) @@ -357,7 +402,72 @@ cmd_setup() { } cmd_process_queue() { - "$SCRIPT_DIR/gitpages-update.sh" "$@" + CONFIG="$DEFAULT_CONFIG" + + while [ "$#" -gt 0 ]; do + case "$1" in + -h) + printf 'usage: gitpages process_queue [-c config]\n' + return 0 + ;; + -c) + [ "$#" -ge 2 ] || { + printf 'ERROR: -c requires a config file\n' >&2 + exit 1 + } + CONFIG="$2" + shift 2 + ;; + -*) + printf 'ERROR: unknown option: %s\n' "$1" >&2 + exit 1 + ;; + *) + printf 'ERROR: too many arguments\n' >&2 + exit 1 + ;; + esac + done + + [ -r "$CONFIG" ] || error "config $CONFIG not readable" + + if ! mkdir "$LOCK_DIR" 2>/dev/null; then + info "Update already in progress. Exiting." + return 0 + fi + + trap 'rmdir "$LOCK_DIR"' EXIT + + if [ ! -d "$QUEUE_DIR" ]; then + info "Queue directory not found: $QUEUE_DIR" + return 0 + fi + + processed=0 + + for jobfile in "$QUEUE_DIR"/*; do + [ -f "$jobfile" ] || continue + + repo_path=$(cat "$jobfile") + + if [ -d "$repo_path" ]; then + info "Starting process_repo for: $repo_path (job: $jobfile)" + + if process_repo "$CONFIG" "$repo_path"; then + processed=$((processed + 1)) + rm -f "$jobfile" + else + error "Failed to process_repo $repo_path (job: $jobfile)" + fi + else + printf 'error: Repository directory %s not found (job: %s)\n' \ + "$repo_path" "$jobfile" >&2 + fi + done + + if [ "$processed" -gt 0 ]; then + info "process_queue completed." + fi } cmd_mirror() { diff --git a/gitpages-update.sh b/gitpages-update.sh @@ -1,105 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2026 Fred Großkopf -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -set -eu -PATH=/usr/local/bin:/usr/bin:/bin:$PATH - -# --- Configuration --- -LOCK_DIR="${GITPAGES_LOCK_DIR:-/tmp/gitpages-update.lock}" -QUEUE_DIR="${GITPAGES_QUEUE_DIR:-/var/spool/gitpages/queue}" -LOG_FILE="${GITPAGES_LOG_FILE:-/var/log/gitpages/update.log}" -DEFAULT_CONFIG="/etc/gitpages.conf" - -# --- Functions --- -error() { printf "[%s] ERROR: %s\n" "$(date)" "$1" >&2; } -log() { printf "[%s] %s\n" "$(date)" "$1"; } - -get_config_val() { - [ -f "$1" ] && awk -F '=' -v key="$2" '$1 == key {gsub(/[[:space:]]/, "", $2); print $2}' "$1" | tail -n 1 -} - -process_repo() { - repo_path=$1 - config_file=$2 - - repo_name=$(basename "$repo_path") - WEB_ROOT=$(get_config_val "$config_file" "WEB_ROOT") - GIT_RAW=$(get_config_val "$config_file" "GIT_RAW") - - if ! gitpages-mirror-git.sh "$repo_path" "$WEB_ROOT/$GIT_RAW"; then - error "Failed to mirror $repo_name" - return 1 - fi - - # Use explicit arguments to avoid word splitting/shellcheck issues - if ! gitpages.sh -c "$config_file" "$WEB_ROOT/$GIT_RAW/$repo_name"; then - error "Failed to generate pages for $repo_name" - return 1 - fi -} - -main() { - processed=0 - CONFIG_FILE="$DEFAULT_CONFIG" - - if [ "${1:-}" = "-c" ]; then - [ $# -lt 2 ] && { - echo "Usage: $0 [-c config]" - exit 1 - } - CONFIG_FILE="$2" - shift 2 - fi - - if ! mkdir "$LOCK_DIR" 2> /dev/null; then - log "Update already in progress. Exiting." - exit 0 - fi - trap 'rmdir "$LOCK_DIR"' EXIT - - if [ ! -d "$QUEUE_DIR" ]; then - log "Queue directory not found: $QUEUE_DIR" - return 0 - fi - - for jobfile in "$QUEUE_DIR"/*; do - [ -f "$jobfile" ] || continue - - repo_path=$(cat "$jobfile") - - if [ -d "$repo_path" ]; then - log "Starting update for: $repo_path (job: $jobfile)" - if process_repo "$repo_path" "$CONFIG_FILE"; then - processed=$((processed + 1)) - rm -f "$jobfile" - else - error "Failed to process $repo_path (job: $jobfile)" - fi - else - error "Repository directory $repo_path not found (job: $jobfile)" - fi - done - - if [ "$processed" -gt 0 ]; then - log "Update completed." - fi - -} - -mkdir -p "$(dirname "$LOG_FILE")" -touch "$LOG_FILE" 2> /dev/null -exec >> "$LOG_FILE" 2>&1 -main "$@" diff --git a/test-gitpages-process-queue.sh b/test-gitpages-process-queue.sh @@ -0,0 +1,83 @@ +#!/bin/sh +# +# Copyright (c) 2026 Fred Großkopf +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +set -e + +# Configuration +TEST_DIR=$(realpath "$(mktemp -d)") + +export GITPAGES_LOCK_DIR="$TEST_DIR/lock" +export GITPAGES_QUEUE_DIR="$TEST_DIR/queue" +export GITPAGES_LOG_FILE="$TEST_DIR/log.txt" +export GITPAGES_VAR_DIR="$TEST_DIR/var" + +CONFIG_FILE="$TEST_DIR/gitpages.conf" + +WEB_ROOT="$TEST_DIR" +GIT_SRC="$TEST_DIR/src" +GIT_RAW="raw" +REPO_PATH="$GIT_SRC/myrepo.git" +GIT_HTML="git" + +# Mock dependencies +mkdir -p "$TEST_DIR/bin" +export PATH="$TEST_DIR/bin:$PATH" + +mock_bin() { + cat << EOF > "$TEST_DIR/bin/$1" +#!/bin/sh +printf "MOCK: %s called with \$*\n" "$1" >&2 +exit 0 +EOF + chmod +x "$TEST_DIR/bin/$1" +} + +mock_bin git +mock_bin stagit +mock_bin stagit-index + +# Setup test environment +mkdir -p "$GITPAGES_QUEUE_DIR" +mkdir -p "$GIT_SRC" +mkdir -p "$REPO_PATH" +mkdir -p "$WEB_ROOT/$GIT_HTML" +mkdir -p "$WEB_ROOT/$GIT_RAW" + +# Create a job file whose content is the repo path +printf '%s\n' "$REPO_PATH" > "$GITPAGES_QUEUE_DIR/myrepo" + +# Create test config +cat << EOF > "$CONFIG_FILE" +WEB_ROOT=$TEST_DIR +GIT_RAW=$GIT_RAW +GIT_HTML=$GIT_HTML +EOF + +echo "Running test on gitpages-cmd.sh..." +./gitpages-cmd.sh process_queue -c "$CONFIG_FILE" + +# Verify: queue directory should be empty (no job files left) +files=$(find "$GITPAGES_QUEUE_DIR" -type f | wc -l) +if [ "$files" -eq 0 ]; then + echo "PASS: Queue directory is empty." +else + echo "FAIL: Queue directory is not empty (has $files files)." + find "$GITPAGES_QUEUE_DIR" -type f + exit 1 +fi + +rm -rf "$TEST_DIR" +echo "PASS: process_queue executed successfully." diff --git a/test-gitpages-update.sh b/test-gitpages-update.sh @@ -1,73 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2026 Fred Großkopf -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -set -e - -# Configuration -TEST_DIR=$(realpath "$(mktemp -d)") - -export GITPAGES_LOCK_DIR="$TEST_DIR/lock" -export GITPAGES_QUEUE_DIR="$TEST_DIR/queue" -export GITPAGES_LOG_FILE="$TEST_DIR/log.txt" - -CONFIG_FILE="$TEST_DIR/gitpages.conf" -GIT_RAW="$TEST_DIR/raw" -REPO_PATH="$GIT_RAW/myrepo.git" - -# Mock dependencies -mkdir -p "$TEST_DIR/bin" -export PATH="$TEST_DIR/bin:$PATH" - -mock_bin() { - cat << EOF > "$TEST_DIR/bin/$1" -#!/bin/sh -printf "MOCK: %s called with \$*\n" "$1" >&2 -exit 0 -EOF - chmod +x "$TEST_DIR/bin/$1" -} - -mock_bin gitpages-mirror-git.sh -mock_bin gitpages.sh - -# Setup test environment -mkdir -p "$GIT_RAW" -mkdir -p "$GITPAGES_QUEUE_DIR" -mkdir -p "$REPO_PATH" - -# Create a job file whose content is the repo path -printf '%s\n' "$REPO_PATH" > "$GITPAGES_QUEUE_DIR/myrepo" - -# Create test config -cat << EOF > "$CONFIG_FILE" -GIT_RAW=$GIT_RAW -EOF - -echo "Running test on gitpages-update.sh..." -./gitpages-cmd.sh process_queue -c "$CONFIG_FILE" - -# Verify: queue directory should be empty (no job files left) -files=$(find "$GITPAGES_QUEUE_DIR" -type f | wc -l) -if [ "$files" -eq 0 ]; then - echo "PASS: Queue directory is empty." -else - echo "FAIL: Queue directory is not empty (has $files files)." - find "$GITPAGES_QUEUE_DIR" -type f - exit 1 -fi - -rm -rf "$TEST_DIR" -echo "PASS: Update script executed successfully."