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:
A | grm | | | 272 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | rebuild_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