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 cafc4603b6a5c4001aba9e9c2c0b0698e51fd89a
parent a42b50903a264bd49f9d6e3093b4cff950ea58a4
Author: Fred Großkopf <fred@kuandu.systems>
Date:   Thu, 17 Sep 2026 18:14:41 +0200

Migrate mirror cmd

Diffstat:
Mgitpages-cmd.sh | 119++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Dgitpages-mirror-git.sh | 84-------------------------------------------------------------------------------
2 files changed, 87 insertions(+), 116 deletions(-)

diff --git a/gitpages-cmd.sh b/gitpages-cmd.sh @@ -75,6 +75,14 @@ check_deps() { command -v git > /dev/null 2>&1 || error "git not found" } +is_bare_repo() { + git --git-dir="$1" rev-parse --is-bare-repository > /dev/null 2>&1 +} + +has_repos() { + [ -d "$1" ] && + ls "$1"/*.git > /dev/null 2>&1 2> /dev/null +} # --- Core Logic --- generate_repo_html() { @@ -171,6 +179,37 @@ generate_repo() { info "Generation complete for $REPO_BASE" } +generate_all() { + CONFIG="$1" + + [ -r "$CONFIG" ] || error "config $CONFIG not readable" + + WEB_ROOT=$(get_config_val "WEB_ROOT") + GIT_SRC=$(get_config_val "GIT_SRC") + GIT_RAW=$(get_config_val "GIT_RAW") + + [ -n "$WEB_ROOT" ] || error "WEB_ROOT missing in config" + [ -n "$GIT_SRC" ] || error "GIT_SRC missing in config" + [ -n "$GIT_RAW" ] || error "GIT_RAW missing in config" + + [ -d "$WEB_ROOT" ] || error "WEB_ROOT directory $WEB_ROOT does not exist" + [ -d "$GIT_SRC" ] || error "GIT_SRC directory $GIT_SRC does not exist" + + GIT_RAW_DIR="$WEB_ROOT/$GIT_RAW" + + info "1/2 Mirroring repos $GIT_SRC → $GIT_RAW_DIR" + mirror "$GIT_SRC" "$GIT_RAW_DIR" + + info "2/2 Generating HTML for all repos in $GIT_RAW_DIR" + + for repo in "$GIT_RAW_DIR"/*.git; do + [ -e "$repo" ] || continue + + info "Processing: $(basename "$repo")" + generate_repo "$CONFIG" "$repo" + done +} + setup_ask() { prompt="$1" current="${2:-}" @@ -263,6 +302,46 @@ setup_all() { info "Setup complete for all repos in $GIT_SRC" } +mirror_repo() { + src="$1" + dst_dir="$2" + name=$(basename "$src") + dst="$dst_dir/$name" + + is_bare_repo "$src" || { + warning "skipping $name (not bare)" + return 0 + } + + rm -rf "$dst" + cp -R "$src" "$dst" + git --git-dir="$dst" update-server-info > /dev/null 2>&1 +} + +mirror() { + src="$1" + dst_dir="$2" + + [ -d "$dst_dir" ] && [ -w "$dst_dir" ] || + error "DST_DIR '$dst_dir' not writable" + + if is_bare_repo "$src"; then + mirror_repo "$src" "$dst_dir" + info "synced: $src → $dst_dir" + elif has_repos "$src"; then + [ "$dst_dir" != "/" ] && rm -rf "$dst_dir"/* + + for repo in "$src"/*.git; do + [ -d "$repo" ] || break + mirror_repo "$repo" "$dst_dir" + done + + info "synced all: $src → $dst_dir" + else + error "$src: neither bare repo nor *.git directory" + fi +} + cmd_setup() { case "$#" in 0) @@ -282,7 +361,14 @@ cmd_process_queue() { } cmd_mirror() { - "$SCRIPT_DIR/gitpages-mirror-git.sh" "$@" + case "$#" in + 2) + mirror "$1" "$2" + ;; + *) + error "usage: gitpages mirror SRC DST_DIR" + ;; + esac } cmd_generate() { @@ -327,37 +413,6 @@ cmd_generate() { fi } -generate_all() { - CONFIG="$1" - - [ -r "$CONFIG" ] || error "config $CONFIG not readable" - - WEB_ROOT=$(get_config_val "WEB_ROOT") - GIT_SRC=$(get_config_val "GIT_SRC") - GIT_RAW=$(get_config_val "GIT_RAW") - - [ -n "$WEB_ROOT" ] || error "WEB_ROOT missing in config" - [ -n "$GIT_SRC" ] || error "GIT_SRC missing in config" - [ -n "$GIT_RAW" ] || error "GIT_RAW missing in config" - - [ -d "$WEB_ROOT" ] || error "WEB_ROOT directory $WEB_ROOT does not exist" - [ -d "$GIT_SRC" ] || error "GIT_SRC directory $GIT_SRC does not exist" - - GIT_RAW_DIR="$WEB_ROOT/$GIT_RAW" - - info "1/2 Mirroring repos $GIT_SRC → $GIT_RAW_DIR" - "$SCRIPT_DIR/gitpages-mirror-git.sh" "$GIT_SRC" "$GIT_RAW_DIR" || - error "Mirroring failed" - - info "2/2 Generating HTML for all repos in $GIT_RAW_DIR" - - for repo in "$GIT_RAW_DIR"/*.git; do - [ -e "$repo" ] || continue - - info "Processing: $(basename "$repo")" - generate_repo "$CONFIG" "$repo" - done -} [ $# -gt 0 ] || usage diff --git a/gitpages-mirror-git.sh b/gitpages-mirror-git.sh @@ -1,84 +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 - -usage() { - cat << EOF -usage: $(basename "$0") SRC DST_DIR - -Mirror bare git repositories to destination. - - SRC Bare repo OR directory of *.git repos - DST_DIR Output directory - -Examples: - $(basename "$0") /src/repo.git /srv/git - $(basename "$0") /src/repos /srv/git -EOF -} - -error() { - printf 'error: %s\n' "$1" >&2 - exit 1 -} -warning() { printf 'warning: %s\n' "$1" >&2; } -info() { printf 'info: %s\n' "$1"; } - -check_args() { [ $# -eq 2 ] || { - usage >&2 - error "usage: $0 SRC DST_DIR" -}; } - -is_bare_repo() { git --git-dir="$1" rev-parse --is-bare-repository > /dev/null 2>&1; } -has_repos() { [ -d "$1" ] && ls "$1"/*.git > /dev/null 2>&1 2> /dev/null; } - -sync_repo() { - src="$1" dst_dir="$2" name=$(basename "$src") - dst="$dst_dir/$name" - - is_bare_repo "$src" || { - warning "skipping $name (not bare)" - return 0 - } - - rm -rf "$dst" - cp -R "$src" "$dst" - git --git-dir="$dst" update-server-info > /dev/null 2>&1 -} - -main() { - check_args "$@" - SRC="$1" DST_DIR="$2" - - [ -d "$DST_DIR" ] && [ -w "$DST_DIR" ] || error "DST_DIR '$DST_DIR' not writable" - - if is_bare_repo "$SRC"; then - sync_repo "$SRC" "$DST_DIR" - info "synced: $SRC → $DST_DIR" - elif has_repos "$SRC"; then - [ "$DST_DIR" != "/" ] && rm -rf "$DST_DIR"/* - for repo in "$SRC"/*.git; do - [ -d "$repo" ] || break - sync_repo "$repo" "$DST_DIR" - done - info "synced all: $SRC → $DST_DIR" - else - error "$SRC: neither bare repo nor *.git directory" - fi -} - -main "$@"