add a script to diff rendered documentation

After making a change to the documentation, it's easy to forget to check the rendered version to make sure it was formatted as you intended. And simply doing a diff between the two built versions is less trivial than you might hope: - diffing the roff or html output isn't particularly readable; what we really care about is what the end user will see - you have to tweak a few build variables to avoid spurious differences (e.g., version numbers, build times) Let's provide a script that builds and installs the manpages for two commits, renders the results using "man", and diffs the result. Since this is time-consuming, we'll also do our best to avoid repeated work, keeping intermediate results between runs. Some of this could probably be made a little less ugly if we built support into Documentation/Makefile. But by relying only on "make install-man" working, this script should work for generating a diff between any two versions, whether they include this script or not. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Aug 6, 2018 at 13:37 UTC beb188e22ad0ca4287984c316c7e0b0f9aa895e6
2 files changed +110
Documentation/.gitignore
+1
@@ -12,3 +12,4 @@ cmds-*.txt
12 mergetools-*.txt
13 manpage-base-url.xsl
14 SubmittingPatches.txt
15 +tmp-doc-diff/
Documentation/doc-diff new
+109
@@ -0,0 +1,109 @@
1 +#!/bin/sh
2 +
3 +OPTIONS_SPEC="\
4 +doc-diff [options] <from> <to> [-- <diff-options>]
5 +--
6 +j=n parallel argument to pass to make
7 +f force rebuild; do not rely on cached results
8 +"
9 +SUBDIRECTORY_OK=1
10 +. "$(git --exec-path)/git-sh-setup"
11 +
12 +parallel=
13 +force=
14 +while test $# -gt 0
15 +do
16 + case "$1" in
17 + -j)
18 + parallel=$2; shift ;;
19 + -f)
20 + force=t ;;
21 + --)
22 + shift; break ;;
23 + *)
24 + usage ;;
25 + esac
26 + shift
27 +done
28 +
29 +if test -z "$parallel"
30 +then
31 + parallel=$(getconf _NPROCESSORS_ONLN 2>/dev/null)
32 + if test $? != 0 || test -z "$parallel"
33 + then
34 + parallel=1
35 + fi
36 +fi
37 +
38 +test $# -gt 1 || usage
39 +from=$1; shift
40 +to=$1; shift
41 +
42 +from_oid=$(git rev-parse --verify "$from") || exit 1
43 +to_oid=$(git rev-parse --verify "$to") || exit 1
44 +
45 +cd_to_toplevel
46 +tmp=Documentation/tmp-doc-diff
47 +
48 +if test -n "$force"
49 +then
50 + rm -rf "$tmp"
51 +fi
52 +
53 +# We'll do both builds in a single worktree, which lets "make" reuse
54 +# results that don't differ between the two trees.
55 +if ! test -d "$tmp/worktree"
56 +then
57 + git worktree add --detach "$tmp/worktree" "$from" &&
58 + dots=$(echo "$tmp/worktree" | sed 's#[^/]*#..#g') &&
59 + ln -s "$dots/config.mak" "$tmp/worktree/config.mak"
60 +fi
61 +
62 +# generate_render_makefile <srcdir> <dstdir>
63 +generate_render_makefile () {
64 + find "$1" -type f |
65 + while read src
66 + do
67 + dst=$2/${src#$1/}
68 + printf 'all:: %s\n' "$dst"
69 + printf '%s: %s\n' "$dst" "$src"
70 + printf '\t@echo >&2 " RENDER $(notdir $@)" && \\\n'
71 + printf '\tmkdir -p $(dir $@) && \\\n'
72 + printf '\tMANWIDTH=80 man -l $< >$@+ && \\\n'
73 + printf '\tmv $@+ $@\n'
74 + done
75 +}
76 +
77 +# render_tree <dirname> <committish>
78 +render_tree () {
79 + # Skip install-man entirely if we already have an installed directory.
80 + # We can't rely on make here, since "install-man" unconditionally
81 + # copies the files (spending effort, but also updating timestamps that
82 + # we then can't rely on during the render step). We use "mv" to make
83 + # sure we don't get confused by a previous run that failed partway
84 + # through.
85 + if ! test -d "$tmp/installed/$1"
86 + then
87 + git -C "$tmp/worktree" checkout "$2" &&
88 + make -j$parallel -C "$tmp/worktree" \
89 + GIT_VERSION=omitted \
90 + SOURCE_DATE_EPOCH=0 \
91 + DESTDIR="$PWD/$tmp/installed/$1+" \
92 + install-man &&
93 + mv "$tmp/installed/$1+" "$tmp/installed/$1"
94 + fi &&
95 +
96 + # As with "installed" above, we skip the render if it's already been
97 + # done. So using make here is primarily just about running in
98 + # parallel.
99 + if ! test -d "$tmp/rendered/$1"
100 + then
101 + generate_render_makefile "$tmp/installed/$1" "$tmp/rendered/$1+" |
102 + make -j$parallel -f - &&
103 + mv "$tmp/rendered/$1+" "$tmp/rendered/$1"
104 + fi
105 +}
106 +
107 +render_tree $from_oid "$from" &&
108 +render_tree $to_oid "$to" &&
109 +git -C $tmp/rendered diff --no-index "$@" $from_oid $to_oid