1#!/bin/sh 2# 3# Build two documentation trees and diff the resulting formatted output. 4# Compared to a source diff, this can reveal mistakes in the formatting. 5# For example: 6# 7# ./doc-diff origin/master HEAD 8# 9# would show the differences introduced by a branch based on master. 10 11OPTIONS_SPEC="\ 12doc-diff [options] <from> <to> [-- <diff-options>] 13doc-diff (-c|--clean) 14-- 15j=n parallel argument to pass to make 16f force rebuild; do not rely on cached results 17c,clean cleanup temporary working files 18from-asciidoc use asciidoc with the 'from'-commit 19from-asciidoctor use asciidoctor with the 'from'-commit 20asciidoc use asciidoc with both commits 21to-asciidoc use asciidoc with the 'to'-commit 22to-asciidoctor use asciidoctor with the 'to'-commit 23asciidoctor use asciidoctor with both commits 24" 25SUBDIRECTORY_OK=1 26. "$(git --exec-path)/git-sh-setup" 27 28parallel= 29force= 30clean= 31from_program= 32to_program= 33whiletest$#-gt0 34do 35case"$1"in 36-j) 37 parallel=$2;shift;; 38-c|--clean) 39 clean=t ;; 40-f) 41 force=t ;; 42--from-asciidoctor) 43 from_program=-asciidoctor;; 44--to-asciidoctor) 45 to_program=-asciidoctor;; 46--asciidoctor) 47 from_program=-asciidoctor 48 to_program=-asciidoctor;; 49--from-asciidoc) 50 from_program=-asciidoc;; 51--to-asciidoc) 52 to_program=-asciidoc;; 53--asciidoc) 54 from_program=-asciidoc 55 to_program=-asciidoc;; 56--) 57shift;break;; 58*) 59 usage ;; 60esac 61shift 62done 63 64tmp="$(git rev-parse --show-toplevel)/Documentation/tmp-doc-diff"||exit1 65 66iftest -n"$clean" 67then 68test$#-eq0|| usage 69 git worktree remove --force"$tmp/worktree"2>/dev/null 70rm-rf"$tmp" 71exit0 72fi 73 74iftest -z"$parallel" 75then 76 parallel=$(getconf _NPROCESSORS_ONLN 2>/dev/null) 77iftest $? !=0||test -z"$parallel" 78then 79 parallel=1 80fi 81fi 82 83test$#-gt1|| usage 84from=$1;shift 85to=$1;shift 86 87from_oid=$(git rev-parse --verify "$from")||exit1 88to_oid=$(git rev-parse --verify "$to")||exit1 89 90iftest -n"$force" 91then 92rm-rf"$tmp" 93fi 94 95# We'll do both builds in a single worktree, which lets "make" reuse 96# results that don't differ between the two trees. 97if!test -d"$tmp/worktree" 98then 99 git worktree add -f --detach"$tmp/worktree""$from"&& 100 dots=$(echo "$tmp/worktree" | sed 's#[^/]*#..#g')&& 101ln-s"$dots/config.mak""$tmp/worktree/config.mak" 102fi 103 104construct_makemanflags () { 105iftest"$1"="-asciidoc" 106then 107echo USE_ASCIIDOCTOR= 108eliftest"$1"="-asciidoctor" 109then 110echo USE_ASCIIDOCTOR=YesPlease 111fi 112} 113 114from_makemanflags=$(construct_makemanflags "$from_program")&& 115to_makemanflags=$(construct_makemanflags "$to_program")&& 116 117from_dir=$from_oid$from_program&& 118to_dir=$to_oid$to_program&& 119 120# generate_render_makefile <srcdir> <dstdir> 121generate_render_makefile () { 122find"$1"-type f | 123whileread src 124do 125 dst=$2/${src#$1/} 126printf'all:: %s\n'"$dst" 127printf'%s: %s\n'"$dst""$src" 128printf'\t@echo >&2 " RENDER$(notdir $@)" &&\\\n' 129printf'\tmkdir -p$(dir $@)&&\\\n' 130printf'\tMANWIDTH=80 man $< >$@+ &&\\\n' 131printf'\tmv $@+ $@\n' 132done 133} 134 135# render_tree <committish_oid> <directory_name> <makemanflags> 136render_tree () { 137# Skip install-man entirely if we already have an installed directory. 138# We can't rely on make here, since "install-man" unconditionally 139# copies the files (spending effort, but also updating timestamps that 140# we then can't rely on during the render step). We use "mv" to make 141# sure we don't get confused by a previous run that failed partway 142# through. 143 oid=$1&& 144 dname=$2&& 145 makemanflags=$3&& 146if!test -d"$tmp/installed/$dname" 147then 148 git -C"$tmp/worktree" checkout --detach"$oid"&& 149make-j$parallel-C"$tmp/worktree" \ 150$makemanflags \ 151 GIT_VERSION=omitted \ 152 SOURCE_DATE_EPOCH=0 \ 153 DESTDIR="$tmp/installed/$dname+" \ 154install-man&& 155mv"$tmp/installed/$dname+""$tmp/installed/$dname" 156fi&& 157 158# As with "installed" above, we skip the render if it's already been 159# done. So using make here is primarily just about running in 160# parallel. 161if!test -d"$tmp/rendered/$dname" 162then 163 generate_render_makefile "$tmp/installed/$dname" \ 164"$tmp/rendered/$dname+"| 165make-j$parallel-f- && 166mv"$tmp/rendered/$dname+""$tmp/rendered/$dname" 167fi 168} 169 170render_tree $from_oid $from_dir $from_makemanflags&& 171render_tree $to_oid $to_dir $to_makemanflags&& 172git -C$tmp/rendered diff--no-index"$@"$from_dir $to_dir