diff options
-rw-r--r-- | Makefile.in | 6 | ||||
-rw-r--r-- | doc/Makefile | 18 | ||||
-rw-r--r-- | doc/README.in | 78 | ||||
-rw-r--r-- | doc/consider-for-docs-1.mail | 109 | ||||
-rw-r--r-- | doc/consider-for-docs-2.mail | 77 | ||||
-rw-r--r-- | doc/consider-for-docs-3.mail | 56 | ||||
-rw-r--r-- | doc/docco.txt | 717 | ||||
-rw-r--r-- | doc/main.tex | 716 | ||||
-rw-r--r-- | doc/quilt.pdf | bin | 0 -> 169217 bytes | |||
-rw-r--r-- | quilt.changes | 6 |
10 files changed, 745 insertions, 1038 deletions
diff --git a/Makefile.in b/Makefile.in index 27d2210..021c680 100644 --- a/Makefile.in +++ b/Makefile.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 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 Binary files differnew file mode 100644 index 0000000..aaba185 --- /dev/null +++ b/doc/quilt.pdf diff --git a/quilt.changes b/quilt.changes index ee85a09..2987193 100644 --- a/quilt.changes +++ b/quilt.changes @@ -1,4 +1,10 @@ ------------------------------------------------------------------- +Wed Nov 12 01:37:17 CET 2003 - agruen@suse.de + +- Add introductory paper to CVS repository. +- Remove obsolete documentation. + +------------------------------------------------------------------- Tue Nov 4 16:51:49 CET 2003 - agruen@suse.de - Add failpop.test that checks if modified patches are recognized. |