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 eebb6e6e7522b72e83ca89da1a72d9b835e7cc22
parent 7d3aa1ee0f649caf50c41c37d6b811a50fc8abcf
Author: Fred Großkopf <fred@kuandu.systems>
Date:   Fri,  1 May 2026 11:05:38 +0200

Use tmp staging folder

Instead of generating directly
into live web content it now uses
a staging folder (/var/gitpages/staging/$repo)

Diffstat:
Mgitpages.sh | 24+++++++++++++++---------
Minstall.sh | 2++
Mtest-gitpages.sh | 71+++++++++++++++++++++++++++++++++++++++++++++++------------------------
3 files changed, 64 insertions(+), 33 deletions(-)

diff --git a/gitpages.sh b/gitpages.sh @@ -4,7 +4,6 @@ set -eu -# Default configuration path DEFAULT_CONFIG="/etc/gitpages.conf" # --- Secure Config Parser --- @@ -33,16 +32,16 @@ check_deps() { # --- Core Logic --- generate_repo_html() { - rm -rf "$TARGET_DIR" - mkdir -p "$TARGET_DIR" - cd "$TARGET_DIR" + rm -rf "$STAGING_DIR" + mkdir -p "$STAGING_DIR" + cd "$STAGING_DIR" stagit "$REPO_SRC" >/dev/null 2>&1 } process_repo_titles() { [ -n "${REPO_TITLE_DESC:-}" ] || return 0 esc_desc=$(sed_escape "$REPO_TITLE_DESC") - find "$TARGET_DIR" -name "*.html" -type f -exec sed -i \ + find "$STAGING_DIR" -name "*.html" -type f -exec sed -i \ "s| - $REPO_BASE - [^<]*| - $REPO_BASE$esc_desc|g" {} + } @@ -80,13 +79,17 @@ process_index() { deploy_assets() { [ -d "${ASSETS_DIR:-}" ] || return 0 - mkdir -p "$TARGET_DIR" + mkdir -p "$STAGING_DIR" for f in "$ASSETS_DIR"/*; do - [ -f "$f" ] && cp -L "$f" "$TARGET_DIR/$(basename "$f")" + [ -f "$f" ] && cp -L "$f" "$STAGING_DIR/$(basename "$f")" done } -# --- Main --- +swap_target_dir() { + rm -rf "$TARGET_DIR" 2>/dev/null || true + mv "$STAGING_DIR" "$TARGET_DIR" || error "could not move staging into place" +} + main() { CONFIG="$DEFAULT_CONFIG" while getopts ":c:h" opt; do @@ -114,14 +117,17 @@ main() { REPO_SRC="$1" REPO_BASE=$(basename "$REPO_SRC" ".git") SRC_DIR="$WEB_ROOT/$GIT_RAW" + VAR_DIR="${GITPAGES_VAR_DIR:-/var/gitpages}" TARGET_DIR="$WEB_ROOT/$GIT_HTML/$REPO_BASE" + STAGING_DIR="$VAR_DIR/staging/$REPO_BASE" # Execution generate_repo_html + deploy_assets process_repo_titles + swap_target_dir generate_index process_index - deploy_assets info "Generation complete for $REPO_BASE" } diff --git a/install.sh b/install.sh @@ -16,6 +16,7 @@ usage() { setup_dirs() { install -d -m 755 -o "$USER_NAME" -g "$GROUP_NAME" "$VAR_DIR" "$LOG_DIR" install -d -m 755 "$BIN_DIR" "$SPOOL_DIR" + install -d -m 755 -o "$USER_NAME" -g "$GROUP_NAME" "$VAR_DIR/staging" } setup_group() { @@ -107,6 +108,7 @@ main() { LOG_DIR="/var/log/gitpages" SPOOL_DIR="/var/spool" QUEUE_DIR="$SPOOL_DIR/gitpages/queue" + STAGING_DIR="$VAR_DIR/staging" if ! id "$GIT_USER" > /dev/null 2>&1; then error "User '$GIT_USER' does not exist." diff --git a/test-gitpages.sh b/test-gitpages.sh @@ -1,54 +1,77 @@ #!/bin/sh + set -e -# Configuration +# --- Configuration --- SCRIPT_NAME="./gitpages.sh" TEST_DIR=$(realpath "$(mktemp -d)") -# Cleanup +# --- Cleanup --- cleanup() { - rm -rf "$TEST_DIR" + rm -rf "$TEST_DIR" } trap cleanup EXIT -# Prerequisites -[ -x "$SCRIPT_NAME" ] || { echo "ERROR: $SCRIPT_NAME missing"; exit 1; } -command -v stagit-index >/dev/null 2>&1 || { echo "ERROR: stagit-index missing"; -exit 1; } +# --- Prerequisites --- +[ -x "$SCRIPT_NAME" ] || { + echo "ERROR: $SCRIPT_NAME missing or not executable" + exit 1 +} +command -v stagit-index > /dev/null 2>&1 || { + echo "ERROR: stagit-index missing" + exit 1 +} -# Create Directory Structure expected by gitpages.sh -# Based on the trace, it expects: $WEB_ROOT/$GIT_RAW +# --- Directory layout expected by gitpages.sh --- WEB_ROOT="$TEST_DIR/public" GIT_RAW_DIR="$WEB_ROOT/raw" -mkdir -p "$GIT_RAW_DIR" "$WEB_ROOT/html" "$TEST_DIR/assets" +GIT_HTML_DIR="$WEB_ROOT/html" +STAGING_ROOT="$TEST_DIR/staging" # we'll point VAR_DIR here -# Setup dummy repo in the location the script expects +mkdir -p "$GIT_RAW_DIR" "$GIT_HTML_DIR" "$TEST_DIR/assets" "$STAGING_ROOT" + +# --- Dummy repo --- REPO_NAME="myrepo" REPO_DIR="$GIT_RAW_DIR/$REPO_NAME.git" mkdir -p "$REPO_DIR" -(cd "$REPO_DIR" && git init --bare >/dev/null 2>&1) +(cd "$REPO_DIR" && git init --bare > /dev/null 2>&1) -# Create config matching this structure +# --- Config (VAR_DIR now set here) --- CONFIG_FILE="$TEST_DIR/gitpages.conf" -cat <<EOF > "$CONFIG_FILE" +cat << EOF > "$CONFIG_FILE" WEB_ROOT=$WEB_ROOT GIT_HTML=html GIT_RAW=raw ASSETS_DIR=$TEST_DIR/assets EOF -# Execution +# --- Assets (for deploy_assets) --- +echo "<!-- dummy logo -->" > "$TEST_DIR/assets/logo.svg" +echo "<!-- dummy style -->" > "$TEST_DIR/assets/style.css" + +# --- Execution --- +export GITPAGES_VAR_DIR="$TEST_DIR" echo "Running $SCRIPT_NAME on $REPO_DIR" -# We pass the repo directory. Ensure gitpages.sh handles absolute paths correctly. "$SCRIPT_NAME" -c "$CONFIG_FILE" "$REPO_DIR" -# Verification -# Stagit-index usually creates an index.html in the output directory -EXPECTED_OUTPUT="$WEB_ROOT/html/index.html" -if [ -f "$EXPECTED_OUTPUT" ]; then - echo "PASS: Generation successful" +# --- Verification --- +EXPECTED_REPO_DIR="$GIT_HTML_DIR/$REPO_NAME" +EXPECTED_INDEX="$GIT_HTML_DIR/index.html" + +if [ -d "$EXPECTED_REPO_DIR" ] && [ -f "$EXPECTED_INDEX" ]; then + echo "PASS: per‑repo HTML and index generated successfully" else - echo "FAIL: $EXPECTED_OUTPUT not created" - ls -R "$TEST_DIR" - exit 1 + echo "FAIL: missing repo or index" + ls -R "$TEST_DIR" + exit 1 +fi + +# --- Staging cleanup check --- +STAGING_DIR="$TEST_DIR/staging/$REPO_NAME" +if [ -d "$STAGING_DIR" ]; then + echo "FAIL: staging directory still present at $STAGING_DIR" + ls -R "$TEST_DIR/staging" + exit 1 fi + +echo "PASS: staging used and then cleaned up"