hgbook
changeset 19:187702df428b
Piles of new content for MQ chapter - cookbook stuff.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Fri Jul 07 19:56:53 2006 -0700 (2006-07-07) |
parents | e6f4088ebe52 |
children | 2888fe6176b3 |
files | en/99defs.tex en/Makefile en/examples/data/netplug-1.2.5.tar.bz2 en/examples/data/netplug-1.2.8.tar.bz2 en/examples/data/remove-redundant-null-checks.patch en/examples/mq.diff en/examples/mq.tarball en/examples/mq.tools en/examples/run-example en/mq.tex |
line diff
1.1 --- a/en/99defs.tex Tue Jul 04 16:41:31 2006 -0700 1.2 +++ b/en/99defs.tex Fri Jul 07 19:56:53 2006 -0700 1.3 @@ -6,8 +6,10 @@ 1.4 \newcommand{\hgext}[1]{\index{\texttt{#1} extension}\texttt{#1}} 1.5 \newcommand{\hgcmd}[1]{\index{\texttt{#1} command}``\texttt{hg #1}''} 1.6 \newcommand{\command}[1]{\index{\texttt{#1} command}\texttt{#1}} 1.7 +\newcommand{\cmdargs}[2]{\index{\texttt{#1} command}\texttt{#1 #2}} 1.8 \newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''} 1.9 \newcommand{\hgopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}} 1.10 +\newcommand{\cmdopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}} 1.11 \newcommand{\package}[1]{\index{\texttt{#1} package}\texttt{#1}} 1.12 1.13 \newsavebox{\notebox}
2.1 --- a/en/Makefile Tue Jul 04 16:41:31 2006 -0700 2.2 +++ b/en/Makefile Fri Jul 07 19:56:53 2006 -0700 2.3 @@ -16,6 +16,9 @@ 2.4 example-sources := \ 2.5 examples/run-example \ 2.6 examples/mq.qinit-help \ 2.7 + examples/mq.diff \ 2.8 + examples/mq.tarball \ 2.9 + examples/mq.tools \ 2.10 examples/mq.tutorial 2.11 2.12 latex-options = \
3.1 Binary file en/examples/data/netplug-1.2.5.tar.bz2 has changed
4.1 Binary file en/examples/data/netplug-1.2.8.tar.bz2 has changed
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/en/examples/data/remove-redundant-null-checks.patch Fri Jul 07 19:56:53 2006 -0700 5.3 @@ -0,0 +1,190 @@ 5.4 + 5.5 +From: Jesper Juhl <jesper.juhl@gmail.com> 5.6 + 5.7 +Remove redundant NULL chck before kfree + tiny CodingStyle cleanup for 5.8 +drivers/ 5.9 + 5.10 +Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com> 5.11 +Signed-off-by: Andrew Morton <akpm@osdl.org> 5.12 +--- 5.13 + 5.14 + drivers/char/agp/sgi-agp.c | 5 ++--- 5.15 + drivers/char/hvcs.c | 11 +++++------ 5.16 + drivers/message/fusion/mptfc.c | 6 ++---- 5.17 + drivers/message/fusion/mptsas.c | 3 +-- 5.18 + drivers/net/fs_enet/fs_enet-mii.c | 3 +-- 5.19 + drivers/net/wireless/ipw2200.c | 22 ++++++---------------- 5.20 + drivers/scsi/libata-scsi.c | 4 +--- 5.21 + drivers/video/au1100fb.c | 3 +-- 5.22 + 8 files changed, 19 insertions(+), 38 deletions(-) 5.23 + 5.24 +diff -puN drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/agp/sgi-agp.c 5.25 +--- a/drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers 5.26 ++++ a/drivers/char/agp/sgi-agp.c 5.27 +@@ -329,9 +329,8 @@ static int __devinit agp_sgi_init(void) 5.28 + 5.29 + static void __devexit agp_sgi_cleanup(void) 5.30 + { 5.31 +- if (sgi_tioca_agp_bridges) 5.32 +- kfree(sgi_tioca_agp_bridges); 5.33 +- sgi_tioca_agp_bridges=NULL; 5.34 ++ kfree(sgi_tioca_agp_bridges); 5.35 ++ sgi_tioca_agp_bridges = NULL; 5.36 + } 5.37 + 5.38 + module_init(agp_sgi_init); 5.39 +diff -puN drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/hvcs.c 5.40 +--- a/drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers 5.41 ++++ a/drivers/char/hvcs.c 5.42 +@@ -1320,11 +1320,12 @@ static struct tty_operations hvcs_ops = 5.43 + static int hvcs_alloc_index_list(int n) 5.44 + { 5.45 + int i; 5.46 ++ 5.47 + hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL); 5.48 + if (!hvcs_index_list) 5.49 + return -ENOMEM; 5.50 + hvcs_index_count = n; 5.51 +- for(i = 0; i < hvcs_index_count; i++) 5.52 ++ for (i = 0; i < hvcs_index_count; i++) 5.53 + hvcs_index_list[i] = -1; 5.54 + return 0; 5.55 + } 5.56 +@@ -1332,11 +1333,9 @@ static int hvcs_alloc_index_list(int n) 5.57 + static void hvcs_free_index_list(void) 5.58 + { 5.59 + /* Paranoia check to be thorough. */ 5.60 +- if (hvcs_index_list) { 5.61 +- kfree(hvcs_index_list); 5.62 +- hvcs_index_list = NULL; 5.63 +- hvcs_index_count = 0; 5.64 +- } 5.65 ++ kfree(hvcs_index_list); 5.66 ++ hvcs_index_list = NULL; 5.67 ++ hvcs_index_count = 0; 5.68 + } 5.69 + 5.70 + static int __init hvcs_module_init(void) 5.71 +diff -puN drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptfc.c 5.72 +--- a/drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers 5.73 ++++ a/drivers/message/fusion/mptfc.c 5.74 +@@ -305,10 +305,8 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in 5.75 + } 5.76 + 5.77 + out: 5.78 +- if (pp0_array) 5.79 +- kfree(pp0_array); 5.80 +- if (p0_array) 5.81 +- kfree(p0_array); 5.82 ++ kfree(pp0_array); 5.83 ++ kfree(p0_array); 5.84 + return rc; 5.85 + } 5.86 + 5.87 +diff -puN drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptsas.c 5.88 +--- a/drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers 5.89 ++++ a/drivers/message/fusion/mptsas.c 5.90 +@@ -1378,8 +1378,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) 5.91 + return 0; 5.92 + 5.93 + out_free_port_info: 5.94 +- if (hba) 5.95 +- kfree(hba); 5.96 ++ kfree(hba); 5.97 + out: 5.98 + return error; 5.99 + } 5.100 +diff -puN drivers/net/fs_enet/fs_enet-mii.c~remove-redundant-null-checks-before-free-in-drivers drivers/net/fs_enet/fs_enet-mii.c 5.101 +--- a/drivers/net/fs_enet/fs_enet-mii.c~remove-redundant-null-checks-before-free-in-drivers 5.102 ++++ a/drivers/net/fs_enet/fs_enet-mii.c 5.103 +@@ -431,8 +431,7 @@ static struct fs_enet_mii_bus *create_bu 5.104 + return bus; 5.105 + 5.106 + err: 5.107 +- if (bus) 5.108 +- kfree(bus); 5.109 ++ kfree(bus); 5.110 + return ERR_PTR(ret); 5.111 + } 5.112 + 5.113 +diff -puN drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers drivers/net/wireless/ipw2200.c 5.114 +--- a/drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers 5.115 ++++ a/drivers/net/wireless/ipw2200.c 5.116 +@@ -1229,12 +1229,6 @@ static struct ipw_fw_error *ipw_alloc_er 5.117 + return error; 5.118 + } 5.119 + 5.120 +-static void ipw_free_error_log(struct ipw_fw_error *error) 5.121 +-{ 5.122 +- if (error) 5.123 +- kfree(error); 5.124 +-} 5.125 +- 5.126 + static ssize_t show_event_log(struct device *d, 5.127 + struct device_attribute *attr, char *buf) 5.128 + { 5.129 +@@ -1296,10 +1290,9 @@ static ssize_t clear_error(struct device 5.130 + const char *buf, size_t count) 5.131 + { 5.132 + struct ipw_priv *priv = dev_get_drvdata(d); 5.133 +- if (priv->error) { 5.134 +- ipw_free_error_log(priv->error); 5.135 +- priv->error = NULL; 5.136 +- } 5.137 ++ 5.138 ++ kfree(priv->error); 5.139 ++ priv->error = NULL; 5.140 + return count; 5.141 + } 5.142 + 5.143 +@@ -1970,8 +1963,7 @@ static void ipw_irq_tasklet(struct ipw_p 5.144 + struct ipw_fw_error *error = 5.145 + ipw_alloc_error_log(priv); 5.146 + ipw_dump_error_log(priv, error); 5.147 +- if (error) 5.148 +- ipw_free_error_log(error); 5.149 ++ kfree(error); 5.150 + } 5.151 + #endif 5.152 + } else { 5.153 +@@ -11693,10 +11685,8 @@ static void ipw_pci_remove(struct pci_de 5.154 + } 5.155 + } 5.156 + 5.157 +- if (priv->error) { 5.158 +- ipw_free_error_log(priv->error); 5.159 +- priv->error = NULL; 5.160 +- } 5.161 ++ kfree(priv->error); 5.162 ++ priv->error = NULL; 5.163 + 5.164 + #ifdef CONFIG_IPW2200_PROMISCUOUS 5.165 + ipw_prom_free(priv); 5.166 +diff -puN drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers drivers/scsi/libata-scsi.c 5.167 +--- a/drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers 5.168 ++++ a/drivers/scsi/libata-scsi.c 5.169 +@@ -222,9 +222,7 @@ int ata_cmd_ioctl(struct scsi_device *sc 5.170 + && copy_to_user(arg + sizeof(args), argbuf, argsize)) 5.171 + rc = -EFAULT; 5.172 + error: 5.173 +- if (argbuf) 5.174 +- kfree(argbuf); 5.175 +- 5.176 ++ kfree(argbuf); 5.177 + return rc; 5.178 + } 5.179 + 5.180 +diff -puN drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers drivers/video/au1100fb.c 5.181 +--- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers 5.182 ++++ a/drivers/video/au1100fb.c 5.183 +@@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void) 5.184 + { 5.185 + driver_unregister(&au1100fb_driver); 5.186 + 5.187 +- if (drv_info.opt_mode) 5.188 +- kfree(drv_info.opt_mode); 5.189 ++ kfree(drv_info.opt_mode); 5.190 + } 5.191 + 5.192 + module_init(au1100fb_init); 5.193 +_
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/en/examples/mq.diff Fri Jul 07 19:56:53 2006 -0700 6.3 @@ -0,0 +1,12 @@ 6.4 +#$ name: diff 6.5 + 6.6 +echo 'this is my first line' > oldfile 6.7 +echo 'my first line is here' > newfile 6.8 + 6.9 +diff -u oldfile newfile > tiny.patch 6.10 + 6.11 +cat tiny.patch 6.12 + 6.13 +patch < tiny.patch 6.14 + 6.15 +cat newfile
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/en/examples/mq.tarball Fri Jul 07 19:56:53 2006 -0700 7.3 @@ -0,0 +1,48 @@ 7.4 +cp $EXAMPLE_DIR/data/netplug-*.tar.bz2 . 7.5 +ln -s /bin/true download 7.6 + 7.7 +#$ name: download 7.8 + 7.9 +download netplug-1.2.5.tar.bz2 7.10 +tar jxf netplug-1.2.5.tar.bz2 7.11 +cd netplug-1.2.5 7.12 +hg init 7.13 +hg commit -q --addremove --message netplug-1.2.5 7.14 +cd .. 7.15 +hg clone netplug-1.2.5 netplug 7.16 + 7.17 +#$ name: 7.18 + 7.19 +cd netplug 7.20 +echo '[extensions]' >> $HGRC 7.21 +echo 'hgext.mq =' >> $HGRC 7.22 +cd .. 7.23 + 7.24 +#$ name: qinit 7.25 + 7.26 +cd netplug 7.27 +hg qinit 7.28 +hg qnew -m 'fix build problem with gcc 4' build-fix.patch 7.29 +perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c 7.30 +hg qrefresh 7.31 +hg tip -p 7.32 + 7.33 +#$ name: newsource 7.34 + 7.35 +hg qpop -a 7.36 +cd .. 7.37 +download netplug-1.2.8.tar.bz2 7.38 +hg clone netplug-1.2.5 netplug-1.2.8 7.39 +cd netplug-1.2.8 7.40 +hg locate -0 | xargs -0 rm 7.41 +cd .. 7.42 +tar jxf netplug-1.2.8.tar.bz2 7.43 +cd netplug-1.2.8 7.44 +hg commit --addremove --message netplug-1.2.8 7.45 + 7.46 +#$ name: repush 7.47 + 7.48 +cd ../netplug 7.49 +hg pull ../netplug-1.2.8 7.50 +hg qpush -a 7.51 +
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/en/examples/mq.tools Fri Jul 07 19:56:53 2006 -0700 8.3 @@ -0,0 +1,9 @@ 8.4 +cp $EXAMPLE_DIR/data/remove-redundant-null-checks.patch . 8.5 + 8.6 +#$ name: tools 8.7 +diffstat -p1 remove-redundant-null-checks.patch 8.8 + 8.9 +filterdiff -i '*/video/*' remove-redundant-null-checks.patch 8.10 + 8.11 +#$ name: lsdiff 8.12 +lsdiff -nvv remove-redundant-null-checks.patch
9.1 --- a/en/examples/run-example Tue Jul 04 16:41:31 2006 -0700 9.2 +++ b/en/examples/run-example Fri Jul 07 19:56:53 2006 -0700 9.3 @@ -76,6 +76,7 @@ 9.4 rcfp = open(rcfile, 'w') 9.5 print >> rcfp, 'PS1="%s"' % self.prompt 9.6 print >> rcfp, 'unset HISTFILE' 9.7 + print >> rcfp, 'export EXAMPLE_DIR="%s"' % os.getcwd() 9.8 print >> rcfp, 'export LANG=C' 9.9 print >> rcfp, 'export LC_ALL=C' 9.10 print >> rcfp, 'export TZ=GMT' 9.11 @@ -117,7 +118,7 @@ 9.12 if nl: hunk += '\n' 9.13 ofp.write(hunk) 9.14 # then its output 9.15 - ofp.write(output) 9.16 + ofp.write(tex_escape(output)) 9.17 self.status('\n') 9.18 finally: 9.19 try: 9.20 @@ -140,7 +141,9 @@ 9.21 for name in os.listdir(path): 9.22 if name == 'run-example' or name.startswith('.'): continue 9.23 if name.endswith('.out') or name.endswith('~'): continue 9.24 - example(os.path.join(path, name)).run() 9.25 + pathname = os.path.join(path, name) 9.26 + if os.path.isfile(pathname): 9.27 + example(pathname).run() 9.28 print >> open(os.path.join(path, '.run'), 'w'), time.asctime() 9.29 9.30 if __name__ == '__main__':
10.1 --- a/en/mq.tex Tue Jul 04 16:41:31 2006 -0700 10.2 +++ b/en/mq.tex Fri Jul 07 19:56:53 2006 -0700 10.3 @@ -126,6 +126,62 @@ 10.4 Because quilt does not care about revision control tools, it is still 10.5 a tremendously useful piece of software to know about for situations 10.6 where you cannot use Mercurial and MQ. 10.7 + 10.8 +\section{Understanding patches} 10.9 + 10.10 +Because MQ doesn't hide its patch-oriented nature, it is helpful to 10.11 +understand what patches are, and a little about the tools that work 10.12 +with them. 10.13 + 10.14 +The traditional Unix \command{diff} command compares two files, and 10.15 +prints a list of differences between them. The \command{patch} command 10.16 +understands these differences as \emph{modifications} to make to a 10.17 +file. Take a look at figure~\ref{ex:mq:diff} for a simple example of 10.18 +these commands in action. 10.19 + 10.20 +\begin{figure}[ht] 10.21 + \interaction{mq.diff.diff} 10.22 + \caption{Simple uses of the \command{diff} and \command{patch} commands} 10.23 + \label{ex:mq:diff} 10.24 +\end{figure} 10.25 + 10.26 +The type of file that \command{diff} generates (and \command{patch} 10.27 +takes as input) is called a ``patch'' or a ``diff''; there is no 10.28 +difference between a patch and a diff. (We'll use the term ``patch'', 10.29 +since it's more commonly used.) 10.30 + 10.31 +A patch file can start with arbitrary text; the \command{patch} 10.32 +command ignores this text, but MQ uses it as the commit message when 10.33 +creating changesets. To find the beginning of the patch content, 10.34 +\command{patch} searches for the first line that starts with the 10.35 +string ``\texttt{diff~-}''. 10.36 + 10.37 +MQ works with \emph{unified} diffs (\command{patch} can accept several 10.38 +other diff formats, but MQ doesn't). A unified diff contains two 10.39 +kinds of header. The \emph{file header} describes the file being 10.40 +modified; it contains the name of the file to modify. When 10.41 +\command{patch} sees a new file header, it looks for a file with that 10.42 +name to start modifying. 10.43 + 10.44 +After the file header comes a series of \emph{hunks}. Each hunk 10.45 +starts with a header; this identifies the range of line numbers within 10.46 +the file that the hunk should modify. Following the header, a hunk 10.47 +starts and ends with a few (usually three) lines of text from the 10.48 +unmodified file; these are called the \emph{context} for the hunk. If 10.49 +there's only a small amount of context between successive hunks, 10.50 +\command{diff} doesn't print a new hunk header; it just runs the hunks 10.51 +together, with a few lines of context between modifications. 10.52 + 10.53 +Each line of context begins with a space character. Within the hunk, 10.54 +a line that begins with ``\texttt{-}'' means ``remove this line,'' 10.55 +while a line that begins with ``\texttt{+}'' means ``insert this 10.56 +line.'' For example, a line that is modified is represented by one 10.57 +deletion and one insertion. 10.58 + 10.59 +We will return to ome of the more subtle aspects of patches later (in 10.60 +section~\ref{ex:mq:adv-patch}), but you should have enough information 10.61 +now to use MQ. 10.62 + 10.63 \section{Getting started with Mercurial Queues} 10.64 \label{sec:mq:start} 10.65 10.66 @@ -200,6 +256,7 @@ 10.67 working directory as you usually would. All of the normal Mercurial 10.68 commands, such as \hgcmd{diff} and \hgcmd{annotate}, work exactly as 10.69 they did before. 10.70 + 10.71 \subsection{Refreshing a patch} 10.72 10.73 When you reach a point where you want to save your work, use the 10.74 @@ -319,45 +376,12 @@ 10.75 \hgcmd{qrefresh} the core patch, and \hgcmd{qpush} back to the UI 10.76 patch to continue where you left off. 10.77 10.78 -\section{Mercurial Queues and GNU patch} 10.79 -\label{sec:mq:patch} 10.80 - 10.81 -MQ uses the GNU \command{patch} command to apply patches. Because MQ 10.82 -doesn't hide its patch-oriented nature, it is helpful to understand 10.83 -the data that MQ and \command{patch} work with, and a few aspects of 10.84 -how \command{patch} operates. 10.85 - 10.86 -The \command{diff} command generates a list of modifications by 10.87 -comparing two files. The \command{patch} command applies a list of 10.88 -modifications to a file. The kinds of files that \command{diff} and 10.89 -\command{patch} work with are referred to as both ``diffs'' and 10.90 -``patches;'' there is no difference between a diff and a patch. 10.91 - 10.92 -A patch file can start with arbitrary text; MQ uses this text as the 10.93 -commit message when creating changesets. It treats the first line 10.94 -that starts with the string ``\texttt{diff~-}'' as the separator 10.95 -between header and content. 10.96 - 10.97 -MQ works with \emph{unified} diffs (\command{patch} can accept several 10.98 -other diff formats, but MQ doesn't). A unified diff contains two 10.99 -kinds of header. The \emph{file header} describes the file being 10.100 -modified; it contains the name of the file to modify. When 10.101 -\command{patch} sees a new file header, it looks for a file with that 10.102 -name to start modifying. 10.103 - 10.104 -After the file header comes a series of \emph{hunks}. Each hunk 10.105 -starts with a header; this identifies the range of line numbers within 10.106 -the file that the hunk should modify. Following the header, a hunk 10.107 -starts and ends with a few (usually three) lines of text from the 10.108 -unmodified file; these are called the \emph{context} for the hunk. 10.109 -Each unmodified line begins with a space characters. Within the hunk, 10.110 -a line that begins with ``\texttt{-}'' means ``remove this line,'' 10.111 -while a line that begins with ``\texttt{+}'' means ``insert this 10.112 -line.'' For example, a line that is modified is represented by one 10.113 -deletion and one insertion. 10.114 - 10.115 -The \command{diff} command runs hunks together when there's not enough 10.116 -context between modifications to justify 10.117 +\section{More about patches} 10.118 +\label{sec:mq:adv-patch} 10.119 + 10.120 +MQ uses the GNU \command{patch} command to apply patches, so it's 10.121 +helpful to know about a few more detailed aspects of how 10.122 +\command{patch} works. 10.123 10.124 When \command{patch} applies a hunk, it tries a handful of 10.125 successively less accurate strategies to try to make the hunk apply. 10.126 @@ -622,6 +646,7 @@ 10.127 confuse MQ's idea of which patches are applied. 10.128 10.129 \section{Commands for working with patches} 10.130 +\label{sec:mq:tools} 10.131 10.132 Once you've been working with patches for a while, you'll find 10.133 yourself hungry for tools that will help you to understand and 10.134 @@ -636,6 +661,12 @@ 10.135 do clever things with prefixes of file names that inevitably confuse 10.136 at least me.) 10.137 10.138 +\begin{figure}[ht] 10.139 + \interaction{mq.tools.tools} 10.140 + \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands} 10.141 + \label{ex:mq:tools} 10.142 +\end{figure} 10.143 + 10.144 The \package{patchutils} package~\cite{web:patchutils} is invaluable. 10.145 It provides a set of small utilities that follow the ``Unix 10.146 philosophy;'' each does one useful thing with a patch. The 10.147 @@ -645,6 +676,122 @@ 10.148 invocation of \command{filterdiff} can generate a smaller patch that 10.149 only touches files whose names match a particular glob pattern. 10.150 10.151 +\section{Good ways to work with patches} 10.152 + 10.153 +Whether you are working on a patch series to submit to a free software 10.154 +or open source project, or a series that you intend to treat as a 10.155 +sequence of regular changesets when you're done, you can use some 10.156 +simple techniques to keep your work well organised. 10.157 + 10.158 +Give your patches descriptive names. A good name for a patch might be 10.159 +\filename{rework-device-alloc.patch}, because it will immediately give 10.160 +you a hint what the purpose of the patch is. Long names shouldn't be 10.161 +a problem; you won't be typing the names often, but you \emph{will} be 10.162 +running commands like \hgcmd{qapplied} and \hgcmd{qtop} over and over. 10.163 +Good naming becomes especially important when you have a number of 10.164 +patches to work with, or if you are juggling a number of different 10.165 +tasks and your patches only get a fraction of your attention. 10.166 + 10.167 +Be aware of what patch you're working on. Use the \hgcmd{qtop} 10.168 +command and skim over the text of your patches frequently---for 10.169 +example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where 10.170 +you stand. I have several times worked on and \hgcmd{qrefresh}ed a 10.171 +patch other than the one I intended, and it's often tricky to migrate 10.172 +changes into the right patch after making them in the wrong one. 10.173 + 10.174 +For this reason, it is very much worth investing a little time to 10.175 +learn how to use some of the third-party tools I described in 10.176 +section~\ref{sec:mq:tools}, particularly \command{diffstat} and 10.177 +\command{filterdiff}. The former will give you a quick idea of what 10.178 +changes your patch is making, while the latter makes it easy to splice 10.179 +hunks selectively out of one patch and into another. 10.180 + 10.181 +\section{MQ cookbook} 10.182 + 10.183 +\subsection{Manage ``trivial'' patches} 10.184 + 10.185 +Because the overhead of dropping files into a new Mercurial repository 10.186 +is so low, it makes a lot of sense to manage patches this way even if 10.187 +you simply want to make a few changes to a source tarball that you 10.188 +downloaded. 10.189 + 10.190 +Begin by downloading and unpacking the source tarball, 10.191 +and turning it into a Mercurial repository. 10.192 +\interaction{mq.tarball.download} 10.193 + 10.194 +Continue by creating a patch stack and making your changes. 10.195 +\interaction{mq.tarball.qinit} 10.196 + 10.197 +Let's say a few weeks or months pass, and your package author releases 10.198 +a new version. First, bring their changes into the repository. 10.199 +\interaction{mq.tarball.newsource} 10.200 +The pipeline starting with \hgcmd{locate} above deletes all files in 10.201 +the working directory, so that \hgcmd{commit}'s 10.202 +\hgopt{commit}{--addremove} option can actually tell which files have 10.203 +really been removed in the newer version of the source. 10.204 + 10.205 +Finally, you can apply your patches on top of the new tree. 10.206 +\interaction{mq.tarball.repush} 10.207 + 10.208 +\subsection{Combining entire patches} 10.209 +\label{sec:mq:combine} 10.210 + 10.211 +It's easy to combine entire patches. 10.212 + 10.213 +\begin{enumerate} 10.214 +\item \hgcmd{qpop} your applied patches until neither patch is 10.215 + applied. 10.216 +\item Concatenate the patches that you want to combine together: 10.217 + \begin{codesample4} 10.218 + cat patch-to-drop.patch >> patch-to-augment.patch 10.219 + \end{codesample4} 10.220 + The description from the first patch (if you have one) will be used 10.221 + as the commit comment when you \hgcmd{qpush} the combined patch. 10.222 + Edit the patch description if you need to. 10.223 +\item Use the \hgcmd{qdel} command to delete the patch you're dropping 10.224 + from the \sfilename{series} file. 10.225 +\item \hgcmd{qpush} the combined patch. Fix up any rejects. 10.226 +\item \hgcmd{qrefresh} the combined patch to tidy it up. 10.227 +\end{enumerate} 10.228 + 10.229 +\subsection{Merging part of one patch into another} 10.230 + 10.231 +Merging \emph{part} of one patch into another is more difficult than 10.232 +combining entire patches. 10.233 + 10.234 +If you want to move changes to entire files, you can use 10.235 +\command{filterdiff}'s \cmdopt{filterdiff}{-i} and 10.236 +\cmdopt{filterdiff}{-x} options to choose the modifications to snip 10.237 +out of one patch, concatenating its output onto the end of the patch 10.238 +you want to merge into. You usually won't need to modify the patch 10.239 +you've merged the changes from. Instead, MQ will report some rejected 10.240 +hunks when you \hgcmd{qpush} it (from the hunks you moved into the 10.241 +other patch), and you can simply \hgcmd{qrefresh} the patch to drop 10.242 +the duplicate hunks. 10.243 + 10.244 +If you have a patch that has multiple hunks modifying a file, and you 10.245 +only want to move a few of those hunks, the job becomes more messy, 10.246 +but you can still partly automate it. Use \cmdargs{lsdiff}{-nvv} to 10.247 +print some metadata about the patch. 10.248 +\interaction{mq.tools.lsdiff} 10.249 + 10.250 +This command prints three different kinds of number: 10.251 +\begin{itemize} 10.252 +\item a \emph{file number} to identify each file modified in the patch; 10.253 +\item the line number within a modified file that a hunk starts at; and 10.254 +\item a \emph{hunk number} to identify that hunk. 10.255 +\end{itemize} 10.256 + 10.257 +You'll have to use some visual inspection, and reading of the patch, 10.258 +to identify the file and hunk numbers you'll want, but you can then 10.259 +pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files} 10.260 +and \cmdopt{filterdiff}{--hunks} options, to select exactly the file 10.261 +and hunk you want to extract. 10.262 + 10.263 +Once you have this hunk, you can concatenate it onto the end of your 10.264 +destination patch and continue with the remainder of 10.265 +section~\ref{sec:mq:combine}. 10.266 + 10.267 %%% Local Variables: 10.268 %%% mode: latex 10.269 %%% TeX-master: "00book"