You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
4.5 KiB
186 lines
4.5 KiB
#!/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 |
|
from-asciidoc use asciidoc with the 'from'-commit |
|
from-asciidoctor use asciidoctor with the 'from'-commit |
|
asciidoc use asciidoc with both commits |
|
to-asciidoc use asciidoc with the 'to'-commit |
|
to-asciidoctor use asciidoctor with the 'to'-commit |
|
asciidoctor use asciidoctor with both commits |
|
cut-footer cut away footer |
|
" |
|
SUBDIRECTORY_OK=1 |
|
. "$(git --exec-path)/git-sh-setup" |
|
|
|
parallel= |
|
force= |
|
clean= |
|
from_program= |
|
to_program= |
|
cut_footer= |
|
while test $# -gt 0 |
|
do |
|
case "$1" in |
|
-j) |
|
parallel=$2; shift ;; |
|
-c|--clean) |
|
clean=t ;; |
|
-f) |
|
force=t ;; |
|
--from-asciidoctor) |
|
from_program=-asciidoctor ;; |
|
--to-asciidoctor) |
|
to_program=-asciidoctor ;; |
|
--asciidoctor) |
|
from_program=-asciidoctor |
|
to_program=-asciidoctor ;; |
|
--from-asciidoc) |
|
from_program=-asciidoc ;; |
|
--to-asciidoc) |
|
to_program=-asciidoc ;; |
|
--asciidoc) |
|
from_program=-asciidoc |
|
to_program=-asciidoc ;; |
|
--cut-footer) |
|
cut_footer=-cut-footer ;; |
|
--) |
|
shift; break ;; |
|
*) |
|
usage ;; |
|
esac |
|
shift |
|
done |
|
|
|
tmp="$(git rev-parse --show-toplevel)/Documentation/tmp-doc-diff" || exit 1 |
|
|
|
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 |
|
|
|
construct_makemanflags () { |
|
if test "$1" = "-asciidoc" |
|
then |
|
echo USE_ASCIIDOCTOR= |
|
elif test "$1" = "-asciidoctor" |
|
then |
|
echo USE_ASCIIDOCTOR=YesPlease |
|
fi |
|
} |
|
|
|
from_makemanflags=$(construct_makemanflags "$from_program") && |
|
to_makemanflags=$(construct_makemanflags "$to_program") && |
|
|
|
from_dir=$from_oid$from_program$cut_footer && |
|
to_dir=$to_oid$to_program$cut_footer && |
|
|
|
# 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> <directory_name> <makemanflags> |
|
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. |
|
oid=$1 && |
|
dname=$2 && |
|
makemanflags=$3 && |
|
if ! test -d "$tmp/installed/$dname" |
|
then |
|
git -C "$tmp/worktree" checkout --detach "$oid" && |
|
make -j$parallel -C "$tmp/worktree" \ |
|
$makemanflags \ |
|
GIT_VERSION=omitted \ |
|
SOURCE_DATE_EPOCH=0 \ |
|
DESTDIR="$tmp/installed/$dname+" \ |
|
install-man && |
|
mv "$tmp/installed/$dname+" "$tmp/installed/$dname" |
|
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/$dname" |
|
then |
|
generate_render_makefile "$tmp/installed/$dname" \ |
|
"$tmp/rendered/$dname+" | |
|
make -j$parallel -f - && |
|
mv "$tmp/rendered/$dname+" "$tmp/rendered/$dname" |
|
|
|
if test "$cut_footer" = "-cut-footer" |
|
then |
|
for f in $(find "$tmp/rendered/$dname" -type f) |
|
do |
|
head -n -2 "$f" | sed -e '${/^$/d}' >"$f+" && |
|
mv "$f+" "$f" || |
|
return 1 |
|
done |
|
fi |
|
fi |
|
} |
|
|
|
render_tree $from_oid $from_dir $from_makemanflags && |
|
render_tree $to_oid $to_dir $to_makemanflags && |
|
git -C $tmp/rendered diff --no-index "$@" $from_dir $to_dir
|
|
|