Subject: Re: Maintaining patches relative to -current
To: None <current-users@NetBSD.ORG>
From: der Mouse <mouse@Collatz.McRCIM.McGill.EDU>
List: current-users
Date: 06/24/1996 20:04:22
> I'm considering setting up a framework for maintainng changes
> relative to -current, not using CVS [...].

> Right now I've got a script that copies the code in from the sup area
> (after doing a prune), and then applies all patchfiles found in a
> special directory -- to make it simple to add new patches in.  My
> update-source script also copies the new kernel configs into the
> appropriate directory -- this is special-cased, and there is probably
> a more general solution.

> Anyone got similar scripts and mechanisms they want to share?

Well, I've referred several times to my private patch tree.  I don't
maintain it by hand. :-)

There are two major scripts, apply-patches and regen-patches.  The
former applies a patch tree (or subtree thereof) to an unpatched source
tree (ditto); the latter regenerates the patch tree, by taking an old
patch tree, walking it to obtain the pathnames of files to patch and
then diffing them between the two versions.  Thus, to add a file to the
patch tree, just touch a file with the appropriate name in the old
patch tree directory, make the edits in the "patched" tree, and run
regen-patches.  There's also a third script, patchkit, that I use to
generate patch kits to mail to other people, because the patch tree
itself is not in a form that's useful to hand directly to patch.  (It
might work to cat the files together and hand them to patch -p1 -dxxx;
I haven't investigated much.)  The patchkit script depends on having my
shar available (at least, that's the only one I know of that supports
-N, to put a file into the shar with a name other than its on-disk
name).

Here's a shar containing the three scripts.  Typically, I'll take a new
tree from the sup directory and do something like this (compare is a
program of mine that, in this usage, updates one directory tree to make
it identical to another):

compare -u /supped/source/tree /working/source/tree
apply-patches /working/source/tree >& somelogfile
...examine somelogfile and deal with any patches that didn't apply
   cleanly, typically because the base file was modified since I last
   supped...
regen-patches /supped/source/tree /working/source/tree src src+
diff -c -r src src+ | less
...inspect the diffs and make sure nothing went completely out to
   lunch...
rm -rf src && mv src+ src
(...or if the diff produced no output, "rm -rf src+" 'cause the patch
    trees are identical, so it doesn't matter which one I keep...)

If I make changes, then I use touch to drop files into the old source
tree in appropriate places, then rerun regen-patches.

All this stuff is up for anon ftp in subdirectories of
collatz.mcrcim.mcgill.edu:/mouse/netbsd-patches (the subdirectories
contain patch trees relative to various versions; the "working"
subdirectory is the most current).

					der Mouse

			    mouse@collatz.mcrcim.mcgill.edu

#! /bin/sh
#
# Shar: Shell Archiver
#
# This archive created Mon Jun 24 20:00:52 1996
# Run this through sh to create:
#	apply-patches
#	regen-patches
#	patchkit
echo x - apply-patches \(617 characters\)
sed 's/^X//' > apply-patches << \EOF
X#! /bin/sh
X#
X# Usage: $0 <src-root> [patches-tree [subtree-to-patch]]
X# eg, "apply-patches /usr/src src sys"
X#
Xcase $# in
X	1)	srcroot="$1"
X		patchtree=src
X		subtree=.
X		;;
X	2)	srcroot="$1"
X		patchtree="$2"
X		subtree=.
X		;;
X	3)	srcroot="$1"
X		patchtree="$2"
X		subtree="$3"
X		;;
X	*)	echo Usage: "$0" '<src-root> [<patches> [<subtree>]]' 1>&2
X		exit 1
X		;;
Xesac
X( cd "$patchtree" && find "$subtree" -type f -print ) |
Xwhile read fn
Xdo
X	echo + patch -f -E "$srcroot"/"$fn" \< "$patchtree"/"$fn"
X	patch -f -E "$srcroot"/"$fn" < "$patchtree"/"$fn" 2>&1
X	echo + rm -f "$srcroot"/"$fn".orig
X	rm -f "$srcroot"/"$fn".orig
Xdone
EOF
if test 617 -ne "`wc -c apply-patches`"
then
echo shar: error transmitting apply-patches \(should have been 617 characters\)
fi
echo x - regen-patches \(1526 characters\)
sed 's/^X//' > regen-patches << \EOF
X#! /bin/sh
X#
X# Usage: $0 <base-src-dir> <patched-src-dir> <old-patches-dir> <new-patches-dir>
X#
Xcase $# in
X	4)	base="$1"
X		patched="$2"
X		old="$3"
X		new="$4"
X		;;
X	*)	echo Usage: "$0" '<base-src> <patched-src> <old-patches> <new-patches>' 1>&2
X		exit 1
X		;;
Xesac
Xbasedots=`echo "$base" | sed -e s/././g`
Xpatcheddots=`echo "$patched" | sed -e s/././g`
Xrm -f .empty
Xtouch -t 197001010000.00 .empty
Xmkdir -p "$new"
X( cd "$old" ; find . -type f -print ) | sed -e 's;^./;;' | sort |
Xwhile read fn
Xdo
X	f1="$base"/"$fn"
X	f2="$patched"/"$fn"
X	if [ ! -f "$f1" ]; then f1=.empty; fi
X	if [ ! -f "$f2" ]; then f2=.empty; fi
X	echo $fn
X	diff -u "$f1" "$f2" |
X		case "$f1" in
X			.empty)	case "$f2" in
X					.empty)	sed                                                                      -e '1,2s/... ... .. ..:..:.. ....$/Thu Jan  1 00:00:00 1970/' ;;
X					*)	sed                                  -e '2s/+++ '$patcheddots'/+++ NEW/' -e '1,2s/... ... .. ..:..:.. ....$/Thu Jan  1 00:00:00 1970/' ;;
X				esac ;;
X			*)	case "$f2" in
X					.empty)	sed -e '1s/--- '$basedots'/--- OLD/'                                     -e '1,2s/... ... .. ..:..:.. ....$/Thu Jan  1 00:00:00 1970/' ;;
X					*)	sed -e '1s/--- '$basedots'/--- OLD/' -e '2s/+++ '$patcheddots'/+++ NEW/' -e '1,2s/... ... .. ..:..:.. ....$/Thu Jan  1 00:00:00 1970/' ;;
X				esac ;;
X		esac > .difftmp
X	if [ -s .difftmp ]; then
X		( ( : >"$new"/"$fn" ) 2> /dev/null ) || mkdir -p "$new/`echo \"$fn\" | sed -e 's;/[^/]*\$;;'`"
X		cat .difftmp > "$new"/"$fn"
X	fi
Xdone
Xrm -f .empty .difftmp
EOF
if test 1526 -ne "`wc -c regen-patches`"
then
echo shar: error transmitting regen-patches \(should have been 1526 characters\)
fi
echo x - patchkit \(899 characters\)
sed 's/^X//' > patchkit << \EOF
X#! /bin/sh
Xsharfiles=""
Xpatchfiles=""
Xerrcmd=:
Xtmp=/tmp/$$.p
Xtouch $tmp.x
Xrm -f $tmp.*
Xtrap 'touch $tmp.x; rm -f $tmp.*; exit' 0 1 2 15
Xfor i
Xdo
X	echo "$i"
Xdone | sort -u > $tmp.args
Xif egrep -q -v '^src/' < $tmp.args; then
X	echo Files not in src/: 1>&2
X	egrep -v '^src/' < $tmp.args 1>&2
X	exit 1
Xfi
Xcase `< $tmp.args wc -l | tr -dc 0-9` in
X	`< $tmp.args tr / - | sort -u | wc -l | tr -dc 0-9`)	;;
X	*)	echo Mapping conflict 1>&2
X		exit 1
X		;;
Xesac
X(
X	echo '#!/bin/sh
Xcase $# in
X	1)	;;
X	*)	echo "Usage: $0 base-directory-to-patch" 1>&2
X		echo "eg:    $0 /usr/src" 1>&2
X		exit 1
X		;;
Xesac'
X< $tmp.args sed -e 's;^src/;;' | while read fn
Xdo
X	echo 'patch "$1"/'$fn' < patch-'`echo $fn | tr / -`
Xdone
X) > $tmp.script
Xwhile read fn
Xdo
X	echo =N | tr = -
X	echo $fn
X	echo $fn | sed -e 's;^src/;;' -e 's;/;-;g' -e 's/^/patch-/'
Xdone < $tmp.args > $tmp.shar
Xshar -q -N $tmp.script apply-script `cat $tmp.shar`
EOF
if test 899 -ne "`wc -c patchkit`"
then
echo shar: error transmitting patchkit \(should have been 899 characters\)
fi
exit 0
# end of shell archive