summaryrefslogtreecommitdiff
path: root/Documentation/doc-diff
blob: dfd9418778a80a209e8ceb43aa94dbb4259f91db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/bin/sh
#
# Build two documentation trees and diff the resulting formatted output.
# Compared to a source diff, this can reveal mistakes in the formatting.
# For example:
#
#   ./doc-diff origin/master HEAD
#
# would show the differences introduced by a branch based on master.

OPTIONS_SPEC="\
doc-diff [options] <from> <to> [-- <diff-options>]
doc-diff (-c|--clean)
--
j=n	parallel argument to pass to make
f	force rebuild; do not rely on cached results
c,clean	cleanup temporary working files
"
SUBDIRECTORY_OK=1
. "$(git --exec-path)/git-sh-setup"

parallel=
force=
clean=
while test $# -gt 0
do
	case "$1" in
	-j)
		parallel=$2; shift ;;
	-c|--clean)
		clean=t ;;
	-f)
		force=t ;;
	--)
		shift; break ;;
	*)
		usage ;;
	esac
	shift
done

cd_to_toplevel
tmp=Documentation/tmp-doc-diff

if test -n "$clean"
then
	test $# -eq 0 || usage
	git worktree remove --force "$tmp/worktree" 2>/dev/null
	rm -rf "$tmp"
	exit 0
fi

if test -z "$parallel"
then
	parallel=$(getconf _NPROCESSORS_ONLN 2>/dev/null)
	if test $? != 0 || test -z "$parallel"
	then
		parallel=1
	fi
fi

test $# -gt 1 || usage
from=$1; shift
to=$1; shift

from_oid=$(git rev-parse --verify "$from") || exit 1
to_oid=$(git rev-parse --verify "$to") || exit 1

if test -n "$force"
then
	rm -rf "$tmp"
fi

# We'll do both builds in a single worktree, which lets "make" reuse
# results that don't differ between the two trees.
if ! test -d "$tmp/worktree"
then
	git worktree add -f --detach "$tmp/worktree" "$from" &&
	dots=$(echo "$tmp/worktree" | sed 's#[^/]*#..#g') &&
	ln -s "$dots/config.mak" "$tmp/worktree/config.mak"
fi

# generate_render_makefile <srcdir> <dstdir>
generate_render_makefile () {
	find "$1" -type f |
	while read src
	do
		dst=$2/${src#$1/}
		printf 'all:: %s\n' "$dst"
		printf '%s: %s\n' "$dst" "$src"
		printf '\t@echo >&2 "  RENDER $(notdir $@)" && \\\n'
		printf '\tmkdir -p $(dir $@) && \\\n'
		printf '\tMANWIDTH=80 man $< >$@+ && \\\n'
		printf '\tmv $@+ $@\n'
	done
}

# render_tree <committish_oid>
render_tree () {
	# Skip install-man entirely if we already have an installed directory.
	# We can't rely on make here, since "install-man" unconditionally
	# copies the files (spending effort, but also updating timestamps that
	# we then can't rely on during the render step). We use "mv" to make
	# sure we don't get confused by a previous run that failed partway
	# through.
	if ! test -d "$tmp/installed/$1"
	then
		git -C "$tmp/worktree" checkout --detach "$1" &&
		make -j$parallel -C "$tmp/worktree" \
			GIT_VERSION=omitted \
			SOURCE_DATE_EPOCH=0 \
			DESTDIR="$PWD/$tmp/installed/$1+" \
			install-man &&
		mv "$tmp/installed/$1+" "$tmp/installed/$1"
	fi &&

	# As with "installed" above, we skip the render if it's already been
	# done.  So using make here is primarily just about running in
	# parallel.
	if ! test -d "$tmp/rendered/$1"
	then
		generate_render_makefile "$tmp/installed/$1" "$tmp/rendered/$1+" |
		make -j$parallel -f - &&
		mv "$tmp/rendered/$1+" "$tmp/rendered/$1"
	fi
}

render_tree $from_oid &&
render_tree $to_oid &&
git -C $tmp/rendered diff --no-index "$@" $from_oid $to_oid