gitserver

self-hosted git server tooling
git clone https://git.ryansepassi.com/git/gitserver.git
Log | Files | Refs | README

stagit-update (3878B)


      1 #!/bin/sh
      2 # Regenerate stagit HTML for one repo (arg) or all (no args). Rebuilds indexes
      3 # and mirrors public repos into ~/repos/www-public/ for Bunny sync.
      4 set -eu
      5 
      6 REPOS=$HOME/repos
      7 ASSETS=$REPOS/assets
      8 PRIV=$REPOS/www
      9 PUB=$REPOS/www-public
     10 CACHE=$REPOS/.stagit-cache
     11 
     12 mkdir -p "$PRIV" "$PUB" "$PUB/git" "$CACHE"
     13 
     14 link_assets() {
     15     out=$1
     16     for f in style.css logo.png favicon.png; do
     17         if [ -f "$ASSETS/$f" ]; then
     18             ln -sfn "../$f" "$out/$f"
     19         fi
     20     done
     21 }
     22 
     23 is_empty() {
     24     ! git --git-dir="$1" rev-parse HEAD >/dev/null 2>&1
     25 }
     26 
     27 # For every .md file stagit rendered into $out/file/, replace the <pre id="blob">
     28 # block with md4c-rendered HTML. Source comes from git HEAD (same content stagit
     29 # saw), not the escaped HTML. No-op if md2html isn't installed.
     30 render_markdown() {
     31     out=$1
     32     repo=$2
     33     command -v md2html >/dev/null 2>&1 || return 0
     34     [ -d "$out/file" ] || return 0
     35     find "$out/file" -type f -name '*.md.html' | while read -r html; do
     36         rel=${html#"$out/file/"}
     37         rel=${rel%.html}
     38         tmp=$(mktemp)
     39         if git --git-dir="$repo" show "HEAD:$rel" 2>/dev/null | md2html > "$tmp" 2>/dev/null; then
     40             awk -v mdfile="$tmp" '
     41                 /<pre id="blob">/ {
     42                     print "<div id=\"md\">"
     43                     while ((getline line < mdfile) > 0) print line
     44                     close(mdfile)
     45                     print "</div>"
     46                     skip=1
     47                     next
     48                 }
     49                 skip && /<\/pre>/ { skip=0; next }
     50                 !skip { print }
     51             ' "$html" > "$html.tmp" && mv "$html.tmp" "$html"
     52         fi
     53         rm -f "$tmp"
     54     done
     55 }
     56 
     57 build_one() {
     58     repo=$1
     59     [ -d "$repo" ] || return 0
     60     # Skip repos with no commits yet — stagit errors on them, and there's
     61     # nothing meaningful to render until the first push.
     62     is_empty "$repo" && return 0
     63     name=$(basename "$repo" .git)
     64 
     65     # Per-output cache files — stagit's -c caches commit HTMLs, keyed to the
     66     # output dir that stagit wrote them to, so PRIV and PUB need separate caches.
     67     out=$PRIV/$name
     68     mkdir -p "$out"
     69     (cd "$out" && stagit -c "$CACHE/$name.priv.cache" "$repo")
     70     link_assets "$out"
     71     render_markdown "$out" "$repo"
     72 
     73     if [ -f "$repo/public" ]; then
     74         out=$PUB/$name
     75         mkdir -p "$out"
     76         (cd "$out" && stagit -c "$CACHE/$name.pub.cache" "$repo")
     77         link_assets "$out"
     78         render_markdown "$out" "$repo"
     79         # bare repo mirror for `git clone` (skip server-side bits)
     80         mkdir -p "$PUB/git/$name.git"
     81         rsync -a --delete --exclude=hooks --exclude=public "$repo/" "$PUB/git/$name.git/"
     82         # github-style archive tarballs (with .b2 sidecars) under <name>/archive/
     83         "$REPOS/bin/archive-refs" "$repo"
     84     else
     85         # drop public copy if marker was removed (archive-refs handles its own)
     86         rm -rf "$PUB/$name" "$PUB/git/$name.git"
     87     fi
     88 }
     89 
     90 if [ $# -ge 1 ]; then
     91     build_one "$REPOS/$1.git"
     92 else
     93     for r in "$REPOS"/*.git; do build_one "$r"; done
     94 fi
     95 
     96 # shared assets at tree root
     97 for f in style.css logo.png favicon.png; do
     98     [ -f "$ASSETS/$f" ] || continue
     99     cp -u "$ASSETS/$f" "$PRIV/"
    100     cp -u "$ASSETS/$f" "$PUB/"
    101 done
    102 
    103 # indexes
    104 all_list=""
    105 pub_list=""
    106 for r in "$REPOS"/*.git; do
    107     [ -d "$r" ] || continue
    108     is_empty "$r" && continue
    109     all_list="$all_list $r"
    110     if [ -f "$r/public" ]; then
    111         pub_list="$pub_list $r"
    112     fi
    113 done
    114 
    115 if [ -n "$all_list" ]; then
    116     # shellcheck disable=SC2086
    117     stagit-index $all_list > "$PRIV/index.html"
    118 else
    119     : > "$PRIV/index.html"
    120 fi
    121 
    122 if [ -n "$pub_list" ]; then
    123     # shellcheck disable=SC2086
    124     stagit-index $pub_list > "$PUB/index.html"
    125 else
    126     : > "$PUB/index.html"
    127 fi
    128 
    129 # optional: user-customizable hook for pushing $PUB to Bunny
    130 [ -x "$REPOS/bin/publish-public" ] && "$REPOS/bin/publish-public" || true