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 82from_dir=$from_oid&& 83to_dir=$to_oid&& 84 85# generate_render_makefile <srcdir> <dstdir> 86generate_render_makefile () { 87find"$1"-type f | 88whileread src 89do 90 dst=$2/${src#$1/} 91printf'all:: %s\n'"$dst" 92printf'%s: %s\n'"$dst""$src" 93printf'\t@echo >&2 " RENDER$(notdir $@)" &&\\\n' 94printf'\tmkdir -p$(dir $@)&&\\\n' 95printf'\tMANWIDTH=80 man $< >$@+ &&\\\n' 96printf'\tmv $@+ $@\n' 97done 98} 99 100# render_tree <committish_oid> <directory_name> 101render_tree () { 102# Skip install-man entirely if we already have an installed directory. 103# We can't rely on make here, since "install-man" unconditionally 104# copies the files (spending effort, but also updating timestamps that 105# we then can't rely on during the render step). We use "mv" to make 106# sure we don't get confused by a previous run that failed partway 107# through. 108 oid=$1&& 109 dname=$2&& 110if!test -d"$tmp/installed/$dname" 111then 112 git -C"$tmp/worktree" checkout --detach"$oid"&& 113make-j$parallel-C"$tmp/worktree" \ 114 GIT_VERSION=omitted \ 115 SOURCE_DATE_EPOCH=0 \ 116 DESTDIR="$tmp/installed/$dname+" \ 117install-man&& 118mv"$tmp/installed/$dname+""$tmp/installed/$dname" 119fi&& 120 121# As with "installed" above, we skip the render if it's already been 122# done. So using make here is primarily just about running in 123# parallel. 124if!test -d"$tmp/rendered/$dname" 125then 126 generate_render_makefile "$tmp/installed/$dname" \ 127"$tmp/rendered/$dname+"| 128make-j$parallel-f- && 129mv"$tmp/rendered/$dname+""$tmp/rendered/$dname" 130fi 131} 132 133render_tree $from_oid $from_dir&& 134render_tree $to_oid $to_dir&& 135git -C$tmp/rendered diff--no-index"$@"$from_dir $to_dir