mirror of https://gitee.com/openkylin/quilt.git
795 lines
33 KiB
TeX
795 lines
33 KiB
TeX
%\documentclass[a4paper]{article}
|
|
\documentclass{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 GPL licensed 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 other add-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 then 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}
|
|
\label{sec:basic}
|
|
|
|
The remainder of this document discusses the script collection
|
|
\textit{quilt.}
|
|
|
|
With quilt, all work occurs within a single directory tree. Since
|
|
version 0.30, commands can be invoked from anywhere within the source
|
|
tree (the directory tree is scanned upwards until either the
|
|
\textsf{.pc} or the \textsf{patches} directory is found).
|
|
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.
|
|
|
|
When files in the working directory are changed, those changes become
|
|
part of the working state of the topmost patch, provided that those
|
|
files are part of the patch. Files that are not part of a patch must be
|
|
added before modifying them so that quilt is aware of the original
|
|
versions of the files. The \quilt{refresh} command regenerates a patch.
|
|
After the refresh, the patch and the working state are the same.
|
|
|
|
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 and quilt
|
|
will remember this location by storing its value in the
|
|
\textsf{.pc/.quilt\_patches} file. The \textsf{patches} directory may contain
|
|
sub-directories, which is useful for grouping related patches together.
|
|
\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.
|
|
|
|
Different series files can be used to assemble patches in different ways,
|
|
corresponding for example to different development branches.
|
|
|
|
\begin{figure}
|
|
\begin{center}
|
|
\begin{minipage}{6cm}
|
|
\begin{small}
|
|
\begin{Verbatim}
|
|
work/ -+- ...
|
|
|- patches/ -+- series
|
|
| |- patch2.diff
|
|
| |- patch1.diff
|
|
| +- ...
|
|
+- .pc/ -+- applied-patches
|
|
|- patch1.diff/ -+- ...
|
|
|- patch2.diff/ -+- ...
|
|
+- ...
|
|
\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 the list of
|
|
currently applied patches (\textsf{.pc/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.
|
|
|
|
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.
|
|
|
|
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. The
|
|
\textsf{QUILT\_PC} environment variable can be used to override the
|
|
location of the \textsf{.pc} directory.
|
|
|
|
\section{An Example}
|
|
|
|
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
|
|
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.diff is now on top
|
|
\sh{$ quilt edit Oberon.txt}
|
|
File Oberon.txt added to patch flower.diff
|
|
\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.diff
|
|
\sh{$ quilt pop}
|
|
Removing flower.diff
|
|
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.diff
|
|
patching file Oberon.txt
|
|
Hunk #1 FAILED at 2.
|
|
1 out of 1 hunk FAILED -- rejects in file Oberon.txt
|
|
Patch flower.diff 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.diff
|
|
patching file Oberon.txt
|
|
Hunk #1 FAILED at 2.
|
|
1 out of 1 hunk FAILED -- saving rejects to file Oberon.txt.rej
|
|
Applied flower.diff (forced; needs refresh)
|
|
\end{Verbatim}
|
|
\end{small}
|
|
|
|
After re-adding the lines 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.diff
|
|
\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.diff
|
|
\sh{$ quilt files}
|
|
Oberon.txt
|
|
\sh{$ quilt patches Oberon.txt}
|
|
flower.diff
|
|
\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. This can be done by hand by first
|
|
adding all the files contained in the additional patch to the topmost
|
|
patch with \quilt{add},\footnote{
|
|
The \prog{lsdiff} utility, which is part of the \textit{patchutils}
|
|
package, generates a list of files affected by a patch.
|
|
} and then applying the patch to the working tree. The \quilt{fold}
|
|
command combines these steps.
|
|
|
|
\subsection{Sharing patches with others}
|
|
|
|
For sharing a set of patches with someone else, the series file which
|
|
contains the list of patches and how they are applied, and the patches
|
|
themselves are all that's needed. The \textsl{.pc} directory only
|
|
contains quilt's working state, and should not be distributed. Make sure
|
|
that all the patches are up-to-date, and refresh patches when
|
|
necessary. The \textsf{--combine} option of \quilt{diff} can be used for
|
|
generating a single patch out of all the patches in the series file.
|
|
|
|
\subsection{Merging with upstream}
|
|
|
|
The concept of merging your patches with upstream is identical to applying
|
|
your patches on a more recent version of the software.
|
|
|
|
Before merging, make sure to pop all your patches using \quilt{pop -a}.
|
|
Then, update your codebase. Finally, remove obsoleted patches
|
|
from the series file and \quilt{push} the remaining ones, resolve
|
|
conflicts and refresh patches as needed.
|
|
|
|
\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
|
|
topmost patch in the series, 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{Dependencies}
|
|
\label{sec:dependencies}
|
|
|
|
When the number of patches in a project grows large, it becomes
|
|
increasingly difficult to find the right place for adding a new patch in
|
|
the patch series. At a certain point, patches will get inserted at the
|
|
end of the patch series, because finding the right place has become too
|
|
complicated. In the long run, a mess accumulates.
|
|
|
|
To help avoid this by keeping the big picture, the \quilt{graph} command
|
|
generates \textit{dot} graphs showing the dependencies between
|
|
patches.\footnote{
|
|
The \quilt{graph} command computes dependencies based on
|
|
which patches modify which files, and optionally will also
|
|
check for overlapping changes in the files. While the former
|
|
approach will often result in false positives, the latter
|
|
approach may result in false negatives (that is, \quilt{graph}
|
|
may overlook dependencies).
|
|
} The output of this command can be visualized using the tools from AT\&T
|
|
Research's Graph Visualization Project (GraphViz,
|
|
\url{http://www.graphviz.org/}). The \quilt{graph} command supports
|
|
different kinds of graphs.
|
|
|
|
\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{Customizing Quilt}
|
|
|
|
Upon startup, quilt evaluates the file \textsf{.quiltrc} in the user's
|
|
home directory, or the file specified with the \textsf{--quiltrc} option.
|
|
This file is a regular bash script. Default options can be passed to
|
|
any command by defining a \textsf{QUILT\_\textit{COMMAND}\_ARGS} variable
|
|
(for example, \textsf{QUILT\_DIFF\_ARGS="--color=auto"} causes the output
|
|
of \quilt{diff} to be syntax colored when writing to a terminal).
|
|
|
|
In addition to that, quilt recognizes the following variables:
|
|
|
|
\begin{description}
|
|
|
|
\item[\textsf{QUILT\_DIFF\_OPTS}]
|
|
Additional options that quilt shall pass to \prog{GNU diff} when
|
|
generating patches. A useful setting for C source code is
|
|
``\textsf{-p}'', which causes \prog{GNU diff} to show in the resulting
|
|
patch which function a change is in.
|
|
|
|
\item[\textsf{QUILT\_PATCH\_OPTS}]
|
|
Additional options that quilt shall pass to \prog{GNU patch} when
|
|
applying patches. (For example, recent versions of \prog{GNU patch}
|
|
support the ``\textsf{--reject-format=unified}'' option for generating
|
|
reject files in unified diff style (older versions used
|
|
``\textsf{--unified-reject-files}'' for that).
|
|
|
|
\item[\textsf{QUILT\_PATCHES}]
|
|
The location of patch files (see Section~\ref{sec:basic}). This setting
|
|
defaults to ``\textsf{patches}''.
|
|
|
|
\end{description}
|
|
|
|
\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://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz}.
|
|
|
|
\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}
|