stagit-update (5779B)
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 --github > "$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 # Replace stagit's flat <table id="files"> in files.html with a collapsible 58 # <details> directory tree built from git HEAD (via bin/filetree-html). No-op if 59 # files.html or the helper is missing. 60 render_file_tree() { 61 out=$1 62 repo=$2 63 [ -f "$out/files.html" ] || return 0 64 [ -x "$REPOS/bin/filetree-html" ] || return 0 65 tmp=$(mktemp) 66 "$REPOS/bin/filetree-html" "$repo" > "$tmp" 2>/dev/null || { rm -f "$tmp"; return 0; } 67 awk -v frag="$tmp" ' 68 !done && /<table id="files">/ { 69 while ((getline line < frag) > 0) print line 70 close(frag); skip=1; done=1; next 71 } 72 skip && /<\/table>/ { skip=0; next } 73 skip { next } 74 { print } 75 ' "$out/files.html" > "$out/files.html.tmp" && mv "$out/files.html.tmp" "$out/files.html" 76 rm -f "$tmp" 77 } 78 79 build_one() { 80 repo=$1 81 [ -d "$repo" ] || return 0 82 # Skip repos with no commits yet — stagit errors on them, and there's 83 # nothing meaningful to render until the first push. 84 is_empty "$repo" && return 0 85 name=$(basename "$repo" .git) 86 87 # Per-output cache files — stagit's -c caches commit HTMLs, keyed to the 88 # output dir that stagit wrote them to, so PRIV and PUB need separate caches. 89 out=$PRIV/$name 90 mkdir -p "$out" 91 (cd "$out" && stagit -c "$CACHE/$name.priv.cache" "$repo") 92 link_assets "$out" 93 render_markdown "$out" "$repo" 94 render_file_tree "$out" "$repo" 95 "$REPOS/bin/repo-index" "$out" "$name" 96 97 if [ -f "$repo/public" ]; then 98 out=$PUB/$name 99 mkdir -p "$out" 100 (cd "$out" && stagit -c "$CACHE/$name.pub.cache" "$repo") 101 link_assets "$out" 102 render_markdown "$out" "$repo" 103 render_file_tree "$out" "$repo" 104 "$REPOS/bin/repo-index" "$out" "$name" 105 # bare repo mirror for `git clone` (skip server-side bits) 106 mkdir -p "$PUB/git/$name.git" 107 rsync -a --delete --exclude=hooks --exclude=public "$repo/" "$PUB/git/$name.git/" 108 # github-style archive tarballs (with .b2 sidecars) under <name>/archive/ 109 "$REPOS/bin/archive-refs" "$repo" 110 else 111 # drop public copy if marker was removed (archive-refs handles its own) 112 rm -rf "$PUB/$name" "$PUB/git/$name.git" 113 fi 114 } 115 116 if [ $# -ge 1 ]; then 117 build_one "$REPOS/$1.git" 118 else 119 for r in "$REPOS"/*.git; do build_one "$r"; done 120 fi 121 122 # shared assets at tree root 123 for f in style.css logo.png favicon.png; do 124 [ -f "$ASSETS/$f" ] || continue 125 cp -u "$ASSETS/$f" "$PRIV/" 126 cp -u "$ASSETS/$f" "$PUB/" 127 done 128 129 # shared fonts at tree root (referenced as /fonts/* from style.css) 130 if [ -d "$ASSETS/fonts" ]; then 131 mkdir -p "$PRIV/fonts" "$PUB/fonts" 132 for f in "$ASSETS/fonts"/*; do 133 [ -f "$f" ] || continue 134 cp -u "$f" "$PRIV/fonts/" 135 cp -u "$f" "$PUB/fonts/" 136 done 137 fi 138 139 # indexes 140 all_list="" 141 pub_list="" 142 for r in "$REPOS"/*.git; do 143 [ -d "$r" ] || continue 144 is_empty "$r" && continue 145 all_list="$all_list $r" 146 if [ -f "$r/public" ]; then 147 pub_list="$pub_list $r" 148 fi 149 done 150 151 # After stagit-index runs, point each repo's row link at file/README.md.html 152 # instead of log.html when a rendered README exists. 153 readme_link_rewrite() { 154 idx=$1; base=$2; shift 2 155 [ -f "$idx" ] || return 0 156 for repo in "$@"; do 157 name=$(basename "$repo" .git) 158 [ -f "$base/$name/file/README.md.html" ] || continue 159 sed -i "s|href=\"$name/log\\.html\"|href=\"$name/file/README.md.html\"|g" "$idx" 160 done 161 } 162 163 if [ -n "$all_list" ]; then 164 # shellcheck disable=SC2086 165 stagit-index $all_list > "$PRIV/index.html" 166 # shellcheck disable=SC2086 167 readme_link_rewrite "$PRIV/index.html" "$PRIV" $all_list 168 else 169 : > "$PRIV/index.html" 170 fi 171 172 if [ -n "$pub_list" ]; then 173 # shellcheck disable=SC2086 174 stagit-index $pub_list > "$PUB/index.html" 175 # shellcheck disable=SC2086 176 readme_link_rewrite "$PUB/index.html" "$PUB" $pub_list 177 else 178 : > "$PUB/index.html" 179 fi 180 181 # optional: user-customizable hook for pushing $PUB to Bunny 182 [ -x "$REPOS/bin/publish-public" ] && "$REPOS/bin/publish-public" || true