git_infra

Git infra scripts for git.bracken.jp
git clone https://git.bracken.jp/git_infra.git
Log | Files | Refs | LICENSE

commit f654ea5e0a4aa1aa6e285ba9b08b2638a9c09a73
parent ae57783d554dc047a8f117b3c116470f3a82096f
Author: Chris Bracken <chris@bracken.jp>
Date:   Mon, 30 Aug 2021 12:21:16 -0700

Add grm tool

Convenient tool for managing git repos whose HTML pages are generated
using stagit. This eliminates the rebuild_repos script since that
functionality is already built into grm.

In the future, it would be useful to generalise this to not be
stagic-specific, instead calling out to separate tools configured at the
top (or just checked into the same repo and hardcoded).

For example, it could be useful for such a tool to trigger both stagit
and stagit-gopher, or other tools on rebuild. It would also be useful to
de-duplicate the stagit-related code in the post-receive hook and this
script itself.

upstream grm repo: git://sink.krj.st/grm

Diffstat:
Agrm | 272+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Drebuild_all.sh | 43-------------------------------------------
2 files changed, 272 insertions(+), 43 deletions(-)

diff --git a/grm b/grm @@ -0,0 +1,272 @@ +#!/bin/sh +# grm: git repo manager for self-hosted git servers + +#---------------+----------+-----------------# +# | config | # +# +----------+ # + +# root directory of git repositories +GRM_REPOS_ROOT="/home/git" + +# default owner +GRM_OWNER="Chris Bracken" + +# default url prefix (without ending slash) +GRM_URL_PREFIX="git://git.bracken.jp" + +# path of the post-receive hooks for stagit +GRM_POSTRECV_HOOK="/home/git/git_infra/post-receive" +GRM_POSTRECV_HOOKS_DIR="/home/git/git_infra/post-receive.d" + +# root directory of stagit web pages +STAGIT_WEB_ROOT="/usr/local/www/git.bracken.jp" + +# # +# # +#--------------------------------------------# + +# for stagit +export LC_CTYPE="en_US.UTF-8" + +prog_name="${0##*/}" +repos_root=${GRM_REPOS_ROOT:-/home/git} +web_root=${STAGIT_WEB_ROOT:-/srv/git} + +recompile_repo() { + echo "[$1] recompiling stagit pages..." + repo_dir="${repos_root}/${1}.git" + repo_web_dir="${web_root}/${repo_name}" + cachefile="${repo_dir}/.htmlcache" + + [ -d "$repo_dir" ] || { echo "[$1] repo not found"; return 1; } + mkdir -p "$repo_web_dir" + + cd "${repo_web_dir:?}" && \ + rm -f "$cachefile" && \ + rm -rf "commit" "file" && \ + stagit -c "$cachefile" "$repo_dir" && \ + ln -sf log.html index.html && \ + echo "[$1] done!" +} + +rebuild_index() { + echo "[index] rebuilding index..." + mkdir -p "${web_root}" || return 1; + # 1. find all directories in $repos_root ending with .git + # 2. filter all the public repos (with git-daemon-export-ok) + # 3. exclude any repo marked with stagit-no-index + # 4. sort the result + # 5. hack for posix compatibility + # 6. run stagit-index on the result + # 7. export result to index.html + find "${repos_root}/." ! -name . -prune \ + -type d -name "*.git" \ + -exec test -e "{}/git-daemon-export-ok" \;\ + -exec test ! -e "{}/stagit-no-index" \; \ + -print \ + | sort -f \ + | sed -e 's/"/"\\""/g' -e 's/.*/"&"/' \ + | xargs stagit-index \ + > "${web_root}/index.html" && \ + echo "[index] done!" +} + +RED="\033[91m" +GREEN="\033[92m" +YELLOW="\033[93m" +BLUE="\033[94m" +RESET="\033[0m" + +grm_new() { + set -e + default_owner=${GRM_OWNER:-$(logname)} + url_prefix=${GRM_URL_PREFIX:-git://$(hostname -f)} + default_desc="a work in progress" + + printf "%b\n> " "${BLUE}repo name${RESET}" + read -r repo_name + [ -z "$repo_name" ] && \ + { echo "no repo name given, exiting..."; exit 1; } + + # now we have the complete path of the repo + repo_path="$repos_root/${repo_name}.git" + [ -e "$repo_path" ] && \ + { echo "repository already exists"; exit 1; } + + printf "%b\n> " "${YELLOW}visibility: + 1) public\n 2) private\n 3) unlisted (hide from index) +${BLUE}enter index [default: ${GREEN}1${BLUE}]${RESET}" + read -r visibility + + case $visibility in + 1|public) exported=1 ;; + 2|private) ;; + 3|unlisted) exported=1; hidden=1 ;; + *) printf "%b\n" "${YELLOW}visibility defaults to ${GREEN}public${RESET}" + exported=1 ;; + esac + + printf "%b%s%b\n> " "${BLUE}description [${GREEN}" "$default_desc" "${BLUE}]${RESET}" + read -r repo_desc + repo_desc=${repo_desc:-$default_desc} + + printf "%b%s%b\n> " "${BLUE}owner [${GREEN}" "$default_owner" "${BLUE}]${RESET}" + read -r owner + owner=${owner:-$default_owner} + + printf "%b%s%b\n> " \ + "${BLUE}clone url [${GREEN}" "$url_prefix/$repo_name" "${BLUE}]${RESET}" + read -r clone_url + clone_url=${clone_url:-$url_prefix/$repo_name} + + # start creating repo + git init --bare "$repo_path" + + echo "writing stagit metadata..." + printf "%s\n" "$repo_desc" > "$repo_path/description" + printf "%s\n" "$owner" > "$repo_path/owner" + printf "%s\n" "$clone_url" > "$repo_path/url" + + echo "setting visibility..." + [ "$exported" = "1" ] && : >> "$repo_path/git-daemon-export-ok" + [ "$hidden" = "1" ] && : >> "$repo_path/stagit-no-index" + + echo "installing stagit post-receive hook..." + ln -sf "$GRM_POSTRECV_HOOK" "$repo_path/hooks/post-receive" + mkdir -p "$repo_path/hooks/post-receive.d" + for hook in "$(ls "$GRM_POSTRECV_HOOKS_DIR")"; do + ln -sf "$GRM_POSTRECV_HOOKS_DIR/$hook" "$repo_path/hooks/post-receive.d/$hook" + done + + echo "done!" +} + +grm_remove() { + [ $# -gt 0 ] || { echo "no repo name given, exiting..."; exit 1; } + + for repo in "$@" + do + printf "remove %s? [y/N] " "$repo" + read -r resp + if echo "$resp" | grep -iq "^y$"; then + rm -rf "${repos_root:?}/${repo:?}.git" || continue; + rm -rf "${web_root:?}/${repo:?}" || continue; + fi + done + # only rebuild index if stagit exists + command -v stagit-index >/dev/null && rebuild_index & + wait +} + +grm_list() { + case "$1" in + public) + find "${repos_root}/." ! -name . -prune \ + -type d -name "*.git" \ + -exec test -e "{}/git-daemon-export-ok" \; \ + -exec test ! -e "{}/stagit-no-index" \; \ + -exec basename {} '.git' \; ;; + private) + find "${repos_root}/." ! -name . -prune \ + -type d -name "*.git" \ + -exec test ! -e "{}/git-daemon-export-ok" \; \ + -exec basename {} '.git' \; ;; + hidden|unlisted) + find "${repos_root}/." ! -name . -prune \ + -type d -name "*.git" \ + -exec test -e "{}/stagit-no-index" \; \ + -exec basename {} '.git' \; ;; + *) + find "${repos_root}/." ! -name . -prune \ + -type d -name "*.git" \ + -exec basename {} '.git' \; ;; + esac +} + +grm_recompile() { + for repo_name in "$@" + do + recompile_repo "$repo_name" & + done + rebuild_index & + wait + echo "recompilation done!" +} + +grm_recompileall() { + grm_list public \ + | sed -e 's/"/"\\""/g' -e 's/.*/"&"/' \ + | xargs "$0" rc +} + +grm_info() { + [ -z "$1" ] && { echo "no repo name given, exiting..."; exit 1; } + + repo_name=$1 + repo_dir="${repos_root}/${repo_name}.git" + + [ -d "$repo_dir" ] || { echo "can't find repo named $repo_name"; exit 1; } + echo "name: $repo_name" + printf "visibility: " + + if [ -e "${repo_dir}/git-daemon-export-ok" ]; then + if [ -e "${repo_dir}/stagit-no-index" ]; then + printf "%b\n" "${YELLOW}unlisted${RESET}" + else + printf "%b\n" "${GREEN}public${RESET}" + fi + else + printf "%b\n" "${RED}private${RESET}" + fi + + [ -f "${repo_dir}/description" ] && \ + echo "description: $(cat "${repo_dir}/description")" + + [ -f "${repo_dir}/owner" ] && \ + echo "owner: $(cat "${repo_dir}/owner")" + + [ -f "${repo_dir}/url" ] && \ + echo "url: $(cat "${repo_dir}/url")" +} + +show_help() { + cat << EOF +usage: $prog_name <command> [<args>] + +Git repo manager, manage git repositories on self-hosted git servers. + +If you have created a 'git' user for managing git repositories, this +script should be run as: + $ doas -u git -- $prog_name <command> [<args>] +or + $ sudo -u git -- $prog_name <command> [<args>] + +commands: + new create a new repo + info repo_name display metadata of the repo + ls list all repos + ls public list public repos + ls private list private repos + ls unlisted list unlisted (hidden) repos + rm repo1 [repo2..] remove repos + rc recompile stagit index + rc repo1 [repo2..] recompile stagit pages for repos, + and recompile index + rca recompile all public repos + help show help +EOF +} + +# parse subcommands +case "$1" in + new) cmd=new;; + ls|list) cmd=list;; + rm|remove) cmd=remove;; + rc|recompile) cmd=recompile;; + rca|recompileall) cmd=recompileall;; + info) cmd=info;; + *) { show_help; exit; };; +esac + +shift +grm_"$cmd" "$@" diff --git a/rebuild_all.sh b/rebuild_all.sh @@ -1,43 +0,0 @@ -#!/bin/sh -e - -# HTML root directory into which stagit will write. -www_root="/usr/local/www/git.bracken.jp" - -# The directory under which all repos are located. -# Repos under this directory will be added to the repo index page. -repos_root="/home/git" - -# Generate the index page. -# Any repo containing a stagit-no-index file will be skipped. -echo "[stagit] Building repo index" -find "${repos_root}" -maxdepth 1 \ - -type d \ - -name "*.git" \ - -exec test -e "{}/git-daemon-export-ok" \; \ - -print \ - | sort -f \ - | sed -e 's/"/"\\""/g' -e 's/.*/"&"/' \ - | xargs stagit-index \ - > "${www_root}/index.html" - -echo "[stagit] Building all stagit repos" -repos="$(find "${repos_root}" -maxdepth 1 \ - -type d \ - -name "*.git" \ - -exec test -e "{}/git-daemon-export-ok" \; \ - -print | sort -f)" -for repo_dir in ${repos}; do - repo_name="$(basename "${repo_dir}" ".git")" - out_dir="${www_root}/${repo_name}" - - echo "[stagit] ... ${repo_name}" - mkdir -p "${out_dir}" - rm -f "${repo_dir}/.htmlcache" - rm -rf "${out_dir}/commit" - rm -rf "${out_dir}/file" - cd "${out_dir}" - stagit -c "${repo_dir}/.htmlcache" "${repo_dir}" - ln -sf ../logo.png logo.png - ln -sf ../style.css style.css - ln -sf ../favicon.png favicon.png -done