hgbook

changeset 106:9cbc5d0db542

Finish off advanced MQ chapter (maybe).
author Bryan O'Sullivan <bos@serpentine.com>
date Mon Oct 23 15:43:04 2006 -0700 (2006-10-23)
parents ecacb6b4c9fd
children a0d7e11db169
files en/99defs.tex en/mq-collab.tex en/mq.tex examples/hg-interdiff
line diff
     1.1 --- a/en/99defs.tex	Sat Oct 21 11:05:51 2006 -0700
     1.2 +++ b/en/99defs.tex	Mon Oct 23 15:43:04 2006 -0700
     1.3 @@ -106,6 +106,9 @@
     1.4  % Interaction from the examples directory.
     1.5  \newcommand{\interaction}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{examples/#1.out}}
     1.6  
     1.7 +% Example code from the examples directory.
     1.8 +\newcommand{\excode}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{../examples/#1}}
     1.9 +
    1.10  % Graphics inclusion.
    1.11  \ifpdf
    1.12    \newcommand{\grafix}[1]{\includegraphics{#1}}
     2.1 --- a/en/mq-collab.tex	Sat Oct 21 11:05:51 2006 -0700
     2.2 +++ b/en/mq-collab.tex	Mon Oct 23 15:43:04 2006 -0700
     2.3 @@ -154,15 +154,12 @@
     2.4  \interaction{mq.guards.qselect.qpush}
     2.5  
     2.6  A guard cannot start with a ``\texttt{+}'' or ``\texttt{-}''
     2.7 -character.  The name of a guard must start with an alphabetic
     2.8 -character (upper or lower case) or an underscore.  The rest of the
     2.9 -guard's name can contain any of these characters, or a digit.  These
    2.10 -rules are similar to those used for variable naming in most popular
    2.11 -programming languages.  If you try to use a guard with an invalid
    2.12 -name, MQ will complain:
    2.13 -\interaction{mq.guards.qselect.error}
    2.14 +character.  The name of a guard must not contain white space, but most
    2.15 +othter characters are acceptable.  If you try to use a guard with an
    2.16 +invalid name, MQ will complain:
    2.17 +\interaction{mq.guards.qselect.error} 
    2.18  Changing the selected guards changes the patches that are applied.
    2.19 -\interaction{mq.guards.qselect.quux}
    2.20 +\interaction{mq.guards.qselect.quux} 
    2.21  You can see in the example below that negative guards take precedence
    2.22  over positive guards.
    2.23  \interaction{mq.guards.qselect.foobar}
    2.24 @@ -250,9 +247,132 @@
    2.25  a while.
    2.26  
    2.27  The ``backport'' and ``do not ship'' patches float at the end of the
    2.28 -\sfilename{series} file in part because they'll never be shipped
    2.29 -upstream.  Additionally, the backport patches must be applied on top
    2.30 -of all other patches.
    2.31 +\sfilename{series} file.  The backport patches must be applied on top
    2.32 +of all other patches, and the ``do not ship'' patches might as well
    2.33 +stay out of harm's way.
    2.34 +
    2.35 +\section{Maintaining the patch series}
    2.36 +
    2.37 +In my work, I use a number of guards to control which patches are to
    2.38 +be applied.
    2.39 +
    2.40 +\begin{itemize}
    2.41 +\item ``Accepted'' patches are guarded with \texttt{accepted}.  I
    2.42 +  enable this guard most of the time.  When I'm applying the patches
    2.43 +  on top of a tree where the patches are already present, I can turn
    2.44 +  this patch off, and the paptches that follow it will apply cleanly.
    2.45 +\item Patches that are ``finished'', but not yet submitted, have no
    2.46 +  guards.  If I'm applying the patch stack to a copy of the upstream
    2.47 +  tree, I don't need to enable any guards in order to get a reasonably
    2.48 +  safe source tree.
    2.49 +\item Those patches that need reworking before being resubmitted are
    2.50 +  guarded with \texttt{rework}.
    2.51 +\item For those patches that are still under development, I use
    2.52 +  \texttt{devel}.
    2.53 +\item A backport patch may have several guards, one for each version
    2.54 +  of the kernel to which it applies.  For example, a patch that
    2.55 +  backports a piece of code to~2.6.9 will have a~\texttt{2.6.9} guard.
    2.56 +\end{itemize}
    2.57 +This variety of guards gives me considerable flexibility in
    2.58 +qdetermining what kind of source tree I want to end up with.  For most
    2.59 +situations, the selection of appropriate guards is automated during
    2.60 +the build process, but I can manually tune the guards to use for less
    2.61 +common circumstances.
    2.62 +
    2.63 +\subsection{The art of writing backport patches}
    2.64 +
    2.65 +Using MQ, writing a backport patch is a simple process.  All such a
    2.66 +patch has to do is modify a piece of code that uses a kernel feature
    2.67 +not present in the older version of the kernel, so that the driver
    2.68 +continues to work correctly under that older version.
    2.69 +
    2.70 +A useful goal when writing a good backport patch is to make your code
    2.71 +look as if it was written for the older version of the kernel you're
    2.72 +targeting.  The less obtrusive the patch, the easier it will be to
    2.73 +understand and maintain.  If you're writing a collection of backport
    2.74 +patches to avoid the ``rat's nest'' effect of lots of
    2.75 +\texttt{\#ifdef}s (hunks of source code that are only used
    2.76 +conditionally) in your code, don't introduce version-dependent
    2.77 +\texttt{\#ifdef}s into the patches.  Instead, write several patches,
    2.78 +each of which makes unconditional changes, and control their
    2.79 +application using guards.
    2.80 +
    2.81 +There are two reasons to divide backport patches into a distinct
    2.82 +group, away from the ``regular'' patches whose effects they modify.
    2.83 +The first is that intermingling the two makes it more difficult to use
    2.84 +a tool like the \hgext{patchbomb} extension to automate the process of
    2.85 +submitting the patches to an upstream maintainer.  The second is that
    2.86 +a backport patch could perturb the context in which a subsequent
    2.87 +regular patch is applied, making it impossible to apply the regular
    2.88 +patch cleanly \emph{without} the earlier backport patch already being
    2.89 +applied.
    2.90 +
    2.91 +\section{Useful tips for developing with MQ}
    2.92 +
    2.93 +\subsection{Organising patches in directories}
    2.94 +
    2.95 +If you're working on a substantial project with MQ, it's not difficult
    2.96 +to accumulate a large number of patches.  For example, I have one
    2.97 +patch repository that contains over 250 patches.
    2.98 +
    2.99 +If you can group these patches into separate logical categories, you
   2.100 +can if you like store them in different directories; MQ has no
   2.101 +problems with patch names that contain path separators.
   2.102 +
   2.103 +\subsection{Viewing the history of a patch}
   2.104 +\label{mq-collab:tips:interdiff}
   2.105 +
   2.106 +If you're developing a set of patches over a long time, it's a good
   2.107 +idea to maintain them in a repository, as discussed in
   2.108 +section~\ref{sec:mq:repo}.  If you do so, you'll quickly discover that
   2.109 +using the \hgcmd{diff} command to look at the history of changes to a
   2.110 +patch is unworkable.  This is in part because you're looking at the
   2.111 +second derivative of the real code (a diff of a diff), but also
   2.112 +because MQ adds noise to the process by modifying time stamps and
   2.113 +directory names when it updates a patch.
   2.114 +
   2.115 +However, you can use the \hgext{extdiff} extension, which is bundled
   2.116 +with Mercurial, to turn a diff of two versions of a patch into
   2.117 +something readable.  To do this, you will need a third-party package
   2.118 +called \package{patchutils}~\cite{web:patchutils}.  This provides a
   2.119 +command named \command{interdiff}, which shows the differences between
   2.120 +two diffs as a diff.  Used on two versions of the same diff, it
   2.121 +generates a diff that represents the diff from the first to the second
   2.122 +version.
   2.123 +
   2.124 +You can enable the \hgext{extdiff} extension in the usual way, by
   2.125 +adding a line to the \rcsection{extensions} section of your \hgrc.
   2.126 +\begin{codesample2}
   2.127 +  [extensions]
   2.128 +  extdiff =
   2.129 +\end{codesample2}
   2.130 +The \command{interdiff} command expects to be passed the names of two
   2.131 +files, but the \hgext{extdiff} extension passes the program it runs a
   2.132 +pair of directories, each of which can contain an arbitrary number of
   2.133 +files.  We thus need a small program that will run \command{interdiff}
   2.134 +on each pair of files in these two directories.  This program is
   2.135 +available as \sfilename{hg-interdiff} in the \dirname{examples}
   2.136 +directory of the source code repository that accompanies this book.
   2.137 +\excode{hg-interdiff}
   2.138 +
   2.139 +With the \sfilename{hg-interdiff} program in your shell's search path,
   2.140 +you can run it as follows, from inside an MQ patch directory:
   2.141 +\begin{codesample2}
   2.142 +  hg extdiff -p hg-interdiff -r A:B my-change.patch
   2.143 +\end{codesample2}
   2.144 +Since you'll probably want to use this long-winded command a lot, you
   2.145 +can get \hgext{hgext} to make it available as a normal Mercurial
   2.146 +command, again by editing your \hgrc.
   2.147 +\begin{codesample2}
   2.148 +  [extdiff]
   2.149 +  cmd.interdiff = hg-interdiff
   2.150 +\end{codesample2}
   2.151 +This directs \hgext{hgext} to make an \texttt{interdiff} command
   2.152 +available, so you can now shorten the previous invocation of
   2.153 +\hgcmd{extdiff} to something a little more wieldy.
   2.154 +\begin{codesample2}
   2.155 +  hg interdiff -r A:B my-change.patch
   2.156 +\end{codesample2}
   2.157  
   2.158  %%% Local Variables: 
   2.159  %%% mode: latex
     3.1 --- a/en/mq.tex	Sat Oct 21 11:05:51 2006 -0700
     3.2 +++ b/en/mq.tex	Mon Oct 23 15:43:04 2006 -0700
     3.3 @@ -800,6 +800,7 @@
     3.4  \end{itemize}
     3.5  
     3.6  \section{Managing patches in a repository}
     3.7 +\label{sec:mq:repo}
     3.8  
     3.9  Because MQ's \sdirname{.hg/patches} directory resides outside a
    3.10  Mercurial repository's working directory, the ``underlying'' Mercurial
    3.11 @@ -894,7 +895,8 @@
    3.12  extracts subsets from a patch file.  For example, given a patch that
    3.13  modifies hundreds of files across dozens of directories, a single
    3.14  invocation of \command{filterdiff} can generate a smaller patch that
    3.15 -only touches files whose names match a particular glob pattern.
    3.16 +only touches files whose names match a particular glob pattern.  See
    3.17 +section~\ref{mq-collab:tips:interdiff} for another example.
    3.18  
    3.19  \section{Good ways to work with patches}
    3.20  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/examples/hg-interdiff	Mon Oct 23 15:43:04 2006 -0700
     4.3 @@ -0,0 +1,35 @@
     4.4 +#!/usr/bin/env python
     4.5 +#
     4.6 +# Adapter for using interdiff with mercurial's extdiff extension.
     4.7 +# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
     4.8 +
     4.9 +import os, sys
    4.10 +
    4.11 +def walk(base):
    4.12 +    # yield all non-directories below the base path.
    4.13 +    for root, dirs, files in os.walk(base):
    4.14 +        for f in files:
    4.15 +            path = os.path.join(root, f)
    4.16 +            yield path[len(base)+1:], path
    4.17 +
    4.18 +# create list of unique file names under both directories.
    4.19 +files = dict(walk(sys.argv[1]))
    4.20 +files.update(walk(sys.argv[2]))
    4.21 +files = files.keys()
    4.22 +files.sort()
    4.23 +
    4.24 +def name(base, f):
    4.25 +    # interdiff requires two files; use /dev/null if one is missing.
    4.26 +    path = os.path.join(base, f)
    4.27 +    if os.path.exists(path):
    4.28 +        return path
    4.29 +    return '/dev/null'
    4.30 +
    4.31 +ret = 0
    4.32 +
    4.33 +for f in files:
    4.34 +    if os.system('interdiff "%s" "%s"' % (name(sys.argv[1], f),
    4.35 +                                          name(sys.argv[2], f))):
    4.36 +        ret = 1
    4.37 +
    4.38 +sys.exit(ret)