summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in15
-rw-r--r--configure.ac4
-rw-r--r--doc/Makefile18
-rw-r--r--doc/README.in78
-rw-r--r--doc/consider-for-docs-1.mail109
-rw-r--r--doc/consider-for-docs-2.mail77
-rw-r--r--doc/consider-for-docs-3.mail56
-rw-r--r--doc/docco.txt717
-rw-r--r--doc/main.tex716
-rw-r--r--doc/quilt.pdfbin0 -> 169217 bytes
-rw-r--r--po/de.po31
-rw-r--r--po/fr.po31
-rw-r--r--po/quilt.pot30
-rw-r--r--quilt.changes34
-rw-r--r--quilt.spec.in2
-rw-r--r--quilt/diff.in2
-rw-r--r--quilt/files.in38
-rw-r--r--quilt/fold.in122
-rwxr-xr-xquilt/gendiff.in4
-rw-r--r--quilt/refresh.in2
-rw-r--r--quilt/setup.in1
-rwxr-xr-xscripts/apatch.in76
-rw-r--r--scripts/patchfns.in3
-rwxr-xr-xscripts/rpatch.in22
-rw-r--r--test/failpop.test27
-rw-r--r--test/fold.test57
-rw-r--r--test/one.test4
27 files changed, 1113 insertions, 1163 deletions
diff --git a/Makefile.in b/Makefile.in
index 54b6e0f..91f480b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -57,7 +57,7 @@ DIRT += $(BIN_IN:%=bin/%)
QUILT_IN := add applied delete diff files import new next patches \
pop previous push refresh remove series setup top unapplied \
- fork snapshot edit gendiff
+ fold fork snapshot edit gendiff
QUILT_SRC := $(QUILT_IN:%=%.in)
QUILT := $(QUILT_IN)
@@ -78,9 +78,9 @@ DIRT += lib/backup-files lib/backup-files.o
DOC_IN := README
DOC_SRC := $(DOC_IN:%=doc/%.in)
DOC := $(DOC_IN)
-SRC += $(DOC_SRC) doc/docco.txt
-SRC += doc/consider-for-docs-1.mail doc/consider-for-docs-2.mail \
- doc/consider-for-docs-3.mail doc/sample.quiltrc
+SRC += $(DOC_SRC)
+SRC += doc/main.tex doc/quilt.pdf doc/Makefile \
+ doc/sample.quiltrc
DIRT += $(DOC_IN:%=doc/%)
MAN1 := bin/guards.1
@@ -132,8 +132,7 @@ reference : $(QUILT:%=quilt/%)
echo; \
(bash -c ". scripts/patchfns ;LC_ALL=C . $$i -h"); \
done | \
- sed -e 's/^Usage: \?// ; p ; d' \
- -e 's/^/ /'
+ sed -e 's/^Usage: \?//' -e 's/^/ /'
bin/guards.1 : bin/guards
mkdir -p $$(dirname $@)
@@ -216,7 +215,9 @@ install : scripts
@INSTALL@ -d $(BUILD_ROOT)$(docdir)/$(PACKAGE)-$(VERSION)/
@INSTALL@ -m 644 doc/README \
- $(BUILD_ROOT)$(docdir)/$(PACKAGE)-$(VERSION)/
+ $(BUILD_ROOT)$(docdir)/$(PACKAGE)-$(VERSION)/
+ @INSTALL@ -m 644 doc/quilt.pdf \
+ $(BUILD_ROOT)$(docdir)/$(PACKAGE)-$(VERSION)/
@INSTALL@ -d $(BUILD_ROOT)$(mandir)/man1
@INSTALL@ -m 644 $(MAN1) $(BUILD_ROOT)$(mandir)/man1/
diff --git a/configure.ac b/configure.ac
index 9903352..2fab014 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,8 +1,8 @@
dnl Process this file with autoconf to produce a configure script.
-AC_INIT([quilt],[0.28_CFS6],[quilt-dev@nongnu.org])
+AC_INIT([quilt],[0.29_CFS6],[quilt-dev@nongnu.org])
AC_CONFIG_AUX_DIR(config)
AC_PREREQ(2.53)
-AC_REVISION ($Revision: 1.17.2.5 $)
+AC_REVISION ($Revision: 1.17.2.6 $)
PACKAGE_RELEASE=1
AC_SUBST(PACKAGE_RELEASE)
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..ba488ba
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,18 @@
+all : quilt.pdf
+
+quilt.ps : quilt.dvi
+ dvips -t letter -o $@ $<
+
+quilt.pdf: main.tex
+ pdflatex -t letter $< && \
+ mv main.pdf $@
+
+quilt.dvi : main.tex
+ latex $< && \
+ mv main.dvi $@
+
+clean:
+ rm -f main.{dvi,log,aux}
+
+distclean: clean
+ rm -f quilt.{ps,pdf,dvi}
diff --git a/doc/README.in b/doc/README.in
index 83f252c..0f080d2 100644
--- a/doc/README.in
+++ b/doc/README.in
@@ -1,82 +1,8 @@
The scripts in this package simplify working with a series of patches.
The usual tasks like applying, refreshing and reversing are supported.
-docco.txt contains Adrew Morton's description of his suite of patch
-scripts. These scripts are based on Andrew's scripts, but include many
-changes. Please keep this in mind when reading Andrew's documentation.
-
-
-Concepts
-========
-
-(Please see docco.txt.)
-
-The scripts maintain a stack of patches, on top of which additional
-patches can be applied, and from with patches can be removed. The list of
-patches is kept in a file (searched for in this order in
-.pc/series, series, patches/series).
-
-The scripts keep meta information in the .pc/ directory. The .pc/
-directory contains:
-
- .pc/applied-patches
- The list of currently applied patches.
-
- .pc/patch/.pc (for each applied patch)
- A list of files modified by the patch.
-
- .pc/patch/ (for each applied patch)
- Copies of the files that the patch modifies,
- before modifying. The original versions of
- the files are needed for refreshing patches,
- and for ensuring that removing a patch does
- recreate the original file contents.
-
-
-Operation
-=========
-
-Patches to be applied must be listed in the series file.
-
-Patches are applied with pushpatch, and are removed with poppatch.
-
-Refpatch refreshes a patch.
-
-New patches can be added at the current position in the patch sequence
-with newpatch.
-
-Additional files to be modified can be added to a patch with patchadd.
-
-
-Installation
-============
-
-To start using the scripts the working directory must contain:
-
- patches/
- Patches to work with.
-
- series (or patches/series)
- List of patches in order of applying.
-
-The scripts will create the .pc/ directory that contains the meta
-information needed for managing the patches automatically.
-
-
-Series file
-===========
-
-The patches that are relevant for a project must be listed in the file
-series, which is searched for in .pc/, ./ and patches/ in this order.
-The patches will be applied in the order given. The series file has
-the following format:
-
- # Comment
- subdir/patch-file-name.patch [-pN]
-
-The location of patches is specified relative to the patches/ directory.
-Optionally a strip level (-p0, -p1, etc.) can be specified. When
-refreshing a patch, only levels 0 and 1 are supported.
+Please see the paper "How To Survive With Many Patches /or/
+Introduction to Quilt" for an introduction.
Command reference
diff --git a/doc/consider-for-docs-1.mail b/doc/consider-for-docs-1.mail
deleted file mode 100644
index ff45891..0000000
--- a/doc/consider-for-docs-1.mail
+++ /dev/null
@@ -1,109 +0,0 @@
-From: Andreas Gruenbacher <agruen@suse.de>
-Organization: SuSE Linux AG
-Subject: Patch Management Scripts
-Date: Sat, 18 Jan 2003 18:40:32 +0100
-
-Hello,
-
-this is to announce that the patch-scripts package is available at
-http://www.suse.de/~agruen/patch-scripts/. The current version is 0.11.
-
-These scripts were based on Andrew Morton's patch scripts
-(http://www.zip.com.au/~akpm/linux/patches/), but have been very
-heavily modified since then.
-
-I am sure that there still a couple of bugs left, but these should
-really be ironed out before long.
-
-
-The scripts support:
-
-* Managing a stack of patches, applying and
- removing patches from the stack, adding new patches, and
- modifying them under a minimal kind of version control.
-
-* They should be reasonably robust (hopefully!).
-
-* Works for ordinary packages with only a few patches, and
- also for the kernel with several hundered patches.
-
-* The refresh script is careful not to drop any documentation
- preceding the actual patch in the patch files.
-
-* Simple to set up to get into "working mode" quickly.
-
-* Any applied patch can be refreshed. This is trivial for the
- topmost patch. If a file is modified by multiple patches,
- all changes to the file affect only the topmost patch that
- changed that file; patches further below will not include
- any such changes when being rediffed.
-
-* Several queries are supported, such as:
- - topmost, preceding, following patch(es),
- - files a patch creates or modifies
- - patches that modify a given file
- - changes a patch includes
- - changes to a patch in the working directory
-
-
-For those of you who are interested, here is a how to get started, after
-grabbing and installing the patch-scripts package.
-
-
-Patching an ordinary package:
-
- * The usual RPM contains a tarball and a set of
- patches. Unpack the tarball and copy the
- patches into the patches/ sub-directory in the
- package.
-
- * Create a file named series in the patches/ directory.
- The series file contains the list of patches for
- the package.
-
- The patches are applied with -p1 by default; for -p0
- or other style patches the series file must have
- -p0 or similar after the patch name (but on the same
- line).
-
- * Run `pushpatch -a' to apply all the patches. (Note
- that the first run is slightly slower because lists
- of files modified by the patches are created.)
-
- * Proceed with the README file in the patch-scripts
- package.
-
-
-Patching the kernel:
-
- * The kernel lives in a CVS repository. Check out this
- tree, say in a directory called $KCVS.
-
- * Unpack the kernel tarball, e.g., in $SRC. Create the
- patches/ directory, and add soft links to the various
- patches.* directories in the CVS into the patches
- directory, e.g.,
-
- $ cd $SRC/patches
- $ ln -s $KCVS/patches.* .
-
- * Create a series file. This is done like that:
-
- $ (cd $K_SRC/scripts ; \
- guards $(arch-symbols)) \
- < ../series.conf \
- > $SRC/patches/series
-
- * Change to $SRC, and run `pushpatch -qa' to apply
- the patches (-q gives much less output).
-
- * As above, check the README in the patch-scripts
- package, and try out what the individual scripts do.
-
-Cheers,
-Andreas.
-
-------------------------------------------------------------------
- Andreas Gruenbacher SuSE Linux AG
- mailto:agruen@suse.de Deutschherrnstr. 15-19
- http://www.suse.de/ D-90429 Nuernberg, Germany
diff --git a/doc/consider-for-docs-2.mail b/doc/consider-for-docs-2.mail
deleted file mode 100644
index bad5c27..0000000
--- a/doc/consider-for-docs-2.mail
+++ /dev/null
@@ -1,77 +0,0 @@
-From: Andreas Gruenbacher <agruen@suse.de>
-Organization: SuSE Linux AG
-To: quilt-dev@nongnu.org
-Subject: My current quilt 0.21 :)
-Date: Tue, 28 Jan 2003 22:05:15 +0100
-
-Hi,
-
-I have copied my current version to http://www.suse.de/~agruen/quilt/.
-Should we use this version to reload the CVS? I think we are nearing
-the stable development phase, so now this seems to make some sense.
-
-There are surely many new bugs. Please help shake them out :)
-
-I also didn't merge several improvements. Would it be possible that
-people contribute patches for the things they want included? I really
-don't have so much time to work on features I don't need so much.
-
-Here's a list of changes (some probably forgotten):
-
- - There now is a quilt wrapper script. All the individual
- commands are run from this script. This is a pain for frequently
- used commands like push and pop. (I am using shell aliases
- for some of them, which works well.)
-
- - The scripts have been split into many separate commands that
- are intended to do only a few things each.
-
- $ quilt
- Usage: quilt command [-h] ...
- Commands are:
- add files patches refresh setup
- applied import pop remove top
- delete new previous rest
- diff next push series
-
- - .gz and .bz2 compressed patches are now suported.
-
- - Quilt setup takes a series file, unpacks archive(s), and
- copies patches in.
-
- - For those working with RPMs, quilt setup can process an RPM
- spec file and produces the series file from that (by running the
- %prep section).
-
- - Quilt diff can diff a specified patch, diff the changes
- done relative to after a patch, and create combined diffs.
-
- - Quilt series shows which patches are applied,
- which is the topmost, and which are unapplied:
-
- $ quilt series -v
- + samba-2.2.4-smbadduser
- + samba-2.2.3-smbsh
- + samba-2.2.6-doc
- + samba-2.2.6-pdbedit
- + samba-2.2.7a-removeldap
- = samba-2.2.5-linkvfs
- samba-2.2.7-nettime
- samba-2.2.7a-acl-mapping-fixes
- samba-2.2.7a-glibc
-
- - Quilt files shows which files are new/removed by a patch (none
- are removed here):
-
- $ quilt files -v
- fs/Config.in
- fs/Makefile
- + fs/posix_acl.c
- + include/linux/posix_acl.h
-
- - Quilt import still sucks. Some ideas are found in the TODO.
-
-
-So long,
-Andreas.
-
diff --git a/doc/consider-for-docs-3.mail b/doc/consider-for-docs-3.mail
deleted file mode 100644
index 4672ae2..0000000
--- a/doc/consider-for-docs-3.mail
+++ /dev/null
@@ -1,56 +0,0 @@
-From: Andreas Gruenbacher <agruen@suse.de>
-Organization: SuSE Linux AG
-To: Andrew Morton <akpm@digeo.com>
-Subject: Patch scripts 0.9 improvements
-Date: Tue, 7 Jan 2003 14:39:16 +0100
-
-Hi Andrew,
-
-I still find your patch management scripts very useful. There are a fewg
-small limitations that still keeps me from using them for the SuSEg
-kernel at the moment. Particularly I need a way to have sub-directoriesg
-in patches/ etc.
-
-Please find some improvements and ideas in the attached patch.
-
-Also I think it would be a good idea to keep all (non-temporary)g
-information pertaining to a patch in a single file, rather thang
-splitting into .patch, .txt, .pc files. I have a format like theg
-following in mind. A simple parser for that proposed format is alsog
-attached.
-
- Summary: Test patch
- Author: Andreas Gruenbacher <agruen@suse.de>
- URL: http://www.suse.de/
-
- %description
- DESCRIPTION
-
- %files
- FILE1
- FILE2
- FILE3
-
- %patch
- PATCH
-
-I think that it doesn't make much sense to keep the .pc files (%filesg
-section) as part of the patch set; they can easily be regenerated fromg
-the .patch files. They are useful while working on a set of patchesg
-though. What do you think of always generating them on the fly, insteadg
-of using import_patch? Then the patches and series files could beg
-checked out from CVS, and patching could start immediately; no cruftg
-would assemble in the .pc files.
-
-Another idea: Maybe all the *~* files could live in their own directoryg
-tree, e.g., under pc/? Then the file names would become more simple,g
-e.g., from file.x~patch to ps/patch/file.x and file.x~dir_patch tog
-dir/patch/file.x, with a smaller chance of clashes. What do you think
-of that?
-
-Cheers,
-Andreas.
-
-
-[ Attachments removed ]
-
diff --git a/doc/docco.txt b/doc/docco.txt
deleted file mode 100644
index 1860f13..0000000
--- a/doc/docco.txt
+++ /dev/null
@@ -1,717 +0,0 @@
-Patch management scripts
-Andrew Morton <akpm@digeo.com>
-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. Lines in the series file which start with `#' are ignored.
-
-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
-
-join-patch patchname
-
- "joins" the named patch to the current topmost patch.
-
- Use this when you want to merge two patches into one. All the
- files which `patchname' affects are added to pc/$(toppatch).pc (if
- they are not already there) and patch `patchname' is applied. The
- top patch remains unchanged. You'll need to run refpatch afterwards.
-
-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".
-
diff --git a/doc/main.tex b/doc/main.tex
new file mode 100644
index 0000000..71e2e2f
--- /dev/null
+++ b/doc/main.tex
@@ -0,0 +1,716 @@
+%\documentclass[a4paper]{article}
+\documentclass[letter]{article}
+\usepackage{graphicx}
+\usepackage{subfigure}
+\usepackage{fancyvrb}
+%\usepackage{times}
+\usepackage[latin1]{inputenc}
+\usepackage{url}
+
+%\usepackage{lineno}
+%\linenumbers
+%\renewcommand{\baselinestretch}{1.5}
+
+% Change url font to textsf (and check what breaks in PDF/HTML/...)
+
+\fvset{xleftmargin=3em,commandchars=\\\{\}}
+
+\newcommand{\quilt}[1]{\textsf{quilt #1}}
+\newcommand{\sh}[1]{\textsl{#1}}
+\newcommand{\prog}[1]{\textit{#1}}
+
+\title{How To Survive With Many Patches\\
+{\Large or}\\
+Introduction to Quilt\footnote{
+ Quilt is a non-GNU project hosted on GNU Savannah. Some ideas
+ for this document were taken from \textit{docco.txt} in
+ Andrew Morton's patch management scripts package~\cite{akpm02}.
+ The text in the examples was taken from \textit{A Midsummer
+ Night's Dream} by William Shakespeare.
+}}
+\author{Andreas Grünbacher, SuSE Labs \\
+%\em{SUSE Labs, SUSE LINUX AG} \\
+{\normalsize agruen@suse.de}
+}
+%\date{}
+
+\begin{document}
+
+\maketitle
+
+\thispagestyle{empty}
+
+\begin{abstract}
+After looking at different strategies for dealing with software packages
+that consist of a base software package on top of which a number of
+patches are applied, this document introduces the script collection
+\textit{quilt,} which was specifically written to help deal with
+multiple patches and common patch management tasks.
+\end{abstract}
+
+\section{Introduction}
+
+% Prerequisites: UNIX, patches, using GNU diff and GNU patch.
+% Why patches in the first place?
+
+In the old days, vendor specific software packages in the open source
+world consisted of a file with the official version of the software,
+plus a patch file with the additional changes needed to adapt the
+package to specific needs. The official software package was usually
+contained in a \textsf{package.tar.gz} file, while the patch was found
+in \textsf{package.diff.} Instead of modifying the official
+package sources, local changes were kept separate. When building the
+software package, the tar archive was extracted, and the patch was
+applied.
+
+Over time, the patch file ended up containing several independent
+changes. Of those changes, some were integrated into later versions of
+the software, while otheradd-ons or adaptations remain external. Whenever
+a new official version was integrated, the patch needed to be revised:
+changes that were already integrated in the official version needed to
+be split from changes that were not.
+
+A big improvement was to allow multiple patches in a vendor package,
+and this is also how patches are handled today: a number of
+patches is applied on top of each other. Each patch usually consists of
+a logically related set of changes. When some patches get integrated
+upstream, those patches can simply be removed from the vendor specific
+package. The remaining patches frequently continue to apply cleanly.
+Some of the remaining patches may have to be maintained across a range
+of upstream versions because they are too specific for the upstream
+software package, etc. These patches often get out of sync, and need to
+be updated.
+
+For the majority of packages, the number of patches remains relatively
+low, so maintaining those patches without tools is feasible. A number of
+packages have dozens of patches, however. At the extreme end is the
+kernel source package (kernel-source-\textit{2.4.x}) with more than
+1\,000 patches. The difficulty of managing such a vast number of
+patches without tools can easily be imagined.
+
+This document discusses different strategies of dealing with large sets
+of patches. Patches are usually generated by the \prog{diff} utility,
+and applied with the \prog{patch} utility. Different patch file formats are
+defined as part of the specification of the \prog{diff} utility in
+POSIX.1~\cite{posix-2001-diff}. The most commonly used format today,
+\textit{unified diff,} is not covered by POSIX.1, however. A good
+description of patch file formats is found in the \prog{GNU diff} info
+pages~\cite{info-diff}.
+
+The question we try to answer in this document is how patches are best kept
+up to date in face of changes both to the upstream software package, and
+to the patches that precede them. After looking at some existing
+approaches, a collection of patch management scripts known as
+\textit{quilt} is described~\cite{quilt}, starting with basic concepts,
+and progressing towards more advanced tasks.
+
+% - quilt
+% (wet people's mouths about the features)
+
+% How exactly does this relate to many patches?
+
+\section{Existing Approaches}
+\label{sec:existing}
+
+The minimal solution for updating a patch is to apply all preceding
+patches.
+%\footnote{ In the kernel CVS, we have a a script called
+%\textit{sequence-patch} that simply applies all patches up to a
+%specified patch. }
+Then, a copy of the resulting source tree is created.\footnote{
+ The two copies can also be hard-linked with each other, which
+ significantly speeds up both the copying and the final
+ ``diffing''. If hard links are used, care must be taken that the
+ tools used to update one copy of the source tree will create new
+ files, and will not overwrite shared files. Editors like
+ \prog{emacs} and \prog{vi}, and utilities like \prog{patch},
+ support this.
+} The next patch in the sequence of patches (which is the one to be
+updated) is applied to only one of these source trees. This source tree
+is the modified until it reflects the desired result. The new version of
+the patch is distilled by comparing the two source trees with
+\prog{diff}, and writing the result into a file.
+
+This simple approach is rather error prone, and leaves much to be
+desired. Several people have independently written scripts that
+automate and improve upon this process.
+
+A version control system like \prog{CVS} or \prog{RCS} may be a
+reasonable alternative in some cases. The version control system is
+brought in the state of the working tree with a number of patches
+applied. Then the next patch is applied. After the working tree is
+updated as required, a diff between the repository copy and the working
+tree is created (with \prog{cvs diff}, etc). In this scenario the
+version control system is used to store and compare against the old
+repository version only. The full version control overhead is paid,
+while only a small fraction of its functionality is needed. Switching
+between different patches is not simplified.
+
+% TODO: Mention some approaches here; RCS and CVS ...
+
+One of the most advanced approaches is Andrew Morton's patch management
+scripts~\cite{akpm02}. The author of this document found that none of
+the available solutions would scale up to the specific requirements of
+the SUSE kernel-source package, and started to improve Andrew Morton's
+scripts until they became what they are now~\cite{quilt}.
+
+% - Re and Rd scripts (Czech scripts using RCS, replaces the
+% now-obsolete rpmpatch that supports one .dif only).
+% - Werner's scripts
+
+% What couldn't be done:
+% - Patches in sub-directories
+% - Many patches
+% - Retaining documentation (akpm's scripts do part of this)
+
+% Actually merging rejects is not handled; use tools like:
+% - wiggle
+% - Other merge tools (e.g., graphical ones)
+
+\section{Quilt: Basic Concepts and Operation}
+
+The remainder of this document discusses the script collection
+\textit{quilt.}
+
+With quilt, all work occurs within a single directory tree. Commands are
+invoked in the root of that tree. Commands are of the form
+``\quilt{cmd},'' similar to CVS commands. They can be abbreviated as
+long as the specified part of the command is unique. All commands print
+some help text with ``\quilt{cmd -h}.''
+
+Quilt manages a stack of patches. Patches are applied incrementally on
+top of the base tree plus all preceding patches. They can be pushed
+on top of the stack (\quilt{push}), and popped off the stack
+(\quilt{pop}). Commands are available for querying the contents of the
+series file (\quilt{series}, see below), the contents of the stack
+(\quilt{applied}, \quilt{previous}, \quilt{top}), and the patches that
+are not applied at a particular moment (\quilt{next}, \quilt{unapplied}).
+By default, most commands apply to the topmost patch on the stack.
+
+Patch files are located in the \textsf{patches} sub-directory of the
+source tree (see Figure~\ref{fig:dir-layout}). The \textsf{QUILT\_PATCHES}
+environment variable can be used to override this location. The
+\textsf{patches} directory may contain sub-directories.
+\textsf{patches} may also be a symbolic link instead of a directory.
+
+A file called \textsf{series} contains a list of patch file names that
+defines the order in which patches are applied. Unless there are means
+by which series files can be generated automatically (see
+Section~\ref{sec:rpm}), they are usually provided along with a set of
+patches. In \textsf{series}, each patch file name is on a separate line.
+Patch files are identified by pathnames that are relative to the
+\textsf{patches} directory; patches may be in sub-directories below the
+\textsf{patches} directory. Lines in the series file that start with a
+hash character (\texttt{\#}) are ignored. When quilt adds, removes, or
+renames patches, it automatically updates the series file. Users of
+quilt can modify series files while some patches are applied, as long as
+the applied patches remain in their original order.
+
+There is no notion of different development branches, but different
+series files can be used to assemble patches in different ways.
+
+\begin{figure}
+\begin{center}
+\begin{minipage}{6cm}
+\begin{small}
+\begin{Verbatim}
+work/ -+- ...
+ |- patches/ -+- series
+ | |- patch2.diff
+ | |- patch1.diff
+ | +- ...
+ +- .pc/ -+- applied-patches
+ |- patch1/ -+- ...
+ |- patch2/ -+- ...
+ +- ...
+\end{Verbatim}
+\end{small}
+\end{minipage}
+\caption{Quilt files in a source tree.}
+\label{fig:dir-layout}
+\end{center}
+\end{figure}
+
+Before a patch is applied (or ``pushed on the stack''), copies of all
+files the patch modifies are saved to the \textsf{.pc/\textit{patch}}
+directory.\footnote{
+ The patch name with extensions stripped is used as the name of
+ the sub-directory below the \textsf{.pc} directory. \prog{GNU patch},
+ which quilt uses internally to apply patches, creates backup
+ files and applies the patch in one step.
+} The patch is added to \textsf{.pc/applied-patches}, the list of
+currently applied patches. Later when a patch is regenerated
+(\quilt{refresh}), the backup copies in \textsf{.pc/\textit{patch}} are
+compared with the current versions of the files in the source tree
+using \prog{GNU diff}.
+
+Documentation related to a patch can be put at the beginning of a patch
+file. Quilt is careful to preserve all text that precedes the actual
+patch when doing a refresh. (This is limited to patches in unified
+format; see~\cite{info-diff}).
+
+The series file is looked up in the root of the source tree, in the
+patches directory, and in the \textsf{.pc} directory. The first series
+file that is found is used. This may also be a symbolic link, or a file
+with multiple hard links. Usually, only one series file is used for a
+set of patches, so the \textsf{patches} sub-directory is a convenient
+location.
+
+The \textsf{.pc} directory and its sub-directories cannot be relocated,
+but \textsf{.pc} may be a symbolic link. While patches are applied to
+the source tree, the \textsf{.pc} directory is essential for many
+operations, including taking patches off the stack (\quilt{pop}), and
+refreshing patches (\quilt{refresh}). Files in the \textsf{.pc}
+directory are automatically removed when they are no longer needed, so
+usually there is no need to clean up manually.
+
+\section{An Example}
+\label{sec:basic}
+
+This section demonstrates how new patches are created and updated, and
+how conflicts are resolved. Let's start with a short text file:
+
+\begin{small}
+\begin{Verbatim}
+Yet mark'd I where the bolt of Cupid fell:
+It fell upon a little western flower,
+Before milk-white, now purple with love's wound,
+And girls call it love-in-idleness.
+\end{Verbatim}
+\end{small}
+
+New patches are created with \quilt{new}. A new patch automatically
+becomes the topmost patch on the stack. Files must be added to a patch
+with \quilt{add} before they are modified. Note that this is slightly
+different from the CVS style of interaction: with CVS, files are in the
+repository, and adding them before committing (but after modifying them)
+is enough. Files are usually added and immediately modified. The
+command \quilt{edit} adds a file and loads it into the default editor.
+(The environment variable \textsf{EDITOR} specifies which is the default
+editor. If \textsf{EDITOR} is not set, \prog{vi} is used.)
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt new flower.diff}
+Patch flower is now on top
+\sh{$ quilt edit Oberon.txt}
+File Oberon.txt added to patch flower
+\end{Verbatim}
+\end{small}
+
+Let's assume that the following lines were added to \textsf{Oberon.txt}
+during editing:
+
+\begin{small}
+\begin{Verbatim}
+The juice of it on sleeping eye-lids laid
+Will make a man or woman madly dote
+Upon the next live creature that it sees.
+\end{Verbatim}
+\end{small}
+
+The actual patch file is created (and later updated) with
+\quilt{refresh}. The result is as follows:\footnote{
+ Timestamps in patches are omitted from the output in the examples.
+}
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt refresh}
+\sh{$ cat patches/flower.diff}
+Index: example1/Oberon.txt
+===================================================================
+--- example1.orig/Oberon.txt
++++ example1/Oberon.txt
+@@ -2,3 +2,6 @@
+ It fell upon a little western flower,
+ Before milk-white, now purple with love's wound,
+ And girls call it love-in-idleness.
++The juice of it on sleeping eye-lids laid
++Will make a man or woman madly dote
++Upon the next live creature that it sees.
+\end{Verbatim}
+\end{small}
+
+Now let's assume that a line in the text has been overlooked, and must
+be inserted. The file \textsf{Oberon.txt} is already part of the patch
+\textsf{flower.diff}, so it can immediately be modified in an editor.
+Alternatively, \quilt{edit} can be used; it simply opens up the default
+editor if the file is already part of the patch.
+
+After the line is added, we use \quilt{diff -z} to see a diff of the
+changes we made:
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt diff -z}
+Index: example1/Oberon.txt
+===================================================================
+--- example1.orig/Oberon.txt
++++ example1/Oberon.txt
+@@ -2,6 +2,7 @@
+ It fell upon a little western flower,
+ Before milk-white, now purple with love's wound,
+ And girls call it love-in-idleness.
++Fetch me that flower; the herb I shew'd thee once:
+ The juice of it on sleeping eye-lids laid
+ Will make a man or woman madly dote
+ Upon the next live creature that it sees.
+\end{Verbatim}
+\end{small}
+
+A diff of the topmost patch can be generated with \quilt{diff} without
+arguments. This does not modify the actual patch file. The changes are
+only added to the patch file by updating it with \quilt{refresh}. Then
+we remove the patch from the stack with \quilt{pop}:
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt refresh}
+Refreshed patch flower
+\sh{$ quilt pop}
+Removing flower
+Restoring Oberon.txt
+
+No patches applied
+\end{Verbatim}
+\end{small}
+
+Next, let's assume that \textsf{Oberon.txt} was modified ``upstream'':
+The word \textit{girl} did not fit very well, and so it was replaced
+with \textit{maiden.} \textsf{Oberon.txt} now contains:
+
+\begin{small}
+\begin{Verbatim}
+Yet mark'd I where the bolt of Cupid fell:
+It fell upon a little western flower,
+Before milk-white, now purple with love's wound,
+And maidens call it love-in-idleness.
+\end{Verbatim}
+\end{small}
+
+This causes \textsf{flower.diff} to no longer apply cleanly. When we
+try to push \textsf{flower.diff} on the stack with \quilt{push}, we get
+the following result:
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt push}
+Applying flower
+patching file Oberon.txt
+Hunk #1 FAILED at 2.
+1 out of 1 hunk FAILED -- rejects in file Oberon.txt
+Patch flower does not apply (enforce with -f)
+\end{Verbatim}
+\end{small}
+
+Quilt does not automatically apply patches that have rejects. Patches
+that do not apply cleanly can be ``force-applied'' with \quilt{push -f},
+which leaves reject files in the source tree for each file that has
+conflicts. Those conflicts must be resolved manually, after which the
+patch can be updated (\quilt{refresh}). Quilt remembers when a patch has
+been force-applied. It refuses to push further patches on top of such
+patches, and it does not remove them from the stack. A force-applied
+patch may be ``force-removed'' from the stack with \quilt{pop -f},
+however. Here is what happens when force-applying \textsf{flower.diff}:
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt push -f}
+Applying flower
+patching file Oberon.txt
+Hunk #1 FAILED at 2.
+1 out of 1 hunk FAILED -- saving rejects to file Oberon.txt.rej
+Applied flower (forced; needs refresh)
+\end{Verbatim}
+\end{small}
+
+After re-adding the line of verse from \textsf{flower.diff} to
+\textsf{Oberon.txt}, we update the patch with \quilt{refresh}.
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt edit Oberon.txt}
+\sh{$ quilt refresh}
+Refreshed patch flower
+\end{Verbatim}
+\end{small}
+
+Our final version of \textsf{Oberon.txt} contains:
+
+\begin{small}
+\begin{Verbatim}
+Yet mark'd I where the bolt of Cupid fell:
+It fell upon a little western flower,
+Before milk-white, now purple with love's wound,
+And maidens call it love-in-idleness.
+Fetch me that flower; the herb I shew'd thee once:
+The juice of it on sleeping eye-lids laid
+Will make a man or woman madly dote
+Upon the next live creature that it sees.
+\end{Verbatim}
+\end{small}
+
+\section{Further Commands and Concepts}
+
+This section introduces a few more basic commands, and then describes
+additional concepts that may not be immediately obvious. We do not
+describe all of the features of quilt here since many quilt commands are
+quite intuitive; furthermore, help text that describes the available
+options for each command is available via \quilt{\textit{cmd} -h}.
+
+The \quilt{top} command shows the name of the topmost patch. The
+\quilt{files} command shows which files a patch contains. The
+\quilt{patches} command shows which patches modify a specified file.
+With our previous example, we get the following results:
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt top}
+flower
+\sh{$ quilt files}
+Oberon.txt
+\sh{$ quilt patches Oberon.txt}
+flower
+\end{Verbatim}
+\end{small}
+
+The \quilt{push} and \quilt{pop} commands optionally take a number or
+a patch name as argument. If a number is given, the specified number of
+patches is added (\quilt{push}) or removed (\quilt{pop}). If a patch
+name is given, patches are added (\quilt{push}) or removed (\quilt{pop})
+until the specified patch is on top of the stack. With the \textsf{-a}
+option, all patches in the series file are added (\quilt{push}), or all
+applied patches are removed from the stack (\quilt{pop}).
+
+\subsection{Patch Strip Levels}
+
+Quilt assumes that patches are applied with a strip level of one (the
+\textsf{-p1} option of \prog{GNU patch}) by default: the topmost directory
+level of file names in patches is stripped off. Quilt remembers the
+strip level of each patch in the \textsf{series} file. When generating a
+diff (\quilt{diff}) or updating a patch (\quilt{refresh}), a different
+strip level can be specified, and the series file will be updated
+accordingly. Quilt can apply patches with an arbitrary strip level, and
+produces patches with a strip level of zero or one. With a strip level
+of one, the name of the directory that contains the working tree is used
+as the additional path component. (So in our example,
+\textsf{Oberon.txt} is contained in directory \textsf{example1}.)
+
+\subsection{Importing Patches}
+
+The \quilt{import} command automates the importing of patches into the
+quilt system. The command copies a patch into the \textsf{patches}
+directory and adds it to the \textsf{series} file. For patch strip
+levels other than one, the strip level is added after the patch file
+name. (An entry for \textsf{a.diff} with strip level zero might read
+``{\small \verb|a.diff -p0|}''.)
+
+Another common operation is to incorporate a fix or similar that comes
+as a patch into the topmost patch. While there is no specific command
+for this, the desired result can be achieved by first adding all the
+files that the fix modifies into the patch, and then apply the patch to
+the working tree. The following commands achieve this for a patch with
+a strip level of one:\footnote{
+ \prog{lsdiff} is part of the \textit{patchutils} package, and
+ generates a list of files a patch modifies.
+}
+
+\begin{small}
+\begin{Verbatim}
+\sh{$ quilt add `lsdiff --strip 1 patch.diff`}
+\sh{$ patch -p1 < patch.diff}
+\end{Verbatim}
+\end{small}
+
+\subsection{Forking}
+\label{sec:forking}
+
+There are situations in which updating a patch in-place is not ideal:
+the same patch may be used in more than one series file. It may also
+serve as convenient documentation to retain old versions of patches, and
+create new ones under different names. This can be done by hand by
+creating a copy of a patch (which must not be applied), and updating the
+patch name in the series file.
+
+The \quilt{fork} command simplifies this: it creates a copy of the
+next patch in the series (the one that \quilt{next} reports), and
+updates the series file. Unless a patch name is explicitly specified,
+\quilt{fork} will generate the following sequence of patch names:
+\textsf{patch.diff}, \textsf{patch-2.diff}, \textsf{patch-3.diff}, \dots
+
+\subsection{Advanced Diffing}
+
+Quilt allows us to diff and refresh patches that are applied, but are not
+on top of the stack (\quilt{diff -P \textit{patch}} and \quilt{refresh
+\textit{patch}}). This is useful in several cases, for example, when
+%\begin{itemize}
+%
+%\item When the topmost patch has been modified but the changes are not
+%yet completed, refreshing the patch would leave a patch file that is in
+%an inconsistent state. Without that, the patch cannot be removed from
+%the stack, or else the changes would be lost.
+%
+%\item Popping patches and then pushing them again results in modified
+%time stamps. This may trigger time consuming recompiles.
+%
+%\item It is simply convenient to be able to fix small bugs in patches
+%further down in the stack without much ado.
+%
+%\end{itemize}
+%
+patches applied higher on the stack modify some of the files that this
+patch modifies. We can picture this as a shadow which the patches higher
+on the stack throw on the files they modify. When refreshing a patch,
+changes to files that are not shadowed (and thus were last modified by
+the patch that is being refreshed) are taken into account. The
+modifications that the patch contains for shadowed files will not be
+updated.
+
+The \quilt{diff} command allows us to merge multiple patches into one by
+optionally specifying the range of patches to include (see \quilt{diff
+-h}). The combined patch will only modify each file contained in these
+patches once. The result of applying the combined patch is the same as
+applying all the patches in the specified range in sequence.
+
+Sometimes it is convenient to use a tool other than \prog{GNU diff} for
+comparing files (for example, a graphical diff replacement like
+\prog{tkdiff}). Quilt will not use tools other than \prog{GNU diff} when
+updating patches (\quilt{refresh}), but \quilt{diff} can be passed the
+\textsf{-{}-diff=\textit{utility}} argument. With this argument, the
+specified utility is invoked for each file that is being modified with
+the original file and new file as arguments. For new files, the first
+argument will be \textsf{/dev/null}. For removed files, the second
+argument will be \textsf{/dev/null}.
+
+When \quilt{diff} is passed a list of file names, the diff will be
+limited to those files. With the \textsf{-R} parameter, the original and
+new files are swapped, which results in a reverse diff.
+
+Sometimes it is useful to create a diff between an arbitrary state of
+the working tree and the current version. This can be used to create a
+diff between different versions of a patch (see
+Section~\ref{sec:forking}), etc. To this end, quilt allows us to take a
+snapshot of the working directory (\quilt{snapshot}). Later, a diff
+against this state of the working tree can be created with \quilt{diff
+-{}-snapshot}.
+
+Currently, only a single snapshot is supported. It is stored in the
+\textsf{.pc/.snap} directory. To recover the disk space the snapshot
+occupies, it can be removed with \quilt{snapshot -d}, or by removing the
+\textsf{.pc/.snap} directory manually.
+
+\subsection{Working with RPM Packages}
+\label{sec:rpm}
+
+Several Linux distributions are based on the RPM Package
+Manager~\cite{max-rpm}. RPM packages consist of a spec that defines how
+packages are built, and a number of additional files like tar archives,
+patches, etc. Most RPM packages contain an official software package
+plus a number of patches. Before these patches can be manipulated with
+quilt, a series file must be created that lists the patches along with
+their strip levels.
+
+The \quilt{setup} command automates this for most RPM packages. When
+given a spec file as its argument, it performs the \textsf{\%prep}
+section of the spec file, which is supposed to extract the official
+software package, and apply the patches. In this run, quilt remembers
+the tar archives and the patches that are applied, and creates a series
+file. Based on that series file, \quilt{setup} extracts the archives,
+and copies the patches into the \textsf{patches} sub-directory. Some
+meta-information like the archive names are stored as comments in the
+series file. \quilt{setup} also accepts a series file as argument (which
+must contain some meta-information), and sets up the working tree from
+the series file in this case.
+
+\section{Pitfalls and Known Problems}
+
+As mentioned earlier, files must be added to patches before they can be
+modified. If this step is overlooked, one of the following problems will
+occur: If the file is included in a patch further below on the stack,
+the changes will appear in that patch when it is refreshed, and for that
+patch the \quilt{pop} command will fail before it is refreshed. If the
+file is not included in any applied patch, the original file in the
+working tree is modified.
+
+Patch files may modify the same file more than once. \prog{GNU patch}
+has a bug that corrupts backup files in this case. A fix is available,
+and will be integrated in a later version of \textit{GNU patch}. The fix has
+already been integrated into the SUSE version of \textit{GNU patch}.
+
+There are some packages that assume that it's a good idea to remove all
+empty files throughout a working tree, including the \textsf{.pc}
+directory. The \textit{make clean} target in the linux kernel sources
+is an example. Quilt uses zero-length files in \textsf{.pc} to mark
+files added by patches, so such packages may corrupt the \textsf{.pc}
+directory. A workaround is to create a symbolic link \textsf{.pc} in the
+working tree that points to a directory outside.
+
+It may happen that the files in the \textsf{patches} directory gets out of
+sync with the working tree (e.g., they may accidentally get updated by
+CVS or similar). Files in the \textsf{.pc} directory may also become
+inconsistent, particularly if files are not added before modifying them
+(\quilt{add} / \quilt{edit}). If this happens, it may be possible to
+repair the source tree, but often the best solution is to start over
+with a scratch working directory and the \textsf{patches} sub-directory.
+There is no need to keep any files from the \textsf{.pc} directory in
+this case.
+
+% - Patches cannot automatically be reverse applied (?)
+% - Does not auto-detect is a patch has been cleanly integrated
+% - Speed
+
+% - Push a patch that is not in the series file (after changing
+% applied-patches to include the full patch name)?
+
+% - Other back-ends (RCS etc.)
+
+% - Pop and push modify file timestamps, which causes recompiles.
+% Ccache ameliorates this.
+
+% - patchutils: Very useful: lsdiff, filterdiff, etc.
+
+\section{Summary}
+
+We have shown how the script collection \textit{quilt} solves various
+problems that occur when dealing with patches to software packages.
+Quilt is an obvious improvement over directly using the underlying tools
+(\prog{GNU patch}, \prog{GNU diff}, etc.), and offers many features not
+available with competing solutions. Join the club!
+
+The quilt project homepage is
+\url{http://savannah.nongnu.org/projects/quilt/}. There is a development
+mailing list at \url{http://mail.nongnu.org/mailman/listinfo/quilt-dev}.
+Additional features that fit into quilt's mode of operation are always
+welcome, of course.
+
+\begin{thebibliography}{XX}
+
+\bibitem{akpm02}
+Andrew Morton: Patch Management Scripts,
+\url{http://lwn.net/Articles/13518/} and
+\url{http://www.zip.com.au/~akpm/linux/patches/patch-scripts-0.9}.
+
+\bibitem{quilt}
+Andreas Grünbacher et al.: Patchwork Quilt,
+\url{http://savannah.nongnu.org/projects/quilt}.
+
+\bibitem{posix-2001-diff}
+IEEE Std. 1003.1-2001: Standard for Information Technology, Portable
+Operating System Interface (POSIX), Shell and Utilities, diff
+command, pp.~317. Online version available from the The Austin Common
+Standards Revision Group, \url{http://www.opengroup.org/austin/}.
+
+\bibitem{info-diff}
+\textit{GNU diff} info pages (\textsf{info Diff}), section \textit{Output
+Formats.}
+
+\bibitem{max-rpm}
+Edward C. Bailey: Maximum RPM: Taking the Red Hat Package Manager to the
+Limit, \url{http://www.rpm.org/max-rpm/}.
+
+\end{thebibliography}
+
+% Add a "quick-reference card"?
+
+\end{document}
diff --git a/doc/quilt.pdf b/doc/quilt.pdf
new file mode 100644
index 0000000..aaba185
--- /dev/null
+++ b/doc/quilt.pdf
Binary files differ
diff --git a/po/de.po b/po/de.po
index 7cd720d..45cb377 100644
--- a/po/de.po
+++ b/po/de.po
@@ -204,7 +204,7 @@ msgstr "Patch $opt_combine ist nicht vor Patch $last_patch angewandt."
msgid "Cannot change into .pc/$last_patch"
msgstr "Kann nicht in Verzeichnis .pc/$last_patch wechseln."
-#: ../quilt/diff.in:239 ../scripts/rpatch.in:67
+#: ../quilt/diff.in:239 ../scripts/rpatch.in:60
msgid "Failed to copy files to temporary directory"
msgstr "Konnte Dateien nicht in ein temporäres Verzeichnis kopieren"
@@ -212,7 +212,7 @@ msgstr "Konnte Dateien nicht in ein temporäres Verzeichnis kopieren"
msgid "Cannot change to temporary directory"
msgstr "Kann nicht in temporäres Verzeichnis wechseln"
-#: ../quilt/diff.in:267 ../scripts/rpatch.in:95
+#: ../quilt/diff.in:267 ../scripts/rpatch.in:88
msgid "Failed to patch temporary files"
msgstr "Konnte temporäre Dateien nicht patchen"
@@ -797,7 +797,7 @@ msgstr "Kopiere Seriendatei"
msgid "Creatig link to series file $arg"
msgstr ""
-#: ../quilt/setup.in:243
+#: ../quilt/setup.in:244
msgid "Directory $packagedir set up."
msgstr "Verzeichnis $packagedir aufgebaut."
@@ -843,31 +843,36 @@ msgstr ""
msgid "Usage: $0 [-fqv] patchname"
msgstr "Verwendung: $0 [-fqv] patchname"
-#: ../scripts/apatch.in:43
+#: ../scripts/apatch.in:29
msgid "Interrupted by user; patch $patch was not applied."
msgstr "Unterbrechung durch Benutzer; Patch $patch wurde nicht angewandt."
-#: ../scripts/apatch.in:54
+#: ../scripts/apatch.in:40
msgid "Patch file $patch_file appears to be empty"
msgstr "Patch-Datei $patch_file scheint leer zu sein"
-#: ../scripts/apatch.in:94
+#: ../scripts/apatch.in:81
msgid "Applying $patch"
msgstr "Anwenden von $patch"
-#: ../scripts/apatch.in:113
+#: ../scripts/apatch.in:86
+#, fuzzy
+msgid "Patch file $patch_file did not exist, push failed"
+msgstr "Patch-Datei $patch_file scheint leer zu sein"
+
+#: ../scripts/apatch.in:120
msgid "Patch $patch appears to be empty, applied"
msgstr "Patch $patch scheint leer zu sein, angewandt"
-#: ../scripts/apatch.in:116
+#: ../scripts/apatch.in:123
msgid "Applied $patch (forced; needs refresh)"
msgstr "Patch $patch angewandt (erzwungen, muß aufgefrischt werden (Refresh))"
-#: ../scripts/apatch.in:120
+#: ../scripts/apatch.in:127
msgid "Patch $patch does not apply (enforce with -f)"
msgstr "Patch $patch läßt sich nicht anwenden (erzwingen mit -f)"
-#: ../scripts/apatch.in:177 ../scripts/rpatch.in:217
+#: ../scripts/apatch.in:184 ../scripts/rpatch.in:211
msgid "The topmost patch $top needs to be refreshed first."
msgstr "Der oberste Patch $top muss zuerst aufgefrischt werden (Refresh)."
@@ -875,16 +880,16 @@ msgstr "Der oberste Patch $top muss zuerst aufgefrischt werden (Refresh)."
msgid "Usage: $0 [-fRq] patchname"
msgstr "Verwendung: $0 [-fRq] patchname"
-#: ../scripts/rpatch.in:110
+#: ../scripts/rpatch.in:103
#, fuzzy
msgid "Patch $patch does not remove cleanly (enforce with -f)."
msgstr "Patch $patch kann nicht entfernt werden (erzwingen mit -f)"
-#: ../scripts/rpatch.in:127
+#: ../scripts/rpatch.in:120
msgid "Patch $patch appears to be empty, removed"
msgstr "Patch $patch scheint leer zu sein, entfernt"
-#: ../scripts/rpatch.in:160
+#: ../scripts/rpatch.in:153
msgid "Removing $patch"
msgstr "Entferne $patch"
diff --git a/po/fr.po b/po/fr.po
index c8306bb..91f2ae9 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -205,7 +205,7 @@ msgstr "Le patch $opt_combine n'est pas appliqué avant $last_patch."
msgid "Cannot change into .pc/$last_patch"
msgstr "Impossible d'entrer dans .pc/$last_patch"
-#: ../quilt/diff.in:239 ../scripts/rpatch.in:67
+#: ../quilt/diff.in:239 ../scripts/rpatch.in:60
msgid "Failed to copy files to temporary directory"
msgstr "Impossible de copier les fichiers dans le répertoire temporaire"
@@ -213,7 +213,7 @@ msgstr "Impossible de copier les fichiers dans le répertoire temporaire"
msgid "Cannot change to temporary directory"
msgstr "Impossible d'entrer dans le répertoire temporaire"
-#: ../quilt/diff.in:267 ../scripts/rpatch.in:95
+#: ../quilt/diff.in:267 ../scripts/rpatch.in:88
msgid "Failed to patch temporary files"
msgstr "Impossible de patcher les fichiers temporaires"
@@ -802,7 +802,7 @@ msgstr "Copie du fichier de série"
msgid "Creatig link to series file $arg"
msgstr ""
-#: ../quilt/setup.in:243
+#: ../quilt/setup.in:244
msgid "Directory $packagedir set up."
msgstr "Le répertoire $packagedir est configuré."
@@ -850,32 +850,37 @@ msgstr ""
msgid "Usage: $0 [-fqv] patchname"
msgstr "Usage : $0 [-fqv] patchname"
-#: ../scripts/apatch.in:43
+#: ../scripts/apatch.in:29
msgid "Interrupted by user; patch $patch was not applied."
msgstr "Interrompu par l'utilisateur ; le patch $patch n'a pas été appliqué."
-#: ../scripts/apatch.in:54
+#: ../scripts/apatch.in:40
msgid "Patch file $patch_file appears to be empty"
msgstr "Le fichier de patch $patch_file semble vide"
-#: ../scripts/apatch.in:94
+#: ../scripts/apatch.in:81
msgid "Applying $patch"
msgstr "Application de $patch"
-#: ../scripts/apatch.in:113
+#: ../scripts/apatch.in:86
+#, fuzzy
+msgid "Patch file $patch_file did not exist, push failed"
+msgstr "Le fichier de patch $patch_file semble vide"
+
+#: ../scripts/apatch.in:120
msgid "Patch $patch appears to be empty, applied"
msgstr "Le patch $patch semble vide. Il a été appliqué."
-#: ../scripts/apatch.in:116
+#: ../scripts/apatch.in:123
msgid "Applied $patch (forced; needs refresh)"
msgstr "$patch a été appliqué (forcé ; vous devriez le rafraîchir)"
-#: ../scripts/apatch.in:120
+#: ../scripts/apatch.in:127
msgid "Patch $patch does not apply (enforce with -f)"
msgstr ""
"Le patch $patch ne s'applique pas proprement (forcez l'application avec -f)"
-#: ../scripts/apatch.in:177 ../scripts/rpatch.in:217
+#: ../scripts/apatch.in:184 ../scripts/rpatch.in:211
msgid "The topmost patch $top needs to be refreshed first."
msgstr "Le patch au sommet $top doit être rafraichi au préalable."
@@ -883,16 +888,16 @@ msgstr "Le patch au sommet $top doit être rafraichi au préalable."
msgid "Usage: $0 [-fRq] patchname"
msgstr "Usage: $0 [-fRq] nom_de_patch"
-#: ../scripts/rpatch.in:110
+#: ../scripts/rpatch.in:103
#, fuzzy
msgid "Patch $patch does not remove cleanly (enforce with -f)."
msgstr "Le patch $patch ne se retire pas proprement (forcez avec -f)"
-#: ../scripts/rpatch.in:127
+#: ../scripts/rpatch.in:120
msgid "Patch $patch appears to be empty, removed"
msgstr "Le patch $patch semble vide. Il a été retiré."
-#: ../scripts/rpatch.in:160
+#: ../scripts/rpatch.in:153
msgid "Removing $patch"
msgstr "Retrait de $patch"
diff --git a/po/quilt.pot b/po/quilt.pot
index a0d7026..299c5a8 100644
--- a/po/quilt.pot
+++ b/po/quilt.pot
@@ -144,7 +144,7 @@ msgstr ""
msgid "Cannot change into .pc/$last_patch"
msgstr ""
-#: ../quilt/diff.in:239 ../scripts/rpatch.in:67
+#: ../quilt/diff.in:239 ../scripts/rpatch.in:60
msgid "Failed to copy files to temporary directory"
msgstr ""
@@ -152,7 +152,7 @@ msgstr ""
msgid "Cannot change to temporary directory"
msgstr ""
-#: ../quilt/diff.in:267 ../scripts/rpatch.in:95
+#: ../quilt/diff.in:267 ../scripts/rpatch.in:88
msgid "Failed to patch temporary files"
msgstr ""
@@ -599,7 +599,7 @@ msgstr ""
msgid "Creatig link to series file $arg"
msgstr ""
-#: ../quilt/setup.in:243
+#: ../quilt/setup.in:244
msgid "Directory $packagedir set up."
msgstr ""
@@ -635,31 +635,35 @@ msgstr ""
msgid "Usage: $0 [-fqv] patchname"
msgstr ""
-#: ../scripts/apatch.in:43
+#: ../scripts/apatch.in:29
msgid "Interrupted by user; patch $patch was not applied."
msgstr ""
-#: ../scripts/apatch.in:54
+#: ../scripts/apatch.in:40
msgid "Patch file $patch_file appears to be empty"
msgstr ""
-#: ../scripts/apatch.in:94
+#: ../scripts/apatch.in:81
msgid "Applying $patch"
msgstr ""
-#: ../scripts/apatch.in:113
+#: ../scripts/apatch.in:86
+msgid "Patch file $patch_file did not exist, push failed"
+msgstr ""
+
+#: ../scripts/apatch.in:120
msgid "Patch $patch appears to be empty, applied"
msgstr ""
-#: ../scripts/apatch.in:116
+#: ../scripts/apatch.in:123
msgid "Applied $patch (forced; needs refresh)"
msgstr ""
-#: ../scripts/apatch.in:120
+#: ../scripts/apatch.in:127
msgid "Patch $patch does not apply (enforce with -f)"
msgstr ""
-#: ../scripts/apatch.in:177 ../scripts/rpatch.in:217
+#: ../scripts/apatch.in:184 ../scripts/rpatch.in:211
msgid "The topmost patch $top needs to be refreshed first."
msgstr ""
@@ -667,15 +671,15 @@ msgstr ""
msgid "Usage: $0 [-fRq] patchname"
msgstr ""
-#: ../scripts/rpatch.in:110
+#: ../scripts/rpatch.in:103
msgid "Patch $patch does not remove cleanly (enforce with -f)."
msgstr ""
-#: ../scripts/rpatch.in:127
+#: ../scripts/rpatch.in:120
msgid "Patch $patch appears to be empty, removed"
msgstr ""
-#: ../scripts/rpatch.in:160
+#: ../scripts/rpatch.in:153
msgid "Removing $patch"
msgstr ""
diff --git a/quilt.changes b/quilt.changes
index a05e606..9f70878 100644
--- a/quilt.changes
+++ b/quilt.changes
@@ -1,4 +1,38 @@
-------------------------------------------------------------------
+Mon Nov 17 20:31:36 CET 2003 - agruen@suse.de
+
+- Add new command `quilt fold' to fold one patch into another.
+- Fix bug in `quilt files': Files that are neither present in the
+ working directory and have an empty backup copy sometimes were
+ still listed.
+- Some minor cleanups in apatch.
+- Add test/fold.test, and fix a now-useless check in one.test.
+
+-------------------------------------------------------------------
+Sat Nov 15 08:44:19 CET 2003 - agruen@suse.de
+
+- Merge some changes from wangdi:
+ + Use -f (force) option of GNU patch in `quilt diff -z'.
+ + Build source and binary RPMs in `make rpm' target.
+ + Simplify sed expression in Makefile.in.
+
+-------------------------------------------------------------------
+Wed Nov 12 01:37:17 CET 2003 - agruen@suse.de
+
+- Add introductory paper to CVS repository.
+- Remove obsolete documentation.
+- Bump version number to 0.29 (cvs tag VER_0_29).
+
+-------------------------------------------------------------------
+Tue Nov 4 16:51:49 CET 2003 - agruen@suse.de
+
+- Add failpop.test that checks if modified patches are recognized.
+- Fix the check for modified patches: That broke with the .pc file
+ removal.
+- `quilt setup' sometimes forgot to create the patches sub-dir.
+- Fix the timestamp check in scripts/rpatch.in for missing files.
+
+-------------------------------------------------------------------
Fri Oct 31 16:59:06 CET 2003 - agruen@suse.de
- Bump version number to 0.28 (cvs tag VER_0_28).
diff --git a/quilt.spec.in b/quilt.spec.in
index 027c19f..e5ba22e 100644
--- a/quilt.spec.in
+++ b/quilt.spec.in
@@ -8,7 +8,7 @@ License: GPL
Group: Productivity/Text/Utilities
Version: 0
Release: 0
-Requires: fileutils diffutils patch gzip bzip2 perl mktemp gettext
+Requires: coreutils diffutils patch gzip bzip2 perl mktemp gettext
Autoreqprov: off
Source: quilt-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-build
diff --git a/quilt/diff.in b/quilt/diff.in
index 6cb5c8a..bab0c8e 100644
--- a/quilt/diff.in
+++ b/quilt/diff.in
@@ -255,7 +255,7 @@ then
then
if ! cat_file $pwd/$patch_file \
| @PATCH@ $patch_args --no-backup-if-mismatch \
- -E >/dev/null 2>/dev/null
+ -Ef >/dev/null 2>/dev/null
then
# If a patch was force applied (and therefore needs
# refreshing), we know that patching the temporary
diff --git a/quilt/files.in b/quilt/files.in
index 796b9e2..3db405e 100644
--- a/quilt/files.in
+++ b/quilt/files.in
@@ -87,28 +87,30 @@ then
fi
fi
-if [ -z "$opt_verbose" ]
-then
- files_in_patch $patch
-else
- for file in $(files_in_patch $patch)
- do
- status=" "
- if [ -s $(backup_file_name $patch $file) ]
+for file in $(files_in_patch $patch)
+do
+ status=" "
+ if [ -s $(backup_file_name $patch $file) ]
+ then
+ if ! [ -s $file ]
+ then
+ status="-"
+ fi
+ else
+ if [ -s $file ]
then
- if ! [ -s $file ]
- then
- status="-"
- fi
+ status="+"
else
- if [ -s $file ]
- then
- status="+"
- fi
+ continue
fi
+ fi
+ if [ -z "$opt_verbose" ]
+ then
+ echo "$file"
+ else
echo "$status $file"
- done
-fi
+ fi
+done
### Local Variables:
### mode: shell-script
### End:
diff --git a/quilt/fold.in b/quilt/fold.in
new file mode 100644
index 0000000..65769fe
--- /dev/null
+++ b/quilt/fold.in
@@ -0,0 +1,122 @@
+#! @BASH@
+
+# This script is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# See the COPYING and AUTHORS files for more details.
+
+# Read in library functions
+if [ "$(type -t patch_file_name)" != function ]
+then
+ if ! [ -r @SCRIPTS@/patchfns ]
+ then
+ echo "Cannot read library @SCRIPTS@/patchfns" >&2
+ exit 1
+ fi
+ . @SCRIPTS@/patchfns
+fi
+
+usage()
+{
+ echo $"Usage: quilt fold [-p strip-level]"
+ if [ x$1 = x-h ]
+ then
+ echo $"
+
+Fold the patch read from standard input into the topmost patch: After
+making sure that all files modified by the patchfile are part of the
+topmost patch, the patch is applied with the specified strip level
+(which defaults to 1).
+
+-p strip-level
+ The number of pathname components to strip from file names
+ when applying patchfile."
+
+ exit 0
+ else
+ exit 1
+ fi
+}
+
+options=`getopt -o p:qh -- "$@"`
+
+if [ $? -ne 0 ]
+then
+ usage
+fi
+
+eval set -- "$options"
+
+while true
+do
+ case "$1" in
+ -p)
+ opt_strip_level=$2
+ shift 2 ;;
+ -q)
+ opt_silent=1
+ shift ;;
+ -h)
+ usage -h ;;
+ --)
+ shift
+ break ;;
+ esac
+done
+
+if [ $# -ne 0 ]
+then
+ usage
+fi
+
+: ${opt_strip_level:=1}
+[ -n "$opt_silent" ] && silent=-s
+
+top=$(top_patch)
+if [ -z "$top" ]
+then
+ echo $"No patch applied"
+fi
+
+trap "failed=1" SIGINT
+
+workdir=$(gen_tempfile -d $PWD)
+@PATCH@ -p$opt_strip_level $silent --backup --prefix="$workdir/" -E \
+|| failed=1
+
+if [ -z "$failed" ]
+then
+ for file in $(find $workdir -type f -a ! -path "$workdir/.timestamp")
+ do
+ backup_file="$(backup_file_name $top "${file:${#workdir}+1}")"
+ if ! [ -e "$backup_file" ]
+ then
+ if ! ln "$file" "$backup_file"
+ then
+ failed=1
+ break
+ fi
+ fi
+ done
+fi
+if [ -n "$failed" ]
+then
+ for file in $(find $workdir -type f -a ! -path "$workdir/.timestamp")
+ do
+ backup_file="$(backup_file_name $top "${file:${#workdir}+1}")"
+ if ! mv -f "$backup_file" "$file"
+ then
+ echo $"File ${file:${#workdir}+1} may be corrupted"
+ fi
+ done
+ rm -rf $workdir
+ exit 1
+fi
+
+rm -rf $workdir
+exit 0
+### Local Variables:
+### mode: shell-script
+### End:
+# vim:filetype=sh
diff --git a/quilt/gendiff.in b/quilt/gendiff.in
index 11791ed..5da95c2 100755
--- a/quilt/gendiff.in
+++ b/quilt/gendiff.in
@@ -74,9 +74,7 @@ fi
for file in $(files_in_patch $save_patch_name)
do
- if [ ! -e $file ]; then
- echo "$file has been deleted"
- else
+ if [ -e $file ]; then
base_dir=$(pwd)
ln -s $base_dir/.pc/$save_patch_name/$file ${file}~old
diff -Nur ${file}~old $file
diff --git a/quilt/refresh.in b/quilt/refresh.in
index f0d9372..5fbfbe4 100644
--- a/quilt/refresh.in
+++ b/quilt/refresh.in
@@ -269,7 +269,7 @@ then
die 1
fi
-touch .pc/$patch
+touch .pc/$patch/.timestamp
rm -f .pc/$patch~refresh
echo $"Refreshed patch $patch"
diff --git a/quilt/setup.in b/quilt/setup.in
index f4efdc7..b0f31eb 100644
--- a/quilt/setup.in
+++ b/quilt/setup.in
@@ -211,6 +211,7 @@ do
fi
else
echo $"Copying series file"
+ mkdir -p $packagedir/patches
cp "$arg" "$packagedir/patches/series"
fi
;;
diff --git a/scripts/apatch.in b/scripts/apatch.in
index 99c5d18..c558b1c 100755
--- a/scripts/apatch.in
+++ b/scripts/apatch.in
@@ -23,20 +23,6 @@ usage()
exit 1
}
-rollback_patch()
-{
- local patch=$1 pc_file=$(gen_tempfile)
-
- # FIXME backup_files should scan the directory hierarchy itself.
- files_in_patch $patch > $pc_file
- @LIB@/backup-files $silent_unless_verbose -f $pc_file -B .pc/$patch/ -r
- if [ -z "$opt_leave_rejects" ]
- then
- @SED@ -e 's/$/\.rej/' $pc_file | xargs rm -f
- fi
- rm -f $pc_file
-}
-
interrupt()
{
rollback_patch $1
@@ -49,11 +35,6 @@ apply_patch()
local patch=$1
local patch_file=$(patch_file_name $patch) output
- if ! [ -e "$patch_file" ]
- then
- echo $"Patch file $patch_file did not exist, push failed"
- exit 1
- fi
if ! [ -s $patch_file ]
then
echo $"Patch file $patch_file appears to be empty"
@@ -62,48 +43,65 @@ apply_patch()
if [ "x${patch_file:(-3)}" = "x.gz" ]
then
- output="$(
gzip -cd $patch_file \
| @PATCH@ $(patch_args $patch) --backup --prefix=".pc/$patch/" \
- -E $silent $force_apply 2>&1 )"
+ -E $silent $force_apply 2>&1
elif [ "x${patch_file:(-4)}" = "x.bz2" ]
then
- output="$(
bzip2 -cd $patch_file \
| @PATCH@ $(patch_args $patch) --backup --prefix=".pc/$patch/" \
- -E $silent $force_apply 2>&1 )"
+ -E $silent $force_apply 2>&1
else
- output="$(
@PATCH@ $(patch_args $patch) --backup --prefix=".pc/$patch/" \
- -E $silent -i $patch_file $force_apply 2>&1 )"
+ -E $silent $force_apply -i $patch_file 2>&1
fi
-
- status=${PIPESTATUS[0]}
- if [ $status -ne 0 -a -z "$opt_leave_rejects" ]
- then
- # The reject files are removed in rollback_patch.
- echo "$output" \
- | sed -e 's/-- saving rejects to file \(.\+\)\.rej/-- rejects in file \1/'
- elif [ -n "$output" ]
+}
+
+rollback_patch()
+{
+ local patch=$1 pc_file=$(gen_tempfile)
+
+ # FIXME backup_files should scan the directory hierarchy itself.
+ files_in_patch $patch > $pc_file
+ @LIB@/backup-files $silent_unless_verbose -f $pc_file -B .pc/$patch/ -r
+ if [ -z "$opt_leave_rejects" ]
then
- echo "$output"
+ @SED@ -e 's/$/\.rej/' $pc_file | xargs rm -f
fi
- return $status
+ rm -f $pc_file
}
apatch()
{
local patch=$(stripit $1)
+ local patch_file=$(patch_file_name $patch) output
local file status
+
echo $"Applying $patch"
trap "interrupt $patch" SIGINT
+
+ if ! [ -e "$patch_file" -o -n "$opt_force" ]
+ then
+ echo $"Patch file $patch_file did not exist, push failed"
+ exit 1
+ fi
- apply_patch $patch
- status=$?
+ output="$(apply_patch $patch)"
+ status=${PIPESTATUS[0]}
trap "" SIGINT
+ if [ $status -ne 0 -a -z "$opt_leave_rejects" ]
+ then
+ # The reject files are removed in rollback_patch.
+ echo "$output" \
+ | sed -e 's/-- saving rejects to file \(.\+\)\.rej/-- rejects in file \1/'
+ elif [ -n "$output" ]
+ then
+ echo "$output"
+ fi
+
if [ $status -eq 0 -o -n "$opt_force" ]
then
add_to_db $patch
@@ -113,6 +111,10 @@ apatch()
else
touch .pc/$patch~refresh
fi
+ if [ -e ".pc/$patch" ]
+ then
+ touch .pc/$patch/.timestamp
+ fi
if [ "$(shopt -s nullglob ; echo .pc/$patch/*)" = "" ]
then
echo $"Patch $patch appears to be empty, applied"
diff --git a/scripts/patchfns.in b/scripts/patchfns.in
index 61c21e8..dcaaa26 100644
--- a/scripts/patchfns.in
+++ b/scripts/patchfns.in
@@ -407,7 +407,8 @@ files_in_patch()
local path=".pc/$patch"
if [ -d "$path" ]
then
- for file in $(find "$path" -type f)
+ for file in $(find "$path" -type f \
+ -a ! -path "$path/.timestamp")
do
echo "${file:${#path}+1}"
done
diff --git a/scripts/rpatch.in b/scripts/rpatch.in
index cccd741..a8bdf18 100755
--- a/scripts/rpatch.in
+++ b/scripts/rpatch.in
@@ -28,26 +28,19 @@ files_may_have_changed()
local patch=$1 file
local patch_file=$(patch_file_name $patch)
- local apply_ts=$(date -r ".pc/$patch" '+%s') ts
-
-
- if [ -e "$patch_file" -a ".pc/$patch" -ot "$patch_file" ]
+ if [ $? -ne 0 -o ! -e "$patch_file" -o ! -e ".pc/$patch/.timestamp" \
+ -o ".pc/$patch/.timestamp" -ot "$patch_file" ]
then
return 0
fi
+ local apply_ts=$(date -r ".pc/$patch/.timestamp" '+%s') ts
for file in $(files_in_patch $patch)
do
- if ! [ -e $file ]
- then
- return 0 # file is missing
- fi
- ts=$(date -r $file '+%s')
- if [ $? -ne 0 -o $ts -gt $apply_ts ]
- then
- return 0 # file has changed
- fi
+ ts=$(date -r $file '+%s' 2> /dev/null)
+ [ -z "$ts" ] && return 0
+ [ "$ts" -gt $apply_ts ] && return 0
done
-return 1
+ return 1
}
# Check if all changes have been folded back into the patch (quilt refresh),
@@ -158,6 +151,7 @@ rpatch()
if [ $status -eq 0 ]
then
echo $"Removing $patch"
+ rm -f ".pc/$patch/.timestamp"
@LIB@/backup-files $silent -f $pc_file -B .pc/$patch/ -r
status=$?
remove_from_db $patch
diff --git a/test/failpop.test b/test/failpop.test
new file mode 100644
index 0000000..9b4cc3d
--- /dev/null
+++ b/test/failpop.test
@@ -0,0 +1,27 @@
+ $ mkdir d
+ $ cd d
+
+ $ cat > test.txt
+ < This is test.txt.
+
+ $ quilt new test.diff
+ > Patch test is now on top
+
+ $ quilt add test.txt
+ > File test.txt added to patch test
+
+ $ cat >> test.txt
+ < Line two.
+
+ $ quilt refresh
+ > Refreshed patch test
+
+ $ sleep 2
+
+ $ sed -e "s/ /_/g" patches/test.diff > patches/test.new
+ $ mv patches/test.new patches/test.diff
+ $ quilt pop
+ > Patch test does not remove cleanly (enforce with -f).
+
+ $ cd ..
+ $ rm -rf d
diff --git a/test/fold.test b/test/fold.test
new file mode 100644
index 0000000..b0aeb90
--- /dev/null
+++ b/test/fold.test
@@ -0,0 +1,57 @@
+ $ mkdir d
+ $ cd d
+
+ $ mkdir patches
+ $ cat > patches/series
+ < patch1.diff
+ < patch2.diff
+
+ $ cat > patches/patch1.diff
+ < --- q.orig/file1.txt
+ < +++ q/file1.txt
+ < @@ -0,0 +1 @@
+ < +This is file1.txt.
+ < --- q.orig/file2.txt
+ < +++ q/file2.txt
+ < @@ -0,0 +1 @@
+ < +This is file2.txt.
+
+ $ cat > patches/patch2.diff
+ < --- q.orig/file2.txt
+ < +++ q/file2.txt
+ < @@ -1 +0,0 @@
+ < -This is file2.txt.
+ < --- q.orig/file3.txt
+ < +++ q/file3.txt
+ < @@ -0,0 +1 @@
+ < +This is file3.txt.
+
+ $ quilt push -q
+ > Applying patch1
+ > Now at patch patch1
+
+ $ quilt files
+ > file1.txt
+ > file2.txt
+
+ $ quilt fold -q < patches/patch2.diff
+ $ quilt files
+ > file1.txt
+ > file3.txt
+
+ $ quilt diff | sed -e "s/\\t.*//"
+ > Index: d/file1.txt
+ > ===================================================================
+ > --- d.orig/file1.txt
+ > +++ d/file1.txt
+ > @@ -0,0 +1 @@
+ > +This is file1.txt.
+ > Index: d/file3.txt
+ > ===================================================================
+ > --- d.orig/file3.txt
+ > +++ d/file3.txt
+ > @@ -0,0 +1 @@
+ > +This is file3.txt.
+
+ $ cd ..
+ $ rm -rf d
diff --git a/test/one.test b/test/one.test
index d1298c5..d72858f 100644
--- a/test/one.test
+++ b/test/one.test
@@ -23,10 +23,6 @@ of the installed quilt with `make check'.
$ quilt refresh
> Nothing in patch patch1
- $ quilt files
- > dir/file1
- > file2
-
$ echo "This is file two." > file2
$ quilt diff | sed -e "s/\\t.*//"
> Index: d/file2