Root/scripts/schhist2web

Source at commit 02e2bf542f9be8b1951511ee45182727b44495f1 created 10 years 25 days ago.
By Werner Almesberger, Optimize cache usage by symlinking identical PPMs.
1#!/bin/sh
2#
3# schhist2web - Web-browseable graphical revision history of schematics
4#
5# Written 2010 by Werner Almesberger
6# Copyright 2010 Werner Almesberger
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13
14
15OUTDIR=_out
16THUMB_OPTS="-w 3 -d 60 -c 0.5,0.5,0.5 -n 1,1,0"
17BG_COLOR="f0f0ff"
18FNAME_COLOR="#b0f0ff"
19SEP_COLOR="#000000"
20
21
22shrink()
23{
24    pnmscale -width 120 "$@" || exit
25}
26
27
28pngdiff()
29{
30    # pngdiff preproc outfile arg ...
31    pp="$1"
32    of="$2"
33    shift 2
34    if ! PATH=$PATH:`dirname $0`/ppmdiff ppmdiff "$@" "$out/_tmp"; then
35    rm -f "$out/_tmp"
36    return 1
37    fi
38    $pp "$out/_tmp" | pnmtopng >"$of"
39    rm "$out/_tmp"
40}
41
42
43symlink()
44{
45    local old=$1 new=$2
46    local src=`dirname "$new"`/$old
47
48    if [ -L "$src" ]; then
49    ln -sf "`readlink \"$src\"`" "$new"
50    else
51    ln -sf "$old" "$new"
52    fi
53}
54
55
56commit_entry()
57{
58    # usage: commit_entry <base-dir> <commit>
59    # note: the repository's base in $dir must be provided by the caller
60
61    local dir=$1 next=$2
62
63    cat <<EOF
64<TABLE bgcolor="$SEP_COLOR" cellspacing=0 width="100%"><TR><TD></TABLE>
65EOF
66    echo "<PRE>"
67    ( cd "$dir" && git show --pretty=short --quiet $next; ) |
68      if [ -z "$SCHHIST_COMMIT_TEMPLATE" ]; then
69    cat
70      else
71    url=`echo "$SCHHIST_COMMIT_TEMPLATE" | sed "s/{}/$next/g"`
72    sed "s|^commit |<A href=\"$url\">commit</a> |"
73      fi |
74      sed '/^<.*>commit</n;s/&/&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'
75    echo "</PRE>"
76}
77
78
79usage()
80{
81    cat <<EOF 2>&1
82usage: $0 [-c cache-dir] [-n] [-S] [top-dir] [top-schem] [out-dir]
83
84  top-dir top-level directory of the git archive (default: locate it)
85  top-schem root sheet of the schematics (default: locate it in top-dir)
86  out-dir output directory (default: $OUTDIR)
87  -c cache-dir cache directory (default: same as out-dir)
88  -n don't use previous cache content (rebuild the cache)
89  -S sanitize KiCad profile
90EOF
91    exit 1
92}
93
94
95# --- Parse command-line options ----------------------------------------------
96
97
98no_cache=false
99sanitize=
100
101while true; do
102    case "$1" in
103    -n) no_cache=true
104    shift;;
105    -c) [ -z "$1" ] && usage
106    cache="$1"
107    shift 2;;
108    -S) sanitize=-S
109    shift;;
110    -*) usage;;
111    *) break;;
112    esac
113done
114
115
116# --- Interpret the command-line arguments ------------------------------------
117
118
119if [ ! -z "$1" -a -d "$1/.git" ]; then
120    dir="$1"
121    shift
122else
123    dir=.
124    while [ ! -d $dir/.git ]; do
125    if [ $dir -ef $dir/.. ]; then
126        echo "no .git/ directory found in hierarchy" 1>&2
127        exit 1
128    fi
129    dir=$dir/..
130    done
131    echo "found top-dir: $dir" 1>&2
132fi
133
134if [ ! -z "$1" -a -f "$dir/$1" -a \
135  -f "$dir/${1%.sch}.pro" ]; then
136    sch="$1"
137    shift
138else
139    for n in "$dir"/*.sch; do
140    [ -f "${n%.sch}.pro" ] || continue
141    if [ ! -z "$sch" ]; then
142        echo "multiple choices for top-level .sch file" 1>&2
143        exit 1
144    fi
145    sch="$n"
146    done
147    if [ -z "$sch" -o "$sch" = "$dir/*.sch" ]; then
148    echo "no candidate for top-level .sch file found" 1>&2
149    exit 1
150    fi
151    echo "found root sheet: $sch" 1>&2
152fi
153
154if [ ! -z "$1" ] && [ ! -e "$1" ] || [ -d "$1" -a ! -d "$1"/.git ]; then
155    out="$1"
156    shift
157else
158    out=$OUTDIR
159fi
160[ -z "$cache" ] && cache="$out"
161
162[ -z "$1" ] || usage
163
164
165# --- Set up some variables and the directories for cache and output ----------
166
167
168PATH=`dirname "$0"`:"$PATH"
169first=`gitenealogy "$dir" "$sch" | sed '$s/ .*//p;d'`
170schname=`gitenealogy "$dir" "$sch" | sed '$s/^.* //p;d'`
171
172rm -rf "$out/diff_*" "$out/thumb_*" "$out/names"
173$no_cache && rm -rf "$cache"
174mkdir -p "$out/names"
175mkdir -p "$cache"
176
177ppmmake '#e0e0e0' 5 30 | pnmtopng >"$out"/unchanged.png
178
179
180# --- Generate/update the cache -----------------------------------------------
181
182
183head=
184for n in $first `cd "$dir" && git rev-list --reverse $first..HEAD`; do
185    ( cd "$dir" && git show --pretty=format:'' --name-only $n; ) |
186      egrep -q '\.sch$|\.pro$|\.lib$' || continue
187    echo Processing $n
188    new=`gitenealogy "$dir" "$sch" | sed "/^$n /s///p;d"`
189    if [ ! -z "$new" ]; then
190    echo Name change $schname to $new 1>&2
191    schname="$new"
192    fi
193    trap "rm -rf \"$cache/ppm_$n\" \"$cache/fat_$n\"" 0
194    if [ ! -d "$cache/ppm_$n" ]; then
195    rm -rf "$cache/ppm_$n"
196    mkdir "$cache/ppm_$n"
197    #
198    # potential optimization here: remember Postscript files from previous
199    # run (or their md5sum) and check if they have changed. If not, skip
200    # the ghostscript run and just put a symlink, replacing the less
201    # efficient optimization below.
202    #
203    gitsch2ppm $sanitize -k "$dir" "$schname" $n "$cache/ppm_$n" || exit
204    gitsch2ppm -c -w 500 "$dir" "$schname" $n "$cache/fat_$n" || exit
205    fi
206    for m in "$cache/ppm_$n/"*; do
207    [ "$m" = "$cache/ppm_$n/*" ] && break
208    if [ ! -z "$head" ]; then
209        prev="$cache/ppm_$head"/`basename "$m"`
210        if [ -r "$prev" ] && cmp -s "$prev" "$m"; then
211        symlink "../ppm_$head"/`basename "$m"` "$m"
212        symlink "../fat_$head"/`basename "$m"` \
213          "$cache/fat_$n"/`basename "$m"`
214        fi
215    fi
216    touch "$out/names/"`basename "$m" .ppm`
217    done
218    trap 0
219    head=$n
220done
221
222if [ -z "$head" ]; then
223    echo "no usable head found" 2>&1
224    exit 1
225fi
226
227
228# --- Title of the Web page and table header ----------------------------------
229
230
231index="$out/index.html"
232{
233    cat <<EOF
234<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
235<HTML>
236EOF
237    if [ ! -z "$SCHHIST_TITLE" ]; then
238    echo "<TITLE>$SCHHIST_TITLE</TITLE>"
239    fi
240    echo "<BODY>"
241    if [ ! -z "$SCHHIST_TITLE" ]; then
242    echo "<H1>"
243    [ -z "$SCHHIST_HOME_URL" ] || echo "<A href=\"$SCHHIST_HOME_URL\">"
244    echo "$SCHHIST_TITLE"
245    [ -z "$SCHHIST_HOME_URL" ] || echo "</A>"
246    echo "</H1>"
247    fi
248    cat <<EOF
249<TABLE bgcolor="$BG_COLOR" callpadding=1>
250<TR bgcolor="$FNAME_COLOR">
251EOF
252    for m in `ls -1 "$out/names"`; do
253    echo "<TD><B>$m</B>"
254    done
255} >"$index"
256
257
258# --- Diff all the revisions, newest to oldest --------------------------------
259
260
261next="$head"
262for n in `cd "$dir" && git rev-list $first..HEAD~1` $first; do
263    [ -d "$cache/ppm_$n" ] || continue
264    empty=true
265    s="<TR>"
266    mkdir -p "$out/diff_$next" "$out/thumb_$next"
267    for m in `ls -1 "$out/names"`; do
268    a="$cache/ppm_$n/$m.ppm"
269    fat_a="$cache/fat_$n/$m.ppm"
270    b="$cache/ppm_$next/$m.ppm"
271    fat_b="$cache/fat_$next/$m.ppm"
272    diff="$out/diff_$next/$m.png"
273    thumb="$out/thumb_$next/$m.png"
274
275    if [ -f "$a" -a -f "$b" ]; then
276        s="$s<TD align=\"center\" valign=\"middle\">"
277        if ! pngdiff cat "$diff" "$a" "$b"; then
278        s="$s<IMG src=\"unchanged.png\""
279        continue
280        fi
281        pngdiff shrink "$thumb" -f $THUMB_OPTS "$fat_a" "$fat_b" \
282          "$a" "$b" || exit
283    elif [ -f "$a" ]; then
284        s="$s<TD>"
285        pngdiff cat "$diff" -f -c 1,0,0 "$a" "$a" || exit
286        pngdiff shrink "$thumb" -f $THUMB_OPTS -c 1,0,0 "$fat_a" "$fat_a" \
287          || exit
288    elif [ -f "$b" ]; then
289        s="$s<TD>"
290        pngdiff cat "$diff" -f -c 0,1,0 "$b" "$b" || exit
291        pngdiff shrink "$thumb" -f $THUMB_OPTS -c 0,1,0 "$fat_b" "$fat_b" \
292          || exit
293    else
294        s="$s<TD>"
295        continue
296    fi
297    echo "$s" >>"$index"
298    s=
299    empty=false
300    echo "<A href=\"diff_$next/$m.png\"><IMG src=\"thumb_$next/$m.png\"></A>" >>"$index"
301    done
302    if ! $empty; then
303     echo "$s<TD valign=\"middle\">" >>"$index"
304    commit_entry "$dir" $next >>"$index"
305    fi
306    next=$n
307done
308
309
310# --- Add creation entries for all files in the first commit ------------------
311
312
313if [ -d "$cache/ppm_$next" ]; then # could this ever be false ?
314    empty=true
315    echo "<TR>" >>"$index"
316    mkdir -p "$out/diff_$next" "$out/thumb_$next"
317    for m in `ls -1 "$out/names"`; do
318    ppm="$cache/ppm_$next/$m.ppm"
319    fat="$cache/fat_$next/$m.ppm"
320    diff="$out/diff_$next/$m.png"
321    thumb="$out/thumb_$next/$m.png"
322
323    echo "<TD>" >>"$index"
324    [ -f "$ppm" ] || continue
325    pngdiff cat "$diff" -f -c 0,1,0 "$ppm" "$ppm" || exit
326    pngdiff shrink "$thumb" -f $THUMB_OPTS -c 0,1,0 "$fat" "$fat" \
327          || exit
328    empty=false
329    echo "<A href=\"diff_$next/$m.png\"><IMG src=\"thumb_$next/$m.png\"></A>" >>"$index"
330    done
331    if ! $empty; then
332     echo "<TD valign=\"middle\">" >>"$index"
333    commit_entry "$dir" $next >>"$index"
334    fi
335fi
336
337
338# --- Finish ------------------------------------------------------------------
339
340
341cat <<EOF >>"$index"
342</TABLE>
343<HR>
344`date -u '+%F %X'` UTC
345</BODY>
346</HTML>
347EOF
348

Archive Download this file



interactive