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 18" 19SUBDIRECTORY_OK=1 20. "$(git --exec-path)/git-sh-setup" 21 22parallel= 23force= 24clean= 25whiletest$#-gt0 26do 27case"$1"in 28-j) 29 parallel=$2;shift;; 30-c|--clean) 31 clean=t ;; 32-f) 33 force=t ;; 34--) 35shift;break;; 36*) 37 usage ;; 38esac 39shift 40done 41 42tmp="$(git rev-parse --show-toplevel)/Documentation/tmp-doc-diff"||exit1 43 44iftest -n"$clean" 45then 46test$#-eq0|| usage 47 git worktree remove --force"$tmp/worktree"2>/dev/null 48rm-rf"$tmp" 49exit0 50fi 51 52iftest -z"$parallel" 53then 54 parallel=$(getconf _NPROCESSORS_ONLN 2>/dev/null) 55iftest $? !=0||test -z"$parallel" 56then 57 parallel=1 58fi 59fi 60 61test$#-gt1|| usage 62from=$1;shift 63to=$1;shift 64 65from_oid=$(git rev-parse --verify "$from")||exit1 66to_oid=$(git rev-parse --verify "$to")||exit1 67 68iftest -n"$force" 69then 70rm-rf"$tmp" 71fi 72 73# We'll do both builds in a single worktree, which lets "make" reuse 74# results that don't differ between the two trees. 75if!test -d"$tmp/worktree" 76then 77 git worktree add -f --detach"$tmp/worktree""$from"&& 78 dots=$(echo "$tmp/worktree" | sed 's#[^/]*#..#g')&& 79ln-s"$dots/config.mak""$tmp/worktree/config.mak" 80fi 81 82# generate_render_makefile <srcdir> <dstdir> 83generate_render_makefile () { 84find"$1"-type f | 85whileread src 86do 87 dst=$2/${src#$1/} 88printf'all:: %s\n'"$dst" 89printf'%s: %s\n'"$dst""$src" 90printf'\t@echo >&2 " RENDER$(notdir $@)" &&\\\n' 91printf'\tmkdir -p$(dir $@)&&\\\n' 92printf'\tMANWIDTH=80 man $< >$@+ &&\\\n' 93printf'\tmv $@+ $@\n' 94done 95} 96 97# render_tree <committish_oid> 98render_tree () { 99# Skip install-man entirely if we already have an installed directory. 100# We can't rely on make here, since "install-man" unconditionally 101# copies the files (spending effort, but also updating timestamps that 102# we then can't rely on during the render step). We use "mv" to make 103# sure we don't get confused by a previous run that failed partway 104# through. 105if!test -d"$tmp/installed/$1" 106then 107 git -C"$tmp/worktree" checkout --detach"$1"&& 108make-j$parallel-C"$tmp/worktree" \ 109 GIT_VERSION=omitted \ 110 SOURCE_DATE_EPOCH=0 \ 111 DESTDIR="$tmp/installed/$1+" \ 112install-man&& 113mv"$tmp/installed/$1+""$tmp/installed/$1" 114fi&& 115 116# As with "installed" above, we skip the render if it's already been 117# done. So using make here is primarily just about running in 118# parallel. 119if!test -d"$tmp/rendered/$1" 120then 121 generate_render_makefile "$tmp/installed/$1""$tmp/rendered/$1+"| 122make-j$parallel-f- && 123mv"$tmp/rendered/$1+""$tmp/rendered/$1" 124fi 125} 126 127render_tree $from_oid&& 128render_tree $to_oid&& 129git -C$tmp/rendered diff--no-index"$@"$from_oid $to_oid