CVS: is/patches/scripts added-by-patch,NONE,1.1 apatch,NONE,1.1 combine-applied,NONE,1.1 combine-series,NONE,1.1 cvs-take-patch,NONE,1.1 docco.txt,NONE,1.1 export_patch,NONE,1.1 extract_description,NONE,1.1 fpatch,NONE,1.1 import_patch,NONE,1.1 inpatch,NONE,1.1 linus-patch,NONE,1.1 mpatch,NONE,1.1 new-kernel,NONE,1.1 p0-2-p1,NONE,1.1 p_diff,NONE,1.1 patchdesc,NONE,1.1 patchfns,NONE,1.1 pcpatch,NONE,1.1 poppatch,NONE,1.1 prep-patch,NONE,1.1 pstatus,NONE,1.1 ptkdiff,NONE,1.1 pushpatch,NONE,1.1 refpatch,NONE,1.1 removed-by-patch,NONE,1.1 rename-patch,NONE,1.1 rolled-up-patch,NONE,1.1 rpatch,NONE,1.1 split-patch,NONE,1.1 tag-series,NONE,1.1 toppatch,NONE,1.1 touched-by-patch,NONE,1.1 unitdiff.py,NONE,1.1

"Peter J. Braam" <[email protected]> Wed, 11 Dec 2002 11:08:44 -0800
Newsgroups gmane.comp.file-systems.intermezzo.cvs
Message-ID <[email protected]>
Update of /cvsroot/intermezzo/is/patches/scripts
In directory sc8-pr-cvs1:/tmp/cvs-serv10284/patches/scripts

Added Files:
	added-by-patch apatch combine-applied combine-series 
	cvs-take-patch docco.txt export_patch extract_description 
	fpatch import_patch inpatch linus-patch mpatch new-kernel 
	p0-2-p1 p_diff patchdesc patchfns pcpatch poppatch prep-patch 
	pstatus ptkdiff pushpatch refpatch removed-by-patch 
	rename-patch rolled-up-patch rpatch split-patch tag-series 
	toppatch touched-by-patch unitdiff.py 
Log Message:
- fixes for intermezzo on 2.5.50
- patch to be sent off to Linus


--- NEW FILE ---
#!/bin/sh
# Extract names of new files from a patch, print them out

PATCHFILE=$1
case "$PATCHFILE" in
*.gz) CMD="gzip -d < $PATCHFILE";;
*)    CMD="cat $PATCHFILE";;
esac

TMP=$(mktemp /tmp/abp.XXXXXX)

eval $CMD | egrep '^--- .*1969|^--- .*1970' > $TMP
sed -e 's@[^/]*/\([^ 	]*\).*@\1@' < $TMP | sed -e 's@^linux/@@' | sort
rm -f $TMP

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}


do_apply()
{
	FILES=$(cat $P/pc/$PATCH_NAME.pc)
	for file in $FILES
	do
		copy_file_to_bup $file $PATCH_NAME
	done

	silent=-s
	if [ $opt_force != 0 ]
	then
		silent=
	fi

	if patch -p1 $silent -i "$1" || [ $opt_force != 0 ]
	then
		true
	else
		echo SOMETHING WENT WRONG
		exit 1
	fi
}

add_to_db()
{
	basename "$1" >> "$DB"
}

usage()
{
	echo "Usage: apatch patchname"
	exit 1
}

opt_force=0
PATCH_NAMES=""

for i in $*
do
	case "$i" in
	-f)
		opt_force=1;;
	*)
		PATCH_NAMES="$PATCH_NAMES $i"
	esac
done

if [ x"$PATCH_NAMES" == x ]
then
	usage
fi

apatch()
{
	PATCH_NAME=$(stripit $1)

	need_file_there $P/pc/$PATCH_NAME.pc

	if is_applied "$PATCH_NAME"
	then
		echo "$PATCH_NAME" is already applied
		exit 1
	fi

	if [ $opt_force != 0 ]
	then
		echo FORCING PATCH
	fi

	if [ $opt_force != 0 ] || can_apply $P/patches/"$PATCH_NAME".patch
	then
		do_apply $P/patches/"$PATCH_NAME".patch
		add_to_db "$PATCH_NAME"
		echo applied $PATCH_NAME
		echo
	else
		echo "$PATCH_NAME" does not apply
		exit 1
	fi
}

for i in $PATCH_NAMES
do
	if ! apatch $i
	then
		exit 1
	fi
done


--- NEW FILE ---
#!/bin/sh

#
# Make superpatch from currently applied patches using combinediff.
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: combine-applied output-file"
	exit 1
}

if [ $# -ne 1 ] 
then
	usage
fi

need_file_there applied-patches
CURRENT=$(mktemp /tmp/cmbd-XXXXXXXX)
for FILE in `cat applied-patches`
do
	NEXT=$(mktemp /tmp/cmbd-XXXXXXXX)
	if [ -f $P/patches/$FILE ] 
	then
		combinediff $CURRENT $P/patches/$FILE > $NEXT
	elif [ -f $P/patches/$FILE.patch ]
	then
		combinediff $CURRENT $P/patches/$FILE.patch > $NEXT
	elif [ -f $FILE ]
	then
		combinediff $CURRENT $FILE > $NEXT
	fi
	rm $CURRENT
	CURRENT=$NEXT
done

mv $NEXT "$1"

--- NEW FILE ---
#!/bin/sh

#
# Make superpatch from current series using combinediff.
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: combine-series output-file"
	exit 1
}

if [ $# -ne 1 ] 
then
	usage
fi

need_file_there series
CURRENT=$(mktemp /tmp/cmbd-XXXXXXXX)
for FILE in $(cat series)
do
	NEXT=$(mktemp /tmp/cmbd-XXXXXXXX)
	if [ -f $P/patches/$FILE ] 
	then
		combinediff $CURRENT $P/patches/$FILE > $NEXT
	elif [ -f $P/patches/$FILE.patch ]
	then
		combinediff $CURRENT $P/patches/$FILE.patch > $NEXT
	elif [ -f $FILE ]
	then
		combinediff $CURRENT $FILE > $NEXT
	fi
	rm $CURRENT
	CURRENT=$NEXT
done

mv $NEXT "$1"

--- NEW FILE ---
#!/bin/sh

doit()
{
	echo $*
	$*
}

usage()
{
	echo "Usage: cvs-take-patch patch_file_name"
	exit 1
}

#
# Find the highest level directory in $1 which does not
# contain the directory $2.  Return it in $MISSING
#
highest_missing()
{
	START_DIR="$1"
	NAME="$2"
	MISSING=""
	WHERE=$(dirname "$START_DIR")
	PREV_WHERE=$START_DIR
	while [ x"$WHERE" != x"$PREV_WHERE" ]
	do
		WHERE="$PREV_WHERE"
		if [ ! -d "$WHERE"/"$NAME" ]
		then
			MISSING="$WHERE"
		fi
		PREV_WHERE=$(dirname "$WHERE")
	done
	echo highest_missing returns $MISSING
}

#
# Add all new directries to CVS, top-down
# $1: name of a directory
# $2: name of the CVS directory
#
add_cvs_dirs()
{
	MISSING=foo
	while [ "$MISSING" != "" ]
	do
		highest_missing $1 $2
		if [ x"$MISSING" != "x" ]
		then
			if [ ! -d "$MISSING"/"$2" ]
			then
				doit cvs add $MISSING
			fi
		fi
	done
}

PATCHFILE=$1

REMOVEDFILES=$(removed-by-patch $PATCHFILE)
if [ "$REMOVEDFILES" != "" ]
then
	doit cvs remove $REMOVEDFILES
fi

NEWFILES=$(added-by-patch $PATCHFILE)
for i in $NEWFILES
do
	DIRNAME=$(dirname $i)
	echo "Looking at $DIRNAME"
	add_cvs_dirs $DIRNAME CVS
done

if [ "$NEWFILES" != "" ]
then
	doit cvs add $NEWFILES
fi

--- NEW FILE ---
Patch management scripts
Andrew Morton <[email protected]>
18 October 2002

This is a description of a bunch of shell scripts which I use for
managing kernel patches.  They are quite powerful.  They can be used on
projects other than the linux kernel.  They are easy to use, and fast.

You end up doing a ton of recompiling with these scripts, because
you're pushing and popping all the time.  ccache takes away the pain of
all that.  http://ccache.samba.org/ - be sure to put the cache
directory on the same fs as where you're working so that ccache can use
hardlinks.

The key philosophical concept is that your primary output is patches. 
Not ".c" files, not ".h" files.  But patches.  So patches are the
first-class object here.

Installation
============

You place all the scripts somewhere in your path, or in
/usr/lib/patch-scripts.

Terminology
===========

The patch scripts require three special directories called "pc",
"patches" and "txt".

If the environment variable PATCHSCRIPTS is set, it is taken to to be
the directory in which those three directories reside.  Typically, it
would be a relative pathname.  So

	setenv PATCHSCRIPTS ./i-put-them-here

would tell the patch scripts to look in ./i-put-them-here/pc, etc.

If PATCHSCRIPTS is not set, and the directory ./patch-scripts is
present then the patch scripts will us ./patch-scripts/pc/,
./patch-scripts/patches/ and ./patch-scripts/txt/.

Otherwise, the patch scripts use ./pc, ./patches and ./txt.

In this document, the symbol $P is used to describe the directory which
holds the pc/, patches/ and txt/ directories, as determined by the
above search.

It is expected that $P will always expand to a relative path.

Concepts
========

All work occurs with a single directory tree.  All commands are invoked
within the root of that tree.  The scripts manage a "stack" of patches.

Each patch is a changeset against the base tree plus the preceding patches.

All patches are listed, in order, in the file ./series.  You manage the
series file.

Any currently-applied patches are described in the file
./applied-patches.  The patch scripts manage this file.

Each patch affects a number of files in the tree.  These files are
listed in a "patch control" file.  These .pc files live in the
directory $P/pc/

Patches are placed in the directory $P/patches/

Documentation for the patches is placed in $P/txt/

So for a particular patch "my-first-patch" the following will exist:

- An entry "my-first-patch.patch" in ./series

- An entry "my-first-patch" in ./applied-patches (if it's currently applied)

- A file $P/pc/my-first-patch.pc which contains the names of the
  files which my-first-patch modifies, adds or removes

- A file $P/txt/my-first-patch.txt which contains the patch's
  changelog.

- A file $P/patches/my-first-patch.patch, which is the output of the
  patch scripts.

Operation
=========

When a patch "my-patch" is applied with apatch, or with pushpatch
(which calls apatch), all the affected files (from $P/pc/my-patch.pc)
are copied to files with ~my-patch appended.  So if $P/pc/my-patch.pc
contained

	kernel/sched.c
	fs/inode.c

then apatch will copy those files into kernel/sched.c~my-patch and
fs/inode.c~my-patch.  It will then apply the patch to kernel/sched.c
and fs/inode.c

When a diff is regenerated by refpatch (which calls mpatch), the diff
is made between kernel/sched.c and kernel/sched.c~my-patch.  How do the
scripts know to use "~my-patch"?  Because my-patch is the current
topmost patch.  It's the last line in ./applied-patches.

In this way, the whole thing is stackable.  If you have four patches
applied, say "patch-1", "patch-2", "patch-3" and "patch-4", and if
patch-2 and patch-4 both touch kernel/sched.c then you will have:

	kernel/sched.c~patch-2		Original copy, before patch-2
	kernel/sched.c~patch-4		Copy before patch-4.  Contains changes
					from patch-2
	kernel/sched.c			Current working copy.  Contains changes
					from patch-4.

This means that your diff headers contain "~patch-name" in them, which
is convenient documentation.

Walkthrough
===========

Let's start.

Go into /usr/src/linux (or wherever)

	mkdir pc patches txt

Now let's generate a patch

	fpatch my-patch kernel/sched.c

OK, we've copied kernel/sched.c to kernel/sched.c~my-patch.  We've
appended "my-patch" to ./applied-patches and we've put "kernel/sched.c"
into the patch control file, pc/my-patch.pc.

	Now edit kernel/sched.c a bit.

Now we're ready to document the patch

	Now write txt/my-patch.txt

Now generate the patch

	refpatch

This will generate patches/my-patch.patch.  Take a look.

Now remove the patch

	poppatch

applied-patches is now empty, and the patch is removed.

Now let's add a file to my-patch and then generate my-second-patch:

	Add "my-patch.patch" to ./series (no blank lines in that file please)

	pushpatch

OK, the patch is applied again.  Let's add another file

	fpatch kernel/printk.c

Note that here we gave fpatch a single argument.  So rather than
opening a new patch, it adds kernel/printk.c to the existing topmost
patch.  That's my-patch.

	Edit kernel/printk.c

Refresh my-patch (you end up running refpatch a lot)

	refpatch

Now start a second patch:

	fpatch my-second-patch kernel/sched.c

Now take a look at applied-patches.  Also do an `ls kernel/sched*'.

	Edit kernel/sched.c, to make some changes for my-second-patch

Generate my-second-patch:

	refpatch

Take a look in patches/my-second-patch.patch

Don't forget to add "my-second-patch.patch" to the series file.

And remove both patches:

	poppatch
	poppatch


That's pretty much it, really.


Command reference
=================

Generally, where any of these commands take a "patch-name", that can be
of the form txt/patch-name.txt, patch-name.pc, just patch-name or
whatever.  The scripts will strip off a leading "txt/", "patches/" or
"pc/" and any trailing extension.  This is so you can do

	apatch patches/a<tab>

to conveniently use shell tabbing to select patch names.



added-by-patch

  Some internal thing.

apatch [-f] patch-name

  This is the low-level function which adds patches.  It does the
  copying into ~-files and updates the applied-patches file.  It
  applies the actual patch.

  apatch will do a patch --dry-run first and will refuse to apply the
  patch if the dryrun fails.

  So when you are getting rejects you do this:

	pushpatch		# This fails, due to rejects.  Drat.
	apatch -f patch-name	# Force the patch
  (or)  pushpatch -f		# Force the patch

  OK, you've now applied patch-name, but you have rejects.  Go fix
  those up and do

	refpatch

  And you're ready to move on.

combine-series output-file

  It incrementally combinediffs all the patches in series to make a
  complete patch for the series.  Requires combinediff frmo patchutils.

  See http://cyberelk.net/tim/patchutils/ (Don't download the
  "experimental" patchutils - it seems to only have half of the
  commands in it.  Go for "stable")

cvs-take-patch

  I forget.

export_patch

  export the patches listed in ./series to a set of files which
  are named in such a way that the sort order is the same as the
  order of the series file. 

  Usage:  export_patch directory [prefix]

  Example:
	
	Suppose ./series contains
	
	mango.patch
	orange.patch
	banana.patch
	apple.patch
	pear.patch

	export_patch ../mypatches fruit 
	
	The patches would be copied to

	../mypatches/p00001_fruit_mango.patch
	../mypatches/p00002_fruit_orange.patch
	../mypatches/p00003_fruit_banana.patch
	../mypatches/p00003_fruit_banana.patch
	../mypatches/p00003_fruit_banana.patch

	Named in this way, someone may easily apply them:

	cat mypatches/p*fruit* | patch -p1

	If prefix is omitted, the patchnames will be transformed
	such that "original.patch" becomes "pXXXXX_original.patch".

fpatch [patch-name] foo.c

  If patch-name is given, fpatch will start a new patch which
  modifies (or adds, or removes) the single file foo.c.  It updates
  ./applied-patches and creates pc/patch-name.pc.  fpatch will copy
  foo.c to foo.c~patch-name in preparation for edits of foo.c.

  If patch-name is not given then fpatch will add foo.c to the
  current topmost patch.  It will add "foo.c" to $P/pc/$(toppatch).pc. 
  It will copy foo.c to foo.c~$(toppatch).

import_patch

  Imports a set of patch files, creating $P/pc, $P/txt, $P/patches and
  ./series as necessary.  It also creates $P/txt/*.txt by stripping 
  off the top of the patches (and removes any diffstat output it finds, 
  so that it can eat refpatch output and export_patch output.)  The 
  imported patch names are appended to the series file.

  In creating the $P/txt/*.txt files, mail headers are stripped with 
  formail, preserving the "From:" and "Subject:" lines.  "DESC" and
  "EDESC" markers are added if they are not already present, using the
  "From:" and "Subject:" lines for the DESC portion, if they are present.
  (See "patchdesc" command, below, for more on these markers.)

  Also, it can rename the patch file as it is imported by stripping out
  a pattern.  This is useful if, as often is the case, you have patch 
  sets with filenames designed to help sort the patches into the correct 
  order, such as "p001_xxx_funky_stuff.patch" you can have it automatically
  renamed to funky_stuff.patch on import, and let the series file manage
  the ordering.

  Import_patch will uncompress patches (*.Z, *.bz2, *.gz) as necessary.

  Usage:

  import_patch [-p pattern] patchfile ...

  Example:

	% ls ../fruit/p*patch
	../fruit/p00001_northern_apple.patch
	../fruit/p00001_tropical_mango.patch
	../fruit/p00002_northern_pear.patch
	../fruit/p00002_tropical_orange.patch
	../fruit/p00003_tropical_banana.patch
	% import_patch -p 'p[0-9]*_tropical_' ../fruit/p*tropical*
	Recreated pc/mango.pc
	Recreated pc/orange.pc
	Recreated pc/banana.pc
	% import_patch -p 'p[0-9]*_northern_' ../fruit/p*northern*
	Recreated pc/apple.pc
	Recreated pc/pear.pc

  Then you can "pushpatch; refpatch" 5 times.

inpatch

  List the names of ths files which are affected by the current
  topmost patch.

  This is basically

	cat pc/$(toppatch).pc

mpatch

  A low-level thing to generate patches

new-kernel

  Some thing I use for importing a new kernel from kernel.org

p0-2-p1

  Internal thing to convert patch -p0 form into patch -p1

patchdesc

  Generates a single-line description of a patch.

  The txt/my-patch.txt files have the following format:

  <start of file>
  DESC
  some short description
  EDESC

  The long description
  <end of file>

  I use

	patchdesc $(cat series)

  to generate short-form summaries of the patch series.

patchfns

  Internal utilities

pcpatch

  Standalone tool to generate a .pc file from a patch.

  Say someone sends you "his-patch.diff".  What you do is:

	cp ~/his-patch.diff patches/his-patch.patch
	pcpatch his-patch

  This generates $P/pc/his-patch.pc and you're all set.  Add
  "his-patch.patch" to ./series in the right place and start pushing.

p_diff

  I forget

poppatch

  Remove one or more patches from the current stack.  This command
  does *not* use the series file.  It works purely against
  applied-patches.

  Usage:

	poppatch
		Remove the topmost patch
	poppatch 10
		Remove ten patches
	poppatch some-patch-name[.patch]
		Remove patches until "some-patch-name" is top patch

pstatus

	Shows status of patches

  Usage:
	pstatus [patchfile ...]
	
	One line per patch is output showing:
	1: Patch number in the series file
	2: Whether the patch is currently applied
	3: Name of patch
	4: Status of the patch (needs pcpatch, changelog, refpatch)

	If no patchfiles are specified, $P/patches/*.patch
	are assumed.

  Caveats:
	A patch set which contains separate patches to add a file
	and modify that same file may give spurious "Needs refpatch"
	status for the patch which adds the file or the topmost patch.

ptkdiff

  Two modes:

	ptkdiff -

               Run tkdiff against all the file affected
               by $(toppatch).  The diff is only for the changes made
               by the top patch! ie: it's between "filename" and
               "filename~toppatch-name".

	ptkdiff filename

               Just run tkdiff against that file,
               showing the changes which are due to toppatch.

pushpatch [-f]

  Apply the next patch, from the series file.

  This consults ./applied-patches to find out the top patch, then
  consults ./series to find the next patch.  And pushes it.

    pushpatch

      Apply the next patch

    pushpatch 10
 
      Apply the next ten patches

    pushpatch some-patch-name

      Keep pushing patches until "some-patch-name" is toppatch

    pushpatch -f

      Push the next patch, ignoring rejects.

refpatch

    regnerates the topmost patch.  Reads all the affected files
    from pc/$(toppatch).pc and diffs them against their tilde-files.

    Also pastes into the patch your patch documentation and
    generates a diffstat summary.

removed-by-patch

  Some thing.

rename-patch

  CVS rename for patches.

rolled-up-patch

  Bit of a hack.  Is designed to generate a rolled-up diff of all
  currently-applied patches.  But it requires a ../linux-2.x.y tree to
  diff against.  Needs to be redone.

rpatch

  Internal command

split-patch

  Some thing someone write to split patches up.  I don't use it.

tag-series

  Assuming you keep pc/*, patches/* and txt/* under CVS revision
  control, tag-series allows you to tag a patchset's individual
  components.  I use

	tag-series s2_5_44-mm3 pc/2.5.44-mm3-series

  which will attach the cvs tag "s2_5_44-mm3" to every .pc, .patch
  and .txt file which is mentioned in the series file
  "pc/2.5.44-mm3-series".

  It will also tag pc/2.5.44-mm3-series, which is a bit redundant
  given that I use a different series file for each patchset release..


toppatch

  Print the name of the topmost patch.  From ./applied-patches

touched-by-patch patch-filename

  List the names of files which are affected by a diff.

unitdiff.py

  Rasmus Andersen's script to convert a diff into minimum-context
  form.  This form has a better chance of applying if you're getting
  nasty rejects.  But patch can and will make mistakes when fed
  small-context input.


Work Practices
==============

I keep the kernel tree, the $P/pc/, $P/patches/ and $P/txt/ contents under
CVS control.  This is important...

I have several "series" files.  I keep these in $P/pc/foo-series and use

	ln -s pc/foo-series series

when I'm working on foo.

If someone sends me a patch I'll do:

	cp ~/whatever patches/his-patch.patch
	pcpatch his-patch
	apatch his-patch

  If apatch fails then run `apatch -f his-patch' and fix the rejects.

	refpatch

  to clean up any fuzz.

	poppatch
	cvs add pc/his-patch.pc patches/his-patch.patch
	cvs commit pc patches

  Now edit ./series and place "his-patch.patch" in the appropriate place.


If you're working on a particular patch (say, "dud-patch") and you
balls something up, just run:

	refpatch	# Generate the crap patch
	poppatch	# Remove it all
	rm patches/dud-patch.patch
	cvs up patches/dud-patch.patch

and all is well.


Getting updates from Linus
==========================

What I do is to grab the latest -bk diff from
http://www.kernel.org/pub/linux/kernel/people/dwmw2/bk-2.5/
and do:

	gzip -d < cs<tab> > patches/linus.patch
	pcpatch linus
	apatch linus | grep diff

               Now fix up all the files which got deleted,
               because there's something wrong with bitkeeper diffs:

	cvs up -ko <missing files from the above diff>

	apatch linus
	$EDITOR linus/linus.txt
	
		Add the changeset number to txt/linus.txt

	refpatch
	poppatch

  Now add "linus.patch" as the first entry in your ./series file and
  start pushing your other patches on top of that.

BUGS
====

Tons and tons.  The scripts are fragile, the error handling is ungraceful and
if you do something silly you can end up in a pickle.

Generally the scripts are very careful to not wreck your files or your
patches.  But they can get the ./applied-patches and ~-files into an
awkward state.

Usually you can sort it out by copying the ~-files back onto the originals
and removing the last line from ./applied-patches.  Or do a "refpatch ;
poppatch ; rm patches/troublesome-patch.patch ; cvs up patches".

If it's really bad, just blow away the entire tree and do a new CVS checkout.


Working on non-kernel projects
==============================

Well it's the same thing.  Say you've downloaded a copy of util-linux
and you want to make a change:

	cd /usr/src
	tar xvfz ~/util-linux.tar.gz
	cd util-linux
	mkdir pc patches txt
	fpatch my-patch sys-utils/rdev.c
	fpatch sys-utils/ipcs.8
	<edit, edit>
	refpatch
	<ship patches/my-patch.patch>

How to balls things up
======================

Well here's one way.  Suppose you have 20 patches applied, and three of
them (say, "p1", "p6" and "p11") all modify "foo.c".

Now you go and change foo.c.

Well, to which patch does that change belong?  You need to decide. 
Let's say you decide "p6".

If you run `refpatch' when "p11" is toppatch then you lose.  The diff
went into p11.

What you can do is:

1:
	poppatch p6
	<edit>
	refpatch
	pushpatch p11
	<test>

  (See why ccache is looking good?)

or

2:
	<edit>
	<test>
	poppatch p6	<hope like hell that the other patches remove cleanly>
	refpatch


Another good way of ballsing up is to cheat.  Say "oh I just want to make
this one-line change".  And "oh, and this one".

Now you're getting in a mess.  It's much, much better to just use the system:

	fpatch junk file1
	fpatch file2
	<edit>
	<play>
	refpatch
	poppatch
	rm pc/junk.pc patches/junk.patch

Merging with -mm kernels
========================

Haven't tried this, but it should work:

- Grab all the patches from broken-out/, place them in your $P/patches/

- Copy my series file into ./series (or $P/pc/akpm-series and symlink it)

- pushpatch 99

And you're off and running.  The nice thing about this is that you can
send me incremental diffs to diffs which I already have.

Or whatever.  I'm fairly handy with diffs nowadays.  Rejects are
expected.  I just prefer to have "one concept per diff".


--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "export_patch: export the patches listed in ./series" 1>&2
	echo "usage: export_patch destination-directory [prefix] " 1>&2
	exit 1
}

DIR="$1"
PREFIX="$2""_"

if [ "$DIR" = "" ]
then
	usage
fi

if [ -e "$DIR" -a ! -d "$DIR" ]
then
	echo "$DIR exists already, but is not a directory." 1>&2
	exit 1
fi

if [ ! -r ./series ]
then
	echo "./series is not readable." 1>&2
	exit 1
fi

mkdir -p "$DIR" || exit 1

count=1
for x in `cat ./series`
do
	fname=`echo "$count" "$PREFIX" "$x" |\
		 awk '{ if ( $2 != "_" )
				printf("p%05d_%s%s\n", $1, $2, $3); 
			else
				printf("p%05d_%s\n", $1, $3); 
		}'`
	if [ ! -r $P/patches/"$x" ]
	then
		echo "$P/patches/"$x" is not readable. skipping." 1>&2
		continue;
	fi
	cp -f $P/patches/"$x" "$DIR"/"$fname" || continue; 
	count=`expr $count + 1`
done


--- NEW FILE ---
#!/bin/sh

insert_line()
{
	PATTERN="$1"
	LINE="$2"
	FILE="$3"
	awk ' BEGIN { found=0; }
		/'"$PATTERN"'/ { 
			print; 
			if (!found)
				printf("%s\n", "'$LINE'"); 
			found=1; 
			next;
		}
		{ print; }
	' < "$FILE"
}

# extract the description from the top of a patch
# filter stdin
# collapse adjacent blank lines to a single blank line
# remove any lines that look like diffstat output
# stop output on encountering a line beginning with '---' (beginning of patch)

	TMPFILE=`mktemp /tmp/xdtmp.XXXXXX` || exit 1
	formail -kfcb -X 'From:' -X 'Subject:' |\
	awk '
		BEGIN { found_end=0; lastone="x"; }
		/^ .* [|] +[0-9]+ [+-]+$/ { 
			#/* we found something like diffstat output... */
			if (found_end == 1) {
				/* we are past end of diffstat, let it pass */
				print;
			}
			next;
		}
		/^ [1-9][0-9]* files changed/ {
			#/* end of diffstat output, stop filtering diffstat */
			found_end=1;
			next;
		}
		/^--- / { exit; }
		{
			#/* collapse adjacent blank lines to 1 blank line */ 
			if ( $0 == "" && lastone == "" )
				next;
			else 
				print; 
		  	lastone=$0;
		}
	' | awk '{ if ($0 == "" && FNR == 1)  next; print; }' > "$TMPFILE"

	descs=`head -10 $TMPFILE | grep -c '^[	]*DESC[ 	]*$'`
	if [ "$descs" = "0" ]
	then
		# DESC is not 1st non blank line in the file
		echo "DESC"
		descs=0
	fi
	edescs=`grep -c '^EDESC$' "$TMPFILE"`
	subjects=`grep -c '^[ 	]*Subject[:]' "$TMPFILE"`
	froms=`grep -c '^[ 	]*From[:]' "$TMPFILE"`
	if [ "$edescs" = "0" ]
	then
		if [ "$subjects" != "0" ]
		then
			insert_line '^Subject[:]' 'EDESC' "$TMPFILE"
		else
			if [ "$froms" != "0" ]
			then
				insert_line '^From[:]' 'EDESC' "$TMPFILE"
			else
				if [ "$descs" = "0" ]
				then
					# blank DESC line...
					echo '(undescribed patch)'
					echo EDESC
					cat "$TMPFILE"
				else
					insert_line '^DESC$' "EDESC" "$TMPFILE"
				fi
			fi
		fi
	else
		cat $TMPFILE
	fi

--- NEW FILE ---
#!/bin/sh

#
# Add a file to a patch.
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: fpatch patchname filename"
	echo "       fpatch filename"
	exit 1
}

if [ $# == 1 ]
then
	PATCH_NAME=$(top_patch)
	FILENAME=$1
elif [ $# == 2 ]
then
	PATCH_NAME=$(stripit $1)
	FILENAME=$2
else
	usage
fi


if is_applied_last $PATCH_NAME
then
	true
else
	if is_applied $PATCH_NAME
	then
		echo $PATCH_NAME is not the last-applied patch
		exit 1
	else
		echo $PATCH_NAME >> $DB
	fi
fi

if file_in_patch $FILENAME $PATCH_NAME
then
	echo File $FILENAME is already in patch $PATCH_NAME
	exit 1
fi

install_file_in_patch $FILENAME $PATCH_NAME


--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "usage: import_patch [ -p prefix-pattern ] patchfile [...]" 1>&2
	exit 1
}

XPATTERN=""
if [ "$1" = "-p" ]
then
	XPATTERN="$2"
	shift; 
	shift;
fi

if [ "$1" = "" ]
then
	usage
fi

if [ ! -e applied-patches ]
then
	touch applied-patches
fi

mkdir -p patches || exit 1
mkdir -p txt || exit 1
mkdir -p pc || exit 1

if [ ! -e ./series ]
then
	touch ./series
	if [ "$?" != "0" ]
	then
		echo "Cannot create ./series" 1>&2
		exit 1
	fi
fi

if [ ! -w ./series ]
then
	echo "./series is not writable." 1>&2
	exit 1
fi

PATTERN='s/^'"$XPATTERN"'//'
for x in $* 
do
	if [ ! -r "$x" ]
	then
		echo "$x does not exist, skipping." 1>&2
		continue
	fi
	patchname=`basename $x .bz2`
	patchname=`basename $patchname .gz`
	patchname=`basename $patchname .Z`
	patchname=`basename $patchname .patch`
	if is_applied $patchname
	then
		echo $patchname is currently applied
		exit 1
	fi
	if [ "$XPATTERN" != "" ]
	then
		patchname=`echo $patchname | sed -e "$PATTERN"`
	fi
	pname=$P/patches/"$patchname".patch
	if [ -r "$pname" ]
	then
		echo "$pname exists already, skipping." 1>&2
		continue
	fi
	case "$x" in
	*.bz2) 
		bunzip2 < "$x" > "$pname"
		;;
	*.gz)
		gunzip < "$x" > "$pname"
		;;
	*.Z)	zcat < "$z" > "$pname"
		;;
	*)	
		cat "$x" > "$pname" || continue 
		;;
	esac
	echo "$patchname".patch >> series
	pcpatch "$pname"
	extract_description < "$pname" >$P/txt/"$patchname".txt
	grep '^[(]undescribed patch[)]$' < $P/txt/"$patchname".txt > /dev/null
	if [ "$?" = "0" ]
	then
		echo "Warning: $patchname has no description." 1>&2
	fi
done


--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: inpatch"
	exit 1
}

if [ $# != 0 ]
then
	usage
fi

if [ -e $DB ]
then
	TOP_PATCH=$(top_patch)
	if [ x$TOP_PATCH != x ]
	then
		cat $P/pc/$TOP_PATCH.pc
	fi
fi

--- NEW FILE ---
#!/bin/sh
#
# Grab a patch frmo kernel.org, install it.
#
# Usage: linus-patch http://www.kernel.org/pub/linux/kernel/people/dwmw2/bk-2.5/cset-1.786.152.7-to-1.798.txt.gz
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

poppatch 999 || die poppatch
wget $1 || die wget
FILE=$(basename $1)
gzip -d < $FILE > $P/patches/linus.patch
pcpatch linus || die pcpatch
(
	echo DESC
	echo $FILE
	echo EDESC
	echo
	echo $FILE
) > $P/txt/linus.txt
rm $FILE

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: mpatch patchname [output_dir]"
	exit 1
}

doit()
{
	echo $* 1>&2
	$* || {
		echo oops
		exit 1 
	}
}

epoch()
{
#	doit touch -t 7001011000.00 $1
	doit touch -t 7001010000.00 $1
}

dirfor()
{
	dir=$(dirname $1)
	if [ ! -d $dir ]
	then
		doit mkdir -p $dir
		RMDIRS="$RMDIRS $dir"
	fi
}

if [ $# == 0 ]
then
	usage
fi

PATCH_NAME=$(stripit $1)
OUTPUT_DIR=$2

FILES=$(cat $P/pc/$PATCH_NAME.pc)
OUT=$P/patches/$PATCH_NAME.patch
TMPOUT=$(mktemp /tmp/patch-$PATCH_NAME-XXXXXX)
TXT=$P/txt/$PATCH_NAME.txt
OLDDIR=$(basename $(/bin/pwd))
NEWDIR=$OLDDIR-$LOGNAME

if is_applied_last $PATCH_NAME
then
	true
else
	echo $PATCH_NAME is not the last-applied patch
	exit 1
fi

doit rm -f $OUT
echo "Placing patch in " $OUT

if [ -e $TXT -a -s $TXT ]
then
	echo >> $OUT
	body $TXT >> $OUT
	echo >> $OUT
	echo >> $OUT
else
	echo "**** No patch description for $PATCH_NAME ****"
fi

rm -f $TMPOUT

for file in $FILES
do
	OLD_FILE="$file"~"$PATCH_NAME"
	if [ ! -e $OLD_FILE ]
	then
		OLD_FILE=/dev/null
	fi
	NEW_FILE=$file
	XDIFF_OPTS=""
	if [ ! -e $NEW_FILE ]
	then
		NEW_FILE=/dev/null
		XDIFF_OPTS="-L $file"
	fi

	echo diff -puN $XDIFF_OPTS $DIFF_OPTS $OLD_FILE $NEW_FILE
	diff -puN $XDIFF_OPTS $DIFF_OPTS $OLD_FILE $NEW_FILE | p0-2-p1 $OLDDIR $NEWDIR >> $TMPOUT
done
diffstat -p1 $TMPOUT >> $OUT 2>/dev/null
echo >> $OUT
cat $TMPOUT >> $OUT
echo >> $OUT
echo "_" >> $OUT
rm -f $TMPOUT

--- NEW FILE ---
#!/bin/sh

usage()
{
	echo "Usage: new-kernel linux-2.4.2-pre2 linux-2.4.3-pre3 linux-2.4.3 patch.gz cvs-dir"
	exit 1
}

wantdir()
{
	if [ x$1 = x ]
	then
		usage
	fi
	if [ ! -d $1 ]
	then
		echo "directory $1 does not exist"
		usage
	fi
}

wantfile()
{
	if [ x$1 = x ]
	then
		usage
	fi
	if [ ! -f $1 ]
	then
		echo "file $1 does not exist"
		usage
	fi
}

doit()
{
	echo $* 1>&2
	$* || {
		echo oops
		exit 1 
	}
}


CURRENT_KERNEL=$1
NEXT_KERNEL=$2
BASE_KERNEL=$3
PATCH_FILE=$4
CVS_DIR=$5

TEMP_PATCH=$(mktemp /tmp/patch-XXXXXX)
MY_DIFF="$CURRENT_KERNEL"--"$NEXT_KERNEL"

wantdir $CURRENT_KERNEL
wantdir $BASE_KERNEL
wantdir $CVS_DIR
wantfile $PATCH_FILE

doit rm -rf $NEXT_KERNEL
doit cp -a $BASE_KERNEL $NEXT_KERNEL
doit rm -f $TEMP_PATCH
doit gunzip < $PATCH_FILE > $TEMP_PATCH
cd $NEXT_KERNEL
doit patch -p1 --dry-run -i $TEMP_PATCH
doit patch -p1 -s -i $TEMP_PATCH
echo cd ..
cd ..

echo diff -uNrp $CURRENT_KERNEL $NEXT_KERNEL
diff -uNrp $CURRENT_KERNEL $NEXT_KERNEL > $MY_DIFF

echo cd $CVS_DIR
cd $CVS_DIR
doit patch -p1 --dry-run -s -i ../$MY_DIFF
doit patch -p1 -s -i ../$MY_DIFF
cvs-take-patch ../$MY_DIFF
cvs commit -m "'doing $NEXT_KERNEL'"
cvs update -ko -d -P

TAG=$(echo $NEXT_KERNEL | sed -e 's@\.@_@g')
cvs tag $TAG
rm -f $TEMP_PATCH

--- NEW FILE ---
#!/bin/sh
#
# Usage: p0-2-p1 olddir newdir
#
OLDDIR=$1
NEWDIR=$2

sed -e "s/^--- \([^\/].*\)/--- $OLDDIR\/\1/" |
sed -e "s/^+++ \([^\/].*\)/+++ $NEWDIR\/\1/"


--- NEW FILE ---
#!/bin/sh

#
# Bring up a patched file in diff.  We show the diffs
# in the topmost patch, unless it was specified
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: pdiff [patchname] filename"
	echo "       pdiff [patchname] -"
	exit 1
}

if [ $# == 1 ]
then
	PATCH_NAME=$(top_patch)
	FILENAME=$1
elif [ $# == 2 ]
then
	PATCH_NAME=$(stripit $1)
	FILENAME=$2
else
	usage
fi

if ! is_applied $PATCH_NAME
then
	echo $PATCH_NAME is not applied
	exit 1
fi

doit()
{
	filename=$1
	unpatched_file=$filename"~"$PATCH_NAME
	need_file_there $filename
	if [ -e $unpatched_file ]
	then
		diff -u $unpatched_file $filename
	else
		echo pdiff: $filename appears to not be in $PATCH_NAME
	fi
}

if [ x"$FILENAME" = "x-" ]
then
	FILENAME=$(cat $P/pc/$PATCH_NAME.pc)
fi

for i in $FILENAME
do
	doit $i
done

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

desc1()
{
	PATCH=$(stripit $1)
	TXT=$P/txt/$PATCH.txt
	echo $PATCH.patch
	desc < $TXT
	echo
}

for i in $*
do
	desc1 $i
done

--- NEW FILE ---
DB=applied-patches

#
# Work out where the user's pc/, patch/ and txt/ directories live.
#
# If the user specified PATCHSCRIPTS in environment then use that (it's
# probably a relative path)
#
# If there is a directory ./patch-scripts then use that
#
# Otherwise use "."
#

if [ x$PATCHSCRIPTS != x ]
then
	P=$PATCHSCRIPTS
elif [ -d ./patch-scripts ]
then
	P=./patch-scripts
elif [ -d ./patches ]
then
	P=.
else
	echo "could not locate your pc/ and patches/ directories"
	exit 1
fi

top_patch()
{
	tail -1 $DB
}

die()
{
	echo error: $*
	exit 1
}

is_numeric()
{
	if echo $1 | egrep '^[0-9]*$' > /dev/null
	then
		return 0
	fi
	return 1
}

is_applied_last()
{
	name="$(stripit $1)"
	top_patch >$DB.1
	if grep "^$name$" "$DB.1" > /dev/null 2>&1
	then
		rm $DB.1
		return 0
	else
		rm $DB.1
		return 1
	fi
}

is_applied()
{
	name=$(stripit "$1")
	if grep "^$name$" "$DB" > /dev/null 2>&1
	then
		return 0
	else
		return 1
	fi
}

can_apply()
{
	if patch -p1 --dry-run -i "$1" -f
	then
		return 0
	else
		return 1
	fi
}

can_remove()
{
	if patch -R -p1 --dry-run -i $P/patches/"$1".patch -f
	then
		return 0
	else
		return 1
	fi
}

remove_from_db()
{
	tmpfile=$(mktemp /tmp/p_XXXXXX)
	name="$1"
	sed -e "/^$name$/d" < "$DB" > $tmpfile
	mv $tmpfile "$DB"
}

stripit()
{
	ret=$(basename $1)
	ret=$(echo $ret | sed -e 's/\.patch$//')
	ret=$(echo $ret | sed -e 's/\.pc$//')
	ret=$(echo $ret | sed -e 's/\.txt$//')
	echo $ret
}

top_is_current()
{
	patch_name=$(top_patch)
	if [ x$patch_name == x ]
	then
		return 1
	else
		patch_file=$P/patches/"$patch_name".patch
		files=$(cat $P/pc/$patch_name.pc)
		for file in $files
		do
			if [ $file -nt $patch_file ]
			then
				echo $file newer than $patch_file
				return 0
			fi
		done
	fi
	return 1
}

need_top_current()
{
	if top_is_current
	then
		echo "Error: Top patch is not up-to-date"
		exit 1
	fi
}

warn_top_current()
{
	if top_is_current
	then
		echo "Warning: Top patch is not up-to-date"
	fi
}

file_in_patch()
{
	file=$1
	patch=$2

	if [ -e $P/pc/$patch.pc ]
	then
		if grep "^"$file"$" $P/pc/$patch.pc > /dev/null
		then
			return 0
		fi
	fi
	return 1
}

# copy_file_to_bup filename patchname
copy_file_to_bup()
{
	file=$1
	patch=$2
	bup="$file"~"$patch"

	if [ -e $bup ]
	then
		echo "Cannot install file $file in patch $patch: backup $bup exists"
		exit 1
	fi

	if [ -e $file ]
	then
		cp $file "$file"~"$patch"
	else
		echo "file $file appears to be newly added"
	fi
}

install_file_in_patch()
{
	file=$1
	patch=$2

	copy_file_to_bup $file $patch
	echo $file >> $P/pc/$patch.pc
#	touch $P/txt/$patch.txt
}

need_file_there()
{
	if [ ! -e $1 ]
	then
		echo "File $1 does not exist"
		exit 1
	fi
}

desc()
{
	state=0
	while read x
	do
		if [ x"$x" = xDESC ]
		then
			state=1
		elif [ x"$x" = xEDESC ]
		then
			state=0
		elif [ $state = 1 ]
		then
			echo "  $x"
		fi
	done
}

body()
{
	file=$1

	did_stuff=0
	while read x
	do
		if [ x"$x" = xEDESC ]
		then
			cat
			did_stuff=1
		fi
	done < $file

	if [ $did_stuff = 0 ]
	then
		cat $file
	fi
}

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "pcpatch: recreate the pc file from patches/{patchname}.patch"
	exit 1
}

doit()
{
	echo $* 1>&2
	$* || {
		echo oops
		exit 1 
	}
}

if [ $# != 1 -o "$1" = "help" ]
then
	usage
fi
PATCH=$1
PATCH_NAME=$(stripit $PATCH)
PC=$P/pc/$PATCH_NAME.pc

if [ ! -e $P/patches/$PATCH_NAME.patch ] 
then
	echo "$P/patches/$PATCH_NAME.patch does not exist"
	exit 1
fi

if is_applied "$PATCH"
then
	echo $PATCH is applied!
	exit 1
fi

touched-by-patch $P/patches/$PATCH_NAME.patch > $PC
echo Recreated $PC

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: poppatch [npatches]"
	exit 1
}

doit()
{
	echo $* 1>&2
	$* || {
		echo oops
		exit 1 
	}
}

if [ $# -gt 1 ]
then
	usage
fi

NR=1
STOP_AT=""
if [ $# -eq 1 ]
then
	if is_numeric $1
	then
		NR=$1
	else
		NR=1000
		STOP_AT=$(stripit $1)
	fi
fi

pop_one()
{
	TOP_PATCH=$(top_patch)
	if [ x$TOP_PATCH == x ]
	then
		echo "no patches applied"
		exit 0
	else
		popped_patch="$(top_patch)"
		if ! rpatch $(top_patch)
		then
			echo still at $(top_patch)
			exit 1
		fi
		echo
	fi
}

for i in $(seq 1 $NR)
do
	pop_one
	if [ x$STOP_AT != "x" ]
	then
		if [ $STOP_AT == $(toppatch) ]
		then
			exit 0
		fi
	fi
done

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

if [ $# -ne 1 ]
then
	echo "Usage prep-patch patchname"
	exit 1
fi

PATCHNAME=$(stripit $1)

xcb -s 2 < $P/patches/$PATCHNAME.patch
head -2 $P/txt/$PATCHNAME.txt | tail -1 | tr -d '\n' | xcb -s 1

--- NEW FILE ---
#!/bin/sh

# print out patch status.  Usage: pstatus [ patchfile ... ]
#
# Stephen Cameron <[email protected]>
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

if [ ! -f ./series ]
then
	echo "./series does not exist." 1>&2
	exit 1
fi

if [ ! -d ./patches ]
then
	echo "Directory ./patches does not exist." 1>&2
	exit 1
fi


PATCHLIST="$*"
if [ "$PATCHLIST" = "" ]
then
	series_optimize=yes
	PATCHLIST=`cat series | sed -e 's/[.]patch[ 	]*$//'`
	SORTSERIES=`mktemp /tmp/ser.XXXXXX` || exit 1 
	SORTPATCHES=`mktemp /tmp/pat.XXXXXX` || exit 1
	sed -e 's/^[ 	]//' -e 's/[.]patch[ 	]*$//' < series | \
		sort > $SORTSERIES 
	exists="`echo $P/patches/*.patch 2>/dev/null`"
	if [ "$exists" != "$P/patches/*.patch" ]
	then
		ls -1 $P/patches/*.patch | sed -e 's/^.*\/patches\///' \
			-e 's/[.]patch[ 	]*$//' | sort > $SORTPATCHES
		PATCHLIST="$PATCHLIST"" `comm -1 -3 $SORTSERIES $SORTPATCHES`"
	fi
	rm -f $SORTPATCHES $SORTSERIES
else
	series_optimize=no
fi

NSERIES=`wc -l series | awk '{ print $1; }'`
series=1
for PATCH_NAME in $PATCHLIST 
do
	PATCH_NAME=$(stripit $PATCH_NAME)
	# see if this patch even exists
	if [ ! -f $P/patches/"$PATCH_NAME".patch ]
	then
		echo "$PATCH_NAME does not exist."
		continue
	fi
	# see if this patch is applied
	applied="-"
	if [ -f applied-patches ]
	then 
		grep '^'"$PATCH_NAME"'$' applied-patches > /dev/null
		if [ "$?" = "0" ]
		then
			applied="a"
		fi
	fi

	# figure the status of this patch, that is, 
	# if it needs changelog, pcpatch, refpatch

	stat=""
	if [ ! -f $P/txt/"$PATCH_NAME".txt ]
	then
		stat="changelog "
	fi
	if [ ! -f $P/pc/"$PATCH_NAME".pc ]
	then
		stat="$stat""pcpatch "
	elif [ "$applied" != '-' ]
	then
		rpatch=n

		# for each file this patch touches
		for y in `cat $P/pc/"$PATCH_NAME".pc`
		do
			# is the patch adding the file?
			if [ ! -e "$y"'~'"$PATCH_NAME" -a -f "$y" ]
			then
				# file is newer than the patch?
				if [ "$y" -nt $P/patches/"$PATCH_NAME".patch ]
				then
					rpatch=y
					stat="$stat""refpatch "
					break
				fi
			else
				# modified file is newer than the patch?
				if [ "$y"'~'"$PATCH_NAME" -nt \
					$P/patches/"$PATCH_NAME".patch ]
				then
					rpatch=y
					stat="$stat""refpatch "
					break
				fi
				if [ "`toppatch`" = "$PATCH_NAME" -a \
					"$y" -nt $P/patches/"$PATCH_NAME".patch ]
				then
					# toppatch, so check if the file 
				        # is newer than the patch?
					rpatch=y
					stat="$stat""refpatch "
					break
				fi
			fi
		done
	fi
	# check if they changed the changelog recently
	if [ "$rpatch" = "n" -a -f $P/txt/"$PATCH_NAME".txt \
		-a $P/txt/"$PATCH_NAME".txt -nt \
		$P/patches/"$PATCH_NAME".patch ]
	then
		rpatch=y
		stat="$stat""refpatch "
	fi
	if [ "$stat" != "" ]
	then
		stat="Needs ""$stat"
	fi

	if [ "$series_optimize" != "yes" ]
	then
		# have to find the series number the hard way.
		series=`grep -n '^'"$PATCH_NAME"'\.patch$' series |\
			awk -F: '{ printf "%d", $1}' `
		if [ "$series" = "" ]
		then
			series="?"
		fi
	fi

	echo "$series":"$applied":"$PATCH_NAME $stat"

	if [ "$series_optimize" = "yes" ]
	then
		if [ "$series" != "?" ]
		then
			series=`expr $series + 1`
			if [ $series -gt $NSERIES ]
			then 
				series="?"
			fi
		fi
	fi
done 

--- NEW FILE ---
#!/bin/sh

#
# Bring up a patched file in tkdiff.  We show the diffs
# in the topmost patch, unless it was specified
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: ptkdiff filename ..."
	echo "       ptkdiff -"
	exit 1
}

PATCH_NAME=$(top_patch)

doit()
{
	filename=$1
	unpatched_file=$filename"~"$PATCH_NAME
	need_file_there $filename
	if [ -e $unpatched_file ]
	then
		tkdiff $unpatched_file $filename
	else
		echo ptkdiff: $filename appears to not be in $PATCH_NAME
	fi
}

if [ x"$1" = "x-" ]
then
	FILENAME=$(cat $P/pc/$PATCH_NAME.pc)
else
	FILENAME="$*"
fi

for i in $FILENAME
do
	doit $i &
done

--- NEW FILE ---
#!/bin/sh

#
# Add next patch in series
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: pushpatch [npatches]"
	exit 1
}

opt_force=0

for i in $*
do
	case "$i" in
	-f)
		opt_force=1;;
	*)
		if [ -n "$NR" -o -n "$STOP_AT" ]
		then
			usage
		fi
		if is_numeric $i
		then
			NR=$i
		else
			NR=1000
			STOP_AT=$(stripit $i)
		fi;;
	esac
done

[ $opt_force = 1 ] && force="-f"

SERIES=series

if [ ! -e $SERIES ]
then
	echo 'File "series" not found'
	exit 1
fi

push_one()
{
	top=$(toppatch)
	if [ x"$top" == x ]
	then
		todo=$(head -1 $SERIES)
	else
		last_in_series=$(stripit $(tail -1 $SERIES))
		if [ $last_in_series == $top ]
		then
			echo "Series fully applied.  Ends at $top"
			exit 0
		fi
		todo=$(grep -C1 "^$top\.patch" $SERIES | tail -1)
		if [ x$todo = x ]
		then
			todo=$(head -1 $SERIES)
		fi
	fi

	apatch $force $todo
}

for i in $(seq 1 $NR)
do
	push_one
	if [ x$STOP_AT != "x" ]
	then
		if [ $STOP_AT == $(toppatch) ]
		then
			exit 0
		fi
	fi
done

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: refpatch"
	exit 1
}

doit()
{
	echo $* 1>&2
	$* || {
		echo oops
		exit 1 
	}
}

if [ $# != 0 ]
then
	usage
fi

TOP_PATCH=$(top_patch)
mpatch $* $(top_patch)
echo "Refreshed $TOP_PATCH"

--- NEW FILE ---
#!/bin/sh
# Extract names of new files from a patch, print them out

PATCHFILE=$1
case "$PATCHFILE" in
*.gz) CMD="gzip -d < $PATCHFILE";;
*)    CMD="cat $PATCHFILE";;
esac

TMP=$(mktemp /tmp/rbp-XXXXXX)

eval $CMD | egrep '^\+\+\+.*1970|\+\+\+.*1969' > $TMP
sed -e 's@[^/]*/\([^ 	]*\).*@\1@' < $TMP | sed -e 's@^linux/@@' | sort
rm -f $TMP

--- NEW FILE ---
#!/bin/sh
. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}
OLD=$(stripit $1)
NEW=$(stripit $2)

mv $P/pc/$OLD.pc $P/pc/$NEW.pc
mv $P/patches/$OLD.patch $P/patches/$NEW.patch
mv $P/txt/$OLD.txt $P/txt/$NEW.txt

cvs remove $P/pc/$OLD.pc
cvs remove $P/patches/$OLD.patch
cvs remove $P/txt/$OLD.txt

cvs add $P/pc/$NEW.pc
cvs add $P/patches/$NEW.patch
cvs add $P/txt/$NEW.txt

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: rolled-up-patch"
	exit 1
}

if [ $# != 0 ]
then
	usage
fi

RUP=$(mktemp /tmp/rup-XXXXXX)
rm -f $RUP

for i in $(cat applied-patches)
do
	patch_name=$(stripit $i)
	cat $P/pc/$patch_name.pc
done | sort | uniq > $RUP

kdiff $(cat $RUP)
rm -f $RUP

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

do_remove()
{
	if patch -R -p1 -s -i $P/patches/"$1".patch
	then
		true
	else
		echo SOMETHING WENT WRONG
		exit 1
	fi
}

kill_old_ones()
{
	FILES=$(cat $P/pc/$1.pc)
	for file in $FILES
	do
		rm -f "$file"~"$1"
	done
}

usage()
{
	echo "Usage: rpatch patchname"
	exit 1
}

if [ $# == 0 ]
then
	usage
fi

PATCH_NAME=$(stripit $1)

warn_top_current

if is_applied "$PATCH_NAME"
then
	if can_remove "$PATCH_NAME"
	then
		do_remove "$PATCH_NAME"
		kill_old_ones "$PATCH_NAME"
		remove_from_db "$PATCH_NAME"
	else
		echo "$PATCH_NAME" does not remove cleanly
		exit 1
	fi
else
	echo "$PATCH_NAME" is not applied
	exit 1
fi

top=$(top_patch)
if [ x"$top" == x ]
then
	msg="no patches applied"
else
	msg="now at $top"
fi

echo Removed $PATCH_NAME, $msg


--- NEW FILE ---
#!/usr/bin/perl -w
$out = "";
while (<>) {
	next if (/^Only/);
	next if (/^Binary/);
	if (/^diff/ || /^Index/) {
		if ($out) {
			close OUT;
		}
		(@out) = split(' ', $_);
		shift(@out) if (/^diff/);
		$out = pop(@out);
		$out =~ s:/*usr/:/:;
		$out =~ s:/*src/:/:;
		$out =~ s:^/*linux[^/]*::;
		$out =~ s:\(w\)::;
		next if ($out eq "");
		$out = "/var/tmp/patches/$out";
		$dir = $out;
		$dir =~ s:/[^/]*$::;
		print STDERR "$out\n";
		system("mkdir -p $dir");
		open(OUT, ">$out") || die("cannot open $out");
	}
	if ($out) {
		print OUT $_;
	}
}


--- NEW FILE ---
#!/bin/sh

# tag-series tagname series-file-name
#
# Does a `cvs tag tagname' of all the .pc, .txt and .patch files mentioned
# in series-file-name.  Also tags series-file-name.
#

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

# tag_one tag patchname
#
tag_one()
{
	PN=$(stripit $2)
	if [ -r $P/txt/$PN.txt ]
	then
		cvs tag $1 $P/pc/$PN.pc $P/patches/$PN.patch $P/txt/$PN.txt
	else
		cvs tag $1 $P/pc/$PN.pc $P/patches/$PN.patch
	fi
}

if [ $# -ne 2 ]
then
	echo Usage: tag-series tagname series-file-name
	exit 1
fi

TAG=$1
SERIES=$2

for p in $(cat $SERIES)
do
	tag_one $TAG $p
done
cvs tag $TAG $SERIES

--- NEW FILE ---
#!/bin/sh

. patchfns >/dev/null || . /usr/lib/patch-scripts/patchfns >/dev/null || { \
	echo "Impossible to find my library 'patchfns'."
	echo "Check your install, or go to the right directory"
	exit 1
}

usage()
{
	echo "Usage: toppatch"
	exit 1
}

if [ $# != 0 ]
then
	usage
fi

if [ -e $DB ]
then
	TOP_PATCH=$(top_patch)
	if [ x$TOP_PATCH != x ]
	then
		echo $TOP_PATCH
	fi
fi

--- NEW FILE ---
#!/bin/sh
# Extract names of new files from a patch, print them out

PATCHFILE=$1
case "$PATCHFILE" in
*.gz) CMD="gzip -d < $PATCHFILE";;
*)    CMD="cat $PATCHFILE";;
esac

TMP=$(mktemp /tmp/tbp-XXXXXX) || exit 1
TMP2=$(mktemp /tmp/tbp2-XXXXXX) || exit 1

eval $CMD | egrep '^\+\+\+ |^\-\-\- ' > $TMP

cat $TMP | sed -e 's@[^/]*/\([^ 	]*\).*@\1@' \
	 | grep -v '^dev\/null$' \
	 | sort \
	 | uniq \
	 > $TMP2

rm -f $TMP
grep < $TMP2 '^[+][+][+]' > /dev/null
if [ "$?" = "0" ]
then
	echo "WARNING: $PATCHFILE appears to be -p0 form rather than -p1." 1>&2
	echo "         Use "\'"p0-2-p1 . . < $PATCHFILE"\'" to fix" 1>&2
	awk '{ print $2 }' < $TMP2
else
	cat $TMP2
fi | grep -v '~'

rm -f $TMP2

--- NEW FILE ---
#!/usr/bin/python

import sys
import re
import string

#TODO
# clean up rest/file
# clean up +6 and like (assumptions). should be turned into 'find'
# make regession tests for all cases (Only in, etc)

try:
        filename = sys.argv[1]
except:
        print 'requires a file name'
        sys.exit(1)

filefd = open(filename)
file = filefd.read()
filefd.close()

rest = file
pat = "(^(?:diff .*\n)?--- .*\n\+\+\+ .*)?\n@@ -(\d+),?(\d+)? \+(\d+),?(\d+)? @@|^(Only in .*)"
startpat = re.compile(pat, re.M)

pos = 0
oldpos = 0
filelen = len(rest)
oldrest = ""
while(1):
        rexp = startpat.search(rest)
        if not rexp:
                break

	if rexp.group(6):
		print rexp.group(6)
		rest = rest[rexp.end(6)+1:]
		continue
		
	header = rexp.group(1)
        orgfile_start = string.atoi(rexp.group(2))
	if rexp.group(3):
		orgfile_len = string.atoi(rexp.group(3))
	else:
		orgfile_len = -1
        newfile_start = string.atoi(rexp.group(4))
	if rexp.group(5):
		newfile_len = string.atoi(rexp.group(5))
	else:
		newfile_len = -1
        rest = rest[rexp.start(2):]
        rest = rest[string.find(rest, "\n")+1:]

	rexp2 = startpat.search(rest)
	if rexp2:
		if rexp2.start(6) != -1:
			oldrest = rest[rexp2.start(6)-1:]
			rest = rest[:rexp2.start(6)]
		elif rexp2.start(1) == -1:
			oldrest = rest[rexp2.start(2)-5:]
			rest = rest[:rexp2.start(2)-4]
		else:
			oldrest = rest[rexp2.start(1)-1:]
			rest = rest[:rexp2.start(1)]
	else:
		oldrest = rest

#	pos = filelen - len(oldrest)
#	if pos - oldpos > 100:
#		sys.stderr.write(`pos`+'/'+`filelen`+'\n')
#		oldpos = pos

	first = 1
	oldminuses = 0
	oldplusses = 0
	oldoffset = 0
	while(1):
		#erstat early line stuff med lookbehind paa {1,2}-dims
		#nedenfor RAA
	        linepat = "^([^-+\n]*)\n?(((^[-+].*\n)|^(.*\n){1,2}(?=^[-+].*\n))+)(.*)\n?"
		compat = re.compile(linepat, re.M)
	        rexp = compat.search(rest)
	        if not rexp:
	                break

		prematch = rexp.group(1)
	        match = rexp.group(2)
		muddle = len(match)

#		print rest
#		print 'prematch ', rexp.start(1), rexp.end(1), prematch
#		print 'match ---------'
#		print match
#		print 'match --------'

		# dump unwanted early lines...
		if match[0] != "+" and match[0] != "-":
			while(1):
				next = string.find(match, '\n')
				if next == -1:
					break
				if match[next+1] == "+" or match[next+1] == "-":
					prematch = match[:next]
					match = match[next+1:]
					break
				match = match[next+1:]


#		print 'prematch ', rexp.start(1), rexp.end(1), len(prematch)
#		print '('+prematch+')'
#		if prematch == ' ':
#			print 'space'
		muddle = muddle - len(match)

	        lines = string.count(match, "\n")
		compat = re.compile("^-", re.M)
	        minuses = len(compat.findall(match))
		compat = re.compile("^\+", re.M)
	        plusses = len(compat.findall(match))
	        orgsize = minuses + 2 + (lines - minuses - plusses)
	        newsize = plusses + 2 + (lines - minuses - plusses)

		noeol = "^(\\\ No newline at end of file)$"
		compnoeol = re.compile(noeol, re.M)
		if compnoeol.search(match) or compnoeol.search(rexp.group(6)):
			orgsize = orgsize - 1
			newsize = newsize - 1
			
		coherent = 0
		if lines - plusses == 0:
			coherent = 1
		elif lines - minuses == 0:
			coherent = 1

		# RAA FIXME
		if not len(prematch):#or len(prematch) == 1 and prematch == ' ':
			orgsize = orgsize -1
			newsize = newsize -1
		if rexp.start(6) == rexp.end(6):
			orgsize = orgsize -1
			newsize = newsize -1

#	        print "lines in match: ", lines
#	        print "number of minuses: ", minuses
#	        print "number of plusses: ", plusses
	
	        matchpos = rexp.start(2) + muddle
	        offset =  string.count(rest[:matchpos], "\n")

#		print 'offset/oldoffset: ', offset,oldoffset
#		print 'oldplusses/oldminuses: ', oldplusses, oldminuses
#		print 'orgfile_start/newfile_start: ', orgfile_start, newfile_start

	        orgstart = orgfile_start + offset + oldoffset - oldplusses
	        newstart = newfile_start + offset - oldminuses + oldoffset

		# RAA: Bwadr. Fix antagelse om prematch paa en anden
		# maade
		orgstartmod = 0
		newstartmod = 0
		if orgfile_start == 1 and not len(prematch):
			orgstartmod = 1
		if newfile_start == 1 and not len(prematch):
			newstartmod = 1
		if orgfile_start == 0 and orgfile_len == 0:
			orgstartmod = 1
			# RAA Hack!
			plusses = plusses + 1
			minuses = minuses +1
		if newfile_start == 0 and newfile_len == 0:
			newstartmod = 1
			# RAA Hack!
			plusses = plusses + 1
			minuses = minuses +1
		
		if header and first:
			print header
			first = 0

		# should the start(1) == 0 be orgstart == 1? RAA
	        if orgstart == 1 and newstart == 1 and plusses == 0 and coherent:
	                print "@@ -"+`orgstart`+","+`orgsize`+" +"+`newstart`+" @@"
	                print match[:string.rfind(match, "\n")]
	                print rexp.group(6)
	        elif rexp.start(6) == rexp.end(6) and plusses == 0 and coherent:
			if orgstartmod:
				orgstart = orgstart + 1
			if newstartmod:
				newstart = newstart + 1
	                print "@@ -"+`orgstart-1`+","+`orgsize`+" +"+`newstart-1`+" @@"
	                print prematch
	                print match[:string.rfind(match, "\n")]
	        elif orgstart == 1 and orgstart == 1 and minuses == 0 and coherent:
	                print "@@ -"+`orgstart`+" +"+`newstart`+","+`newsize`+" @@"
	                print match[:string.rfind(match, "\n")]
	                print rexp.group(6)
	        elif rexp.start(6) == rexp.end(6) and minuses == 0 and coherent:
			if orgstartmod:
				orgstart = orgstart + 1
			if newstartmod:
				newstart = newstart + 1
	                print "@@ -"+`orgstart-1`+" +"+`newstart-1`+","+`newsize`+" @@"
	                print prematch
	                print match[:string.rfind(match, "\n")]
	        else:
			if orgstartmod:
				orgstart = orgstart + 1
			if newstartmod:
				newstart = newstart + 1
	                print "@@ -"+`orgstart-1`+","+`orgsize`+" +"+`newstart-1`+","+`newsize`+" @@"
			if len(prematch):
				print prematch
	                print match[:string.rfind(match, "\n")]
			if rexp.start(6) != rexp.end(6):
	                	print rexp.group(6)
	
        	rest = rest[rexp.end(6):]
		oldminuses = minuses + oldminuses
		oldplusses = plusses + oldplusses
		oldoffset = oldoffset + offset + lines #include match()-lines


	rest = oldrest



-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility 
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/