hgbook
changeset 24:a752b0fd3c10
Merge.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Sun Jul 09 21:47:15 2006 -0700 (2006-07-09) |
parents | 9457add294b8 2888fe6176b3 |
children | 9d5b6d303ef5 |
files | en/Makefile en/examples/run-example |
line diff
1.1 --- a/.hgignore Sun Jul 09 21:47:02 2006 -0700 1.2 +++ b/.hgignore Sun Jul 09 21:47:15 2006 -0700 1.3 @@ -15,6 +15,7 @@ 1.4 *.ind 1.5 *.lg 1.6 *.lo[fgt] 1.7 +*.orig 1.8 *.out 1.9 *.pdf 1.10 *.png
2.1 --- a/en/99defs.tex Sun Jul 09 21:47:02 2006 -0700 2.2 +++ b/en/99defs.tex Sun Jul 09 21:47:15 2006 -0700 2.3 @@ -6,8 +6,10 @@ 2.4 \newcommand{\hgext}[1]{\index{\texttt{#1} extension}\texttt{#1}} 2.5 \newcommand{\hgcmd}[1]{\index{\texttt{#1} command}``\texttt{hg #1}''} 2.6 \newcommand{\command}[1]{\index{\texttt{#1} command}\texttt{#1}} 2.7 +\newcommand{\cmdargs}[2]{\index{\texttt{#1} command}\texttt{#1 #2}} 2.8 \newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''} 2.9 \newcommand{\hgopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}} 2.10 +\newcommand{\cmdopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}} 2.11 \newcommand{\package}[1]{\index{\texttt{#1} package}\texttt{#1}} 2.12 2.13 \newsavebox{\notebox}
3.1 --- a/en/Makefile Sun Jul 09 21:47:02 2006 -0700 3.2 +++ b/en/Makefile Sun Jul 09 21:47:15 2006 -0700 3.3 @@ -16,6 +16,9 @@ 3.4 example-sources := \ 3.5 examples/run-example \ 3.6 examples/mq.qinit-help \ 3.7 + examples/mq.diff \ 3.8 + examples/mq.tarball \ 3.9 + examples/mq.tools \ 3.10 examples/mq.tutorial 3.11 3.12 latex-options = \
4.1 Binary file en/examples/data/netplug-1.2.5.tar.bz2 has changed
5.1 Binary file en/examples/data/netplug-1.2.8.tar.bz2 has changed
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/en/examples/data/remove-redundant-null-checks.patch Sun Jul 09 21:47:15 2006 -0700 6.3 @@ -0,0 +1,190 @@ 6.4 + 6.5 +From: Jesper Juhl <jesper.juhl@gmail.com> 6.6 + 6.7 +Remove redundant NULL chck before kfree + tiny CodingStyle cleanup for 6.8 +drivers/ 6.9 + 6.10 +Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com> 6.11 +Signed-off-by: Andrew Morton <akpm@osdl.org> 6.12 +--- 6.13 + 6.14 + drivers/char/agp/sgi-agp.c | 5 ++--- 6.15 + drivers/char/hvcs.c | 11 +++++------ 6.16 + drivers/message/fusion/mptfc.c | 6 ++---- 6.17 + drivers/message/fusion/mptsas.c | 3 +-- 6.18 + drivers/net/fs_enet/fs_enet-mii.c | 3 +-- 6.19 + drivers/net/wireless/ipw2200.c | 22 ++++++---------------- 6.20 + drivers/scsi/libata-scsi.c | 4 +--- 6.21 + drivers/video/au1100fb.c | 3 +-- 6.22 + 8 files changed, 19 insertions(+), 38 deletions(-) 6.23 + 6.24 +diff -puN drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/agp/sgi-agp.c 6.25 +--- a/drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers 6.26 ++++ a/drivers/char/agp/sgi-agp.c 6.27 +@@ -329,9 +329,8 @@ static int __devinit agp_sgi_init(void) 6.28 + 6.29 + static void __devexit agp_sgi_cleanup(void) 6.30 + { 6.31 +- if (sgi_tioca_agp_bridges) 6.32 +- kfree(sgi_tioca_agp_bridges); 6.33 +- sgi_tioca_agp_bridges=NULL; 6.34 ++ kfree(sgi_tioca_agp_bridges); 6.35 ++ sgi_tioca_agp_bridges = NULL; 6.36 + } 6.37 + 6.38 + module_init(agp_sgi_init); 6.39 +diff -puN drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/hvcs.c 6.40 +--- a/drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers 6.41 ++++ a/drivers/char/hvcs.c 6.42 +@@ -1320,11 +1320,12 @@ static struct tty_operations hvcs_ops = 6.43 + static int hvcs_alloc_index_list(int n) 6.44 + { 6.45 + int i; 6.46 ++ 6.47 + hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL); 6.48 + if (!hvcs_index_list) 6.49 + return -ENOMEM; 6.50 + hvcs_index_count = n; 6.51 +- for(i = 0; i < hvcs_index_count; i++) 6.52 ++ for (i = 0; i < hvcs_index_count; i++) 6.53 + hvcs_index_list[i] = -1; 6.54 + return 0; 6.55 + } 6.56 +@@ -1332,11 +1333,9 @@ static int hvcs_alloc_index_list(int n) 6.57 + static void hvcs_free_index_list(void) 6.58 + { 6.59 + /* Paranoia check to be thorough. */ 6.60 +- if (hvcs_index_list) { 6.61 +- kfree(hvcs_index_list); 6.62 +- hvcs_index_list = NULL; 6.63 +- hvcs_index_count = 0; 6.64 +- } 6.65 ++ kfree(hvcs_index_list); 6.66 ++ hvcs_index_list = NULL; 6.67 ++ hvcs_index_count = 0; 6.68 + } 6.69 + 6.70 + static int __init hvcs_module_init(void) 6.71 +diff -puN drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptfc.c 6.72 +--- a/drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers 6.73 ++++ a/drivers/message/fusion/mptfc.c 6.74 +@@ -305,10 +305,8 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in 6.75 + } 6.76 + 6.77 + out: 6.78 +- if (pp0_array) 6.79 +- kfree(pp0_array); 6.80 +- if (p0_array) 6.81 +- kfree(p0_array); 6.82 ++ kfree(pp0_array); 6.83 ++ kfree(p0_array); 6.84 + return rc; 6.85 + } 6.86 + 6.87 +diff -puN drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptsas.c 6.88 +--- a/drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers 6.89 ++++ a/drivers/message/fusion/mptsas.c 6.90 +@@ -1378,8 +1378,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) 6.91 + return 0; 6.92 + 6.93 + out_free_port_info: 6.94 +- if (hba) 6.95 +- kfree(hba); 6.96 ++ kfree(hba); 6.97 + out: 6.98 + return error; 6.99 + } 6.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 6.101 +--- a/drivers/net/fs_enet/fs_enet-mii.c~remove-redundant-null-checks-before-free-in-drivers 6.102 ++++ a/drivers/net/fs_enet/fs_enet-mii.c 6.103 +@@ -431,8 +431,7 @@ static struct fs_enet_mii_bus *create_bu 6.104 + return bus; 6.105 + 6.106 + err: 6.107 +- if (bus) 6.108 +- kfree(bus); 6.109 ++ kfree(bus); 6.110 + return ERR_PTR(ret); 6.111 + } 6.112 + 6.113 +diff -puN drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers drivers/net/wireless/ipw2200.c 6.114 +--- a/drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers 6.115 ++++ a/drivers/net/wireless/ipw2200.c 6.116 +@@ -1229,12 +1229,6 @@ static struct ipw_fw_error *ipw_alloc_er 6.117 + return error; 6.118 + } 6.119 + 6.120 +-static void ipw_free_error_log(struct ipw_fw_error *error) 6.121 +-{ 6.122 +- if (error) 6.123 +- kfree(error); 6.124 +-} 6.125 +- 6.126 + static ssize_t show_event_log(struct device *d, 6.127 + struct device_attribute *attr, char *buf) 6.128 + { 6.129 +@@ -1296,10 +1290,9 @@ static ssize_t clear_error(struct device 6.130 + const char *buf, size_t count) 6.131 + { 6.132 + struct ipw_priv *priv = dev_get_drvdata(d); 6.133 +- if (priv->error) { 6.134 +- ipw_free_error_log(priv->error); 6.135 +- priv->error = NULL; 6.136 +- } 6.137 ++ 6.138 ++ kfree(priv->error); 6.139 ++ priv->error = NULL; 6.140 + return count; 6.141 + } 6.142 + 6.143 +@@ -1970,8 +1963,7 @@ static void ipw_irq_tasklet(struct ipw_p 6.144 + struct ipw_fw_error *error = 6.145 + ipw_alloc_error_log(priv); 6.146 + ipw_dump_error_log(priv, error); 6.147 +- if (error) 6.148 +- ipw_free_error_log(error); 6.149 ++ kfree(error); 6.150 + } 6.151 + #endif 6.152 + } else { 6.153 +@@ -11693,10 +11685,8 @@ static void ipw_pci_remove(struct pci_de 6.154 + } 6.155 + } 6.156 + 6.157 +- if (priv->error) { 6.158 +- ipw_free_error_log(priv->error); 6.159 +- priv->error = NULL; 6.160 +- } 6.161 ++ kfree(priv->error); 6.162 ++ priv->error = NULL; 6.163 + 6.164 + #ifdef CONFIG_IPW2200_PROMISCUOUS 6.165 + ipw_prom_free(priv); 6.166 +diff -puN drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers drivers/scsi/libata-scsi.c 6.167 +--- a/drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers 6.168 ++++ a/drivers/scsi/libata-scsi.c 6.169 +@@ -222,9 +222,7 @@ int ata_cmd_ioctl(struct scsi_device *sc 6.170 + && copy_to_user(arg + sizeof(args), argbuf, argsize)) 6.171 + rc = -EFAULT; 6.172 + error: 6.173 +- if (argbuf) 6.174 +- kfree(argbuf); 6.175 +- 6.176 ++ kfree(argbuf); 6.177 + return rc; 6.178 + } 6.179 + 6.180 +diff -puN drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers drivers/video/au1100fb.c 6.181 +--- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers 6.182 ++++ a/drivers/video/au1100fb.c 6.183 +@@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void) 6.184 + { 6.185 + driver_unregister(&au1100fb_driver); 6.186 + 6.187 +- if (drv_info.opt_mode) 6.188 +- kfree(drv_info.opt_mode); 6.189 ++ kfree(drv_info.opt_mode); 6.190 + } 6.191 + 6.192 + module_init(au1100fb_init); 6.193 +_
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/en/examples/mq.diff Sun Jul 09 21:47:15 2006 -0700 7.3 @@ -0,0 +1,12 @@ 7.4 +#$ name: diff 7.5 + 7.6 +echo 'this is my first line' > oldfile 7.7 +echo 'my first line is here' > newfile 7.8 + 7.9 +diff -u oldfile newfile > tiny.patch 7.10 + 7.11 +cat tiny.patch 7.12 + 7.13 +patch < tiny.patch 7.14 + 7.15 +cat newfile
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/en/examples/mq.tarball Sun Jul 09 21:47:15 2006 -0700 8.3 @@ -0,0 +1,48 @@ 8.4 +cp $EXAMPLE_DIR/data/netplug-*.tar.bz2 . 8.5 +ln -s /bin/true download 8.6 + 8.7 +#$ name: download 8.8 + 8.9 +download netplug-1.2.5.tar.bz2 8.10 +tar jxf netplug-1.2.5.tar.bz2 8.11 +cd netplug-1.2.5 8.12 +hg init 8.13 +hg commit -q --addremove --message netplug-1.2.5 8.14 +cd .. 8.15 +hg clone netplug-1.2.5 netplug 8.16 + 8.17 +#$ name: 8.18 + 8.19 +cd netplug 8.20 +echo '[extensions]' >> $HGRC 8.21 +echo 'hgext.mq =' >> $HGRC 8.22 +cd .. 8.23 + 8.24 +#$ name: qinit 8.25 + 8.26 +cd netplug 8.27 +hg qinit 8.28 +hg qnew -m 'fix build problem with gcc 4' build-fix.patch 8.29 +perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c 8.30 +hg qrefresh 8.31 +hg tip -p 8.32 + 8.33 +#$ name: newsource 8.34 + 8.35 +hg qpop -a 8.36 +cd .. 8.37 +download netplug-1.2.8.tar.bz2 8.38 +hg clone netplug-1.2.5 netplug-1.2.8 8.39 +cd netplug-1.2.8 8.40 +hg locate -0 | xargs -0 rm 8.41 +cd .. 8.42 +tar jxf netplug-1.2.8.tar.bz2 8.43 +cd netplug-1.2.8 8.44 +hg commit --addremove --message netplug-1.2.8 8.45 + 8.46 +#$ name: repush 8.47 + 8.48 +cd ../netplug 8.49 +hg pull ../netplug-1.2.8 8.50 +hg qpush -a 8.51 +
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/en/examples/mq.tools Sun Jul 09 21:47:15 2006 -0700 9.3 @@ -0,0 +1,9 @@ 9.4 +cp $EXAMPLE_DIR/data/remove-redundant-null-checks.patch . 9.5 + 9.6 +#$ name: tools 9.7 +diffstat -p1 remove-redundant-null-checks.patch 9.8 + 9.9 +filterdiff -i '*/video/*' remove-redundant-null-checks.patch 9.10 + 9.11 +#$ name: lsdiff 9.12 +lsdiff -nvv remove-redundant-null-checks.patch
10.1 --- a/en/examples/run-example Sun Jul 09 21:47:02 2006 -0700 10.2 +++ b/en/examples/run-example Sun Jul 09 21:47:15 2006 -0700 10.3 @@ -76,6 +76,7 @@ 10.4 rcfp = open(rcfile, 'w') 10.5 print >> rcfp, 'PS1="%s"' % self.prompt 10.6 print >> rcfp, 'unset HISTFILE' 10.7 + print >> rcfp, 'export EXAMPLE_DIR="%s"' % os.getcwd() 10.8 print >> rcfp, 'export LANG=C' 10.9 print >> rcfp, 'export LC_ALL=C' 10.10 print >> rcfp, 'export TZ=GMT' 10.11 @@ -118,7 +119,7 @@ 10.12 if nl: hunk += '\n' 10.13 ofp.write(hunk) 10.14 # then its output 10.15 - ofp.write(output) 10.16 + ofp.write(tex_escape(output)) 10.17 self.status('\n') 10.18 finally: 10.19 try: 10.20 @@ -141,7 +142,9 @@ 10.21 for name in os.listdir(path): 10.22 if name == 'run-example' or name.startswith('.'): continue 10.23 if name.endswith('.out') or name.endswith('~'): continue 10.24 - example(os.path.join(path, name)).run() 10.25 + pathname = os.path.join(path, name) 10.26 + if os.path.isfile(pathname): 10.27 + example(pathname).run() 10.28 print >> open(os.path.join(path, '.run'), 'w'), time.asctime() 10.29 10.30 if __name__ == '__main__':
11.1 --- a/en/mq.tex Sun Jul 09 21:47:02 2006 -0700 11.2 +++ b/en/mq.tex Sun Jul 09 21:47:15 2006 -0700 11.3 @@ -126,6 +126,62 @@ 11.4 Because quilt does not care about revision control tools, it is still 11.5 a tremendously useful piece of software to know about for situations 11.6 where you cannot use Mercurial and MQ. 11.7 + 11.8 +\section{Understanding patches} 11.9 + 11.10 +Because MQ doesn't hide its patch-oriented nature, it is helpful to 11.11 +understand what patches are, and a little about the tools that work 11.12 +with them. 11.13 + 11.14 +The traditional Unix \command{diff} command compares two files, and 11.15 +prints a list of differences between them. The \command{patch} command 11.16 +understands these differences as \emph{modifications} to make to a 11.17 +file. Take a look at figure~\ref{ex:mq:diff} for a simple example of 11.18 +these commands in action. 11.19 + 11.20 +\begin{figure}[ht] 11.21 + \interaction{mq.diff.diff} 11.22 + \caption{Simple uses of the \command{diff} and \command{patch} commands} 11.23 + \label{ex:mq:diff} 11.24 +\end{figure} 11.25 + 11.26 +The type of file that \command{diff} generates (and \command{patch} 11.27 +takes as input) is called a ``patch'' or a ``diff''; there is no 11.28 +difference between a patch and a diff. (We'll use the term ``patch'', 11.29 +since it's more commonly used.) 11.30 + 11.31 +A patch file can start with arbitrary text; the \command{patch} 11.32 +command ignores this text, but MQ uses it as the commit message when 11.33 +creating changesets. To find the beginning of the patch content, 11.34 +\command{patch} searches for the first line that starts with the 11.35 +string ``\texttt{diff~-}''. 11.36 + 11.37 +MQ works with \emph{unified} diffs (\command{patch} can accept several 11.38 +other diff formats, but MQ doesn't). A unified diff contains two 11.39 +kinds of header. The \emph{file header} describes the file being 11.40 +modified; it contains the name of the file to modify. When 11.41 +\command{patch} sees a new file header, it looks for a file with that 11.42 +name to start modifying. 11.43 + 11.44 +After the file header comes a series of \emph{hunks}. Each hunk 11.45 +starts with a header; this identifies the range of line numbers within 11.46 +the file that the hunk should modify. Following the header, a hunk 11.47 +starts and ends with a few (usually three) lines of text from the 11.48 +unmodified file; these are called the \emph{context} for the hunk. If 11.49 +there's only a small amount of context between successive hunks, 11.50 +\command{diff} doesn't print a new hunk header; it just runs the hunks 11.51 +together, with a few lines of context between modifications. 11.52 + 11.53 +Each line of context begins with a space character. Within the hunk, 11.54 +a line that begins with ``\texttt{-}'' means ``remove this line,'' 11.55 +while a line that begins with ``\texttt{+}'' means ``insert this 11.56 +line.'' For example, a line that is modified is represented by one 11.57 +deletion and one insertion. 11.58 + 11.59 +We will return to ome of the more subtle aspects of patches later (in 11.60 +section~\ref{ex:mq:adv-patch}), but you should have enough information 11.61 +now to use MQ. 11.62 + 11.63 \section{Getting started with Mercurial Queues} 11.64 \label{sec:mq:start} 11.65 11.66 @@ -200,6 +256,7 @@ 11.67 working directory as you usually would. All of the normal Mercurial 11.68 commands, such as \hgcmd{diff} and \hgcmd{annotate}, work exactly as 11.69 they did before. 11.70 + 11.71 \subsection{Refreshing a patch} 11.72 11.73 When you reach a point where you want to save your work, use the 11.74 @@ -319,45 +376,12 @@ 11.75 \hgcmd{qrefresh} the core patch, and \hgcmd{qpush} back to the UI 11.76 patch to continue where you left off. 11.77 11.78 -\section{Mercurial Queues and GNU patch} 11.79 -\label{sec:mq:patch} 11.80 - 11.81 -MQ uses the GNU \command{patch} command to apply patches. Because MQ 11.82 -doesn't hide its patch-oriented nature, it is helpful to understand 11.83 -the data that MQ and \command{patch} work with, and a few aspects of 11.84 -how \command{patch} operates. 11.85 - 11.86 -The \command{diff} command generates a list of modifications by 11.87 -comparing two files. The \command{patch} command applies a list of 11.88 -modifications to a file. The kinds of files that \command{diff} and 11.89 -\command{patch} work with are referred to as both ``diffs'' and 11.90 -``patches;'' there is no difference between a diff and a patch. 11.91 - 11.92 -A patch file can start with arbitrary text; MQ uses this text as the 11.93 -commit message when creating changesets. It treats the first line 11.94 -that starts with the string ``\texttt{diff~-}'' as the separator 11.95 -between header and content. 11.96 - 11.97 -MQ works with \emph{unified} diffs (\command{patch} can accept several 11.98 -other diff formats, but MQ doesn't). A unified diff contains two 11.99 -kinds of header. The \emph{file header} describes the file being 11.100 -modified; it contains the name of the file to modify. When 11.101 -\command{patch} sees a new file header, it looks for a file with that 11.102 -name to start modifying. 11.103 - 11.104 -After the file header comes a series of \emph{hunks}. Each hunk 11.105 -starts with a header; this identifies the range of line numbers within 11.106 -the file that the hunk should modify. Following the header, a hunk 11.107 -starts and ends with a few (usually three) lines of text from the 11.108 -unmodified file; these are called the \emph{context} for the hunk. 11.109 -Each unmodified line begins with a space characters. Within the hunk, 11.110 -a line that begins with ``\texttt{-}'' means ``remove this line,'' 11.111 -while a line that begins with ``\texttt{+}'' means ``insert this 11.112 -line.'' For example, a line that is modified is represented by one 11.113 -deletion and one insertion. 11.114 - 11.115 -The \command{diff} command runs hunks together when there's not enough 11.116 -context between modifications to justify 11.117 +\section{More about patches} 11.118 +\label{sec:mq:adv-patch} 11.119 + 11.120 +MQ uses the GNU \command{patch} command to apply patches, so it's 11.121 +helpful to know about a few more detailed aspects of how 11.122 +\command{patch} works. 11.123 11.124 When \command{patch} applies a hunk, it tries a handful of 11.125 successively less accurate strategies to try to make the hunk apply. 11.126 @@ -622,6 +646,7 @@ 11.127 confuse MQ's idea of which patches are applied. 11.128 11.129 \section{Commands for working with patches} 11.130 +\label{sec:mq:tools} 11.131 11.132 Once you've been working with patches for a while, you'll find 11.133 yourself hungry for tools that will help you to understand and 11.134 @@ -636,6 +661,12 @@ 11.135 do clever things with prefixes of file names that inevitably confuse 11.136 at least me.) 11.137 11.138 +\begin{figure}[ht] 11.139 + \interaction{mq.tools.tools} 11.140 + \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands} 11.141 + \label{ex:mq:tools} 11.142 +\end{figure} 11.143 + 11.144 The \package{patchutils} package~\cite{web:patchutils} is invaluable. 11.145 It provides a set of small utilities that follow the ``Unix 11.146 philosophy;'' each does one useful thing with a patch. The 11.147 @@ -645,6 +676,122 @@ 11.148 invocation of \command{filterdiff} can generate a smaller patch that 11.149 only touches files whose names match a particular glob pattern. 11.150 11.151 +\section{Good ways to work with patches} 11.152 + 11.153 +Whether you are working on a patch series to submit to a free software 11.154 +or open source project, or a series that you intend to treat as a 11.155 +sequence of regular changesets when you're done, you can use some 11.156 +simple techniques to keep your work well organised. 11.157 + 11.158 +Give your patches descriptive names. A good name for a patch might be 11.159 +\filename{rework-device-alloc.patch}, because it will immediately give 11.160 +you a hint what the purpose of the patch is. Long names shouldn't be 11.161 +a problem; you won't be typing the names often, but you \emph{will} be 11.162 +running commands like \hgcmd{qapplied} and \hgcmd{qtop} over and over. 11.163 +Good naming becomes especially important when you have a number of 11.164 +patches to work with, or if you are juggling a number of different 11.165 +tasks and your patches only get a fraction of your attention. 11.166 + 11.167 +Be aware of what patch you're working on. Use the \hgcmd{qtop} 11.168 +command and skim over the text of your patches frequently---for 11.169 +example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where 11.170 +you stand. I have several times worked on and \hgcmd{qrefresh}ed a 11.171 +patch other than the one I intended, and it's often tricky to migrate 11.172 +changes into the right patch after making them in the wrong one. 11.173 + 11.174 +For this reason, it is very much worth investing a little time to 11.175 +learn how to use some of the third-party tools I described in 11.176 +section~\ref{sec:mq:tools}, particularly \command{diffstat} and 11.177 +\command{filterdiff}. The former will give you a quick idea of what 11.178 +changes your patch is making, while the latter makes it easy to splice 11.179 +hunks selectively out of one patch and into another. 11.180 + 11.181 +\section{MQ cookbook} 11.182 + 11.183 +\subsection{Manage ``trivial'' patches} 11.184 + 11.185 +Because the overhead of dropping files into a new Mercurial repository 11.186 +is so low, it makes a lot of sense to manage patches this way even if 11.187 +you simply want to make a few changes to a source tarball that you 11.188 +downloaded. 11.189 + 11.190 +Begin by downloading and unpacking the source tarball, 11.191 +and turning it into a Mercurial repository. 11.192 +\interaction{mq.tarball.download} 11.193 + 11.194 +Continue by creating a patch stack and making your changes. 11.195 +\interaction{mq.tarball.qinit} 11.196 + 11.197 +Let's say a few weeks or months pass, and your package author releases 11.198 +a new version. First, bring their changes into the repository. 11.199 +\interaction{mq.tarball.newsource} 11.200 +The pipeline starting with \hgcmd{locate} above deletes all files in 11.201 +the working directory, so that \hgcmd{commit}'s 11.202 +\hgopt{commit}{--addremove} option can actually tell which files have 11.203 +really been removed in the newer version of the source. 11.204 + 11.205 +Finally, you can apply your patches on top of the new tree. 11.206 +\interaction{mq.tarball.repush} 11.207 + 11.208 +\subsection{Combining entire patches} 11.209 +\label{sec:mq:combine} 11.210 + 11.211 +It's easy to combine entire patches. 11.212 + 11.213 +\begin{enumerate} 11.214 +\item \hgcmd{qpop} your applied patches until neither patch is 11.215 + applied. 11.216 +\item Concatenate the patches that you want to combine together: 11.217 + \begin{codesample4} 11.218 + cat patch-to-drop.patch >> patch-to-augment.patch 11.219 + \end{codesample4} 11.220 + The description from the first patch (if you have one) will be used 11.221 + as the commit comment when you \hgcmd{qpush} the combined patch. 11.222 + Edit the patch description if you need to. 11.223 +\item Use the \hgcmd{qdel} command to delete the patch you're dropping 11.224 + from the \sfilename{series} file. 11.225 +\item \hgcmd{qpush} the combined patch. Fix up any rejects. 11.226 +\item \hgcmd{qrefresh} the combined patch to tidy it up. 11.227 +\end{enumerate} 11.228 + 11.229 +\subsection{Merging part of one patch into another} 11.230 + 11.231 +Merging \emph{part} of one patch into another is more difficult than 11.232 +combining entire patches. 11.233 + 11.234 +If you want to move changes to entire files, you can use 11.235 +\command{filterdiff}'s \cmdopt{filterdiff}{-i} and 11.236 +\cmdopt{filterdiff}{-x} options to choose the modifications to snip 11.237 +out of one patch, concatenating its output onto the end of the patch 11.238 +you want to merge into. You usually won't need to modify the patch 11.239 +you've merged the changes from. Instead, MQ will report some rejected 11.240 +hunks when you \hgcmd{qpush} it (from the hunks you moved into the 11.241 +other patch), and you can simply \hgcmd{qrefresh} the patch to drop 11.242 +the duplicate hunks. 11.243 + 11.244 +If you have a patch that has multiple hunks modifying a file, and you 11.245 +only want to move a few of those hunks, the job becomes more messy, 11.246 +but you can still partly automate it. Use \cmdargs{lsdiff}{-nvv} to 11.247 +print some metadata about the patch. 11.248 +\interaction{mq.tools.lsdiff} 11.249 + 11.250 +This command prints three different kinds of number: 11.251 +\begin{itemize} 11.252 +\item a \emph{file number} to identify each file modified in the patch; 11.253 +\item the line number within a modified file that a hunk starts at; and 11.254 +\item a \emph{hunk number} to identify that hunk. 11.255 +\end{itemize} 11.256 + 11.257 +You'll have to use some visual inspection, and reading of the patch, 11.258 +to identify the file and hunk numbers you'll want, but you can then 11.259 +pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files} 11.260 +and \cmdopt{filterdiff}{--hunks} options, to select exactly the file 11.261 +and hunk you want to extract. 11.262 + 11.263 +Once you have this hunk, you can concatenate it onto the end of your 11.264 +destination patch and continue with the remainder of 11.265 +section~\ref{sec:mq:combine}. 11.266 + 11.267 %%% Local Variables: 11.268 %%% mode: latex 11.269 %%% TeX-master: "00book"