filetree-html (2250B)
1 #!/bin/sh 2 # Emit a collapsible <details> file tree (HTML fragment) for a bare repo's HEAD. 3 # Used by stagit-update to replace stagit's flat <table id="files"> in files.html. 4 # Output: a single <div id="filetree">...</div>. Directories are collapsed 5 # <details>; files link to the same file/<path>.html blob pages stagit generates. 6 # Usage: filetree-html <gitdir> 7 set -eu 8 9 repo=$1 10 11 # Sort rows so that within each directory subdirs group before files (both 12 # alphabetical): build a key prefixing every dir component with "0" and the file 13 # leaf with "1", sort on it, then drop the key. Directory subtrees stay 14 # contiguous, which the tree-builder below relies on. 15 git --git-dir="$repo" ls-tree -r --long HEAD \ 16 | awk -F'\t' '{ 17 np = split($2, c, "/"); key = "" 18 for (i = 1; i < np; i++) key = key "0" c[i] "/" 19 print key "1" c[np] "\t" $0 20 }' \ 21 | LC_ALL=C sort \ 22 | cut -f2- \ 23 | awk ' 24 function esc(s) { 25 gsub(/&/, "\\&", s); gsub(/</, "\\<", s) 26 gsub(/>/, "\\>", s); gsub(/"/, "\\"", s) 27 return s 28 } 29 function hsize(n) { 30 if (n == "-" || n == "") return "" 31 if (n < 1024) return n "B" 32 if (n < 1048576) return sprintf("%.1fK", n / 1024) 33 if (n < 1073741824) return sprintf("%.1fM", n / 1048576) 34 return sprintf("%.1fG", n / 1073741824) 35 } 36 BEGIN { print "<div id=\"filetree\">"; depth = 0 } 37 { 38 # line: <mode> <type> <sha> <size>\t<path> 39 tab = index($0, "\t") 40 meta = substr($0, 1, tab - 1) 41 path = substr($0, tab + 1) 42 split(meta, m, /[ \t]+/); size = m[4] 43 np = split(path, c, "/") 44 45 # how many leading dir components match the currently-open dirs 46 k = 0 47 while (k < depth && k < np - 1 && cur[k + 1] == c[k + 1]) k++ 48 49 # close dirs deeper than the shared prefix 50 while (depth > k) { print "</div></details>"; depth-- } 51 52 # open dirs for the new path 53 for (i = k + 1; i <= np - 1; i++) { 54 print "<details><summary>" esc(c[i]) "/</summary><div class=\"tree\">" 55 cur[i] = c[i]; depth++ 56 } 57 58 # the file row 59 print "<div class=\"f\"><a href=\"file/" esc(path) ".html\">" esc(c[np]) \ 60 "</a><span class=\"sz\">" hsize(size) "</span></div>" 61 } 62 END { 63 while (depth > 0) { print "</div></details>"; depth-- } 64 print "</div>" 65 } 66 '