rev |
line source |
igor@440
|
1 \chapter{Administración de cambios con Colas de Mercurial}
|
jerojasro@336
|
2 \label{chap:mq}
|
jerojasro@336
|
3
|
igor@440
|
4 \section{El problema de la administración de parches}
|
jerojasro@336
|
5 \label{sec:mq:patch-mgmt}
|
jerojasro@336
|
6
|
igor@443
|
7 Un escenario frecuente: usted necesita instalar un paquete de software
|
igor@443
|
8 desde las fuentes, pero encuentra un fallo que debe arreglar antes de
|
igor@443
|
9 poder comenzar a usarlo. Hace sus cambios, y se olvida del paquete
|
igor@443
|
10 por un tiempo, unos meses después necesita actualizar a una nueva
|
igor@443
|
11 versión del paquete. Si la nueva versión del paquete todavía tiene el
|
igor@443
|
12 fallo, debe extraer su arreglo del árbol de fuentes anteriores y
|
igor@443
|
13 aplicarlo a la nueva versión. Una tarea tediosa en la cual es fácil
|
igor@443
|
14 equivocarse.
|
igor@443
|
15
|
igor@443
|
16 Este es un caso simple del problema del ``manejo de parches''. Usted
|
igor@443
|
17 tiene un árbol de fuentes del ``mantenedor principal'' que no puede
|
igor@443
|
18 cambiar: necesita hacer algunos cambios locales sobre el árbol
|
igor@443
|
19 principal; y desearía poder mantener tales cambios separados, de forma
|
igor@443
|
20 tal que pueda aplicarlos a versiones más nuevas del árbol principal.
|
igor@443
|
21
|
igor@443
|
22 El problema de administración de parches surge en muchas situaciones.
|
igor@443
|
23 Probablemente la más visible es cuando un usuario de un proyecto de
|
igor@443
|
24 software de fuentes abiertas contribuye con un arreglo de un fallo o
|
igor@443
|
25 una nueva característica a los mantenedores del proyecto en la forma
|
igor@443
|
26 de un parche.
|
igor@443
|
27
|
igor@443
|
28 Aquellos que distribuyen sistemas operativos que incluyen programas
|
igor@443
|
29 abiertos usualmente requieren hacer cambios en los paquetes que
|
igor@443
|
30 distribuyen de tal forma que se armen apropiadamente en sus ambientes.
|
igor@443
|
31
|
igor@443
|
32 Cuando hay pocos cambios por mantener, es muy sencillo administrar un
|
igor@443
|
33 solo parche con los programas estándar \command{diff} y
|
igor@443
|
34 \command{patch}( ver la sección~\ref{sec:mq:patch} para ver cómo
|
igor@443
|
35 emplear tales herramientas). Cuando la cantidad de cambios comienza a
|
igor@443
|
36 crecer, tiene sentido mantener parches como ``porciones de trabajo''
|
igor@443
|
37 individual, de forma que cada cambio contiene solamente un arreglo de
|
igor@443
|
38 un fallo(el parche puede modificar varios archivos, pero está
|
igor@443
|
39 ``haciendo una sola cosa''), y puede tener cierta cantidad de tales
|
igor@443
|
40 parches para diferentes fallos y cambios locales. En esta situación,
|
igor@443
|
41 si envía un parche que arregla un fallo a los mantenedores principales
|
igor@443
|
42 de un paquete y ellos incluyen su arreglo en una publicación
|
igor@443
|
43 posterior, puede deshacerse de tal parche cuando se actualice a la
|
igor@443
|
44 nueva versión.
|
igor@443
|
45
|
igor@443
|
46 Mantener un solo parche frente a un árbol principal es algo tedioso y
|
igor@443
|
47 es fácil equivocarse, pero no es difícil. Aunque, la complejidad del
|
igor@443
|
48 problema crece rápidamente a medida que la cantidad de parches que
|
igor@443
|
49 tiene que mantener crece. Con más que una pequeña cantidad de
|
igor@443
|
50 cambios, entender cuáles ha aplicado se convierte de algo desordenado
|
igor@443
|
51 a algo avasallante.
|
igor@443
|
52
|
igor@443
|
53 Afortunadamente Mercurial provee una extensión poderos: Colas de
|
igor@443
|
54 Mercurial( o simplemente ``MQ''), que simplifica en gran medida el
|
igor@443
|
55 problema de administración de parches.
|
igor@443
|
56
|
igor@443
|
57 \section{La prehistoria de las Colas de Mercurial}
|
jerojasro@336
|
58 \label{sec:mq:history}
|
jerojasro@336
|
59
|
igor@443
|
60 A finales de los 90s, muchos desarrolladores del núcleo de Linux
|
igor@443
|
61 comenzaron a mantener ``series de parches'' que modificaron el
|
igor@443
|
62 comportamiento del núcleo de Linux. Algunos se enfocaban en
|
igor@443
|
63 estabilidad, otros en aumentar las características, y otros un poco
|
igor@443
|
64 más especulativos.
|
igor@443
|
65
|
igor@443
|
66 Los tamaños de las series de parches crecieron rápidamente. En el
|
igor@443
|
67 2002, Andrew Morton publicó algunos guiones de línea de órdenes que
|
igor@443
|
68 estuvo usando para automatizar la tarea de administrar su cola de
|
igor@443
|
69 parches. Andrew usó exitósamente tales guiones para administrar
|
igor@443
|
70 centenas( aveces millares) de parches en el núcleo de Linux.
|
igor@443
|
71
|
igor@443
|
72 \subsection{Trabajar parches con quilt}
|
jerojasro@336
|
73 \label{sec:mq:quilt}
|
jerojasro@336
|
74
|
igor@443
|
75 A comienzos del 2003, Andreas Gruenbacher y Martin Quinson tomaron la
|
igor@443
|
76 aproximación de los guiones de Andrew y publicaron una herramienta
|
igor@443
|
77 llamada
|
igor@443
|
78 ``patchwork quilt''~\cite{web:quilt}, o simplemente ``quilt''
|
igor@443
|
79 (ver~\cite{gruenbacher:2005} el paper que lo describe). Dado que
|
igor@443
|
80 quilt automatizaba sustancialmente la administración de parches, fue
|
igor@443
|
81 adoptado en gran medida por desarrolladores de programas abiertos.
|
igor@443
|
82
|
igor@443
|
83 Quilt maneja una \emph{pila de parches} sobre un árbol de directorios.
|
igor@443
|
84 Para comenzar, usted le indica a quilt que administre un árbol de
|
igor@443
|
85 directorios, le indica qué archivos manejar; Este almacena los nombres
|
igor@443
|
86 y los contenidos de estos archivos. Para arreglar un fallo, usted
|
igor@443
|
87 crea un nuevo parche(con una sola orden), edita los archivos que está
|
igor@443
|
88 arreglando y ``refresca'' el parche.
|
igor@443
|
89
|
igor@443
|
90 El paso de refresco hace que quilt revise el árbol de directorios;
|
igor@443
|
91 actualiza el parche con todos los cambios que usted haya hecho. Puede
|
igor@443
|
92 crear otro parche sobre el primero, que hará seguimiento de los
|
igor@443
|
93 cambios requeridos para modificar el árbol desde ``el árbol con un
|
igor@443
|
94 parch aplicado'' a un ``árbol con dos parches aplicados''.
|
igor@443
|
95
|
igor@443
|
96 Usted puede \emph{elegir} qué cambios desea aplicar al árbol. Si
|
igor@443
|
97 ``pop''\ndt{saca} un parche, los cambios hechos por tal parchve
|
igor@443
|
98 desapareceŕan del árbol de directorios. Quilt recuerda qué parches ha
|
igor@443
|
99 sacado, para que pueda ``introducirlos''\ndt{push} posteriormente, así el
|
igor@443
|
100 árbol de directorios se restaurará con las modificaciones que vienen
|
igor@443
|
101 del parche. Lo más importante es que puede ejecutar la orden
|
igor@443
|
102 ``refresh'' en cualquier momento, y el último parche será
|
igor@443
|
103 actualizado. Esto significa que puede, en cualquier momento, cambiar
|
igor@443
|
104 qué parches serán aplicados y qué modificaciones hacen ellos.
|
igor@443
|
105
|
igor@443
|
106 Quilt no tiene nada que ver con herramientas de control de versiones,
|
igor@443
|
107 y puede trabajar bien sobre un conjunto de fuentes que viene de un
|
igor@443
|
108 archivo comprimido y empaquetado o una copia de trabajo de Subversion.
|
igor@443
|
109
|
igor@443
|
110 \subsection{Pasar de trabajo con parches con Quilt hacia Colas de Mercurial}
|
jerojasro@336
|
111 \label{sec:mq:quilt-mq}
|
jerojasro@336
|
112
|
igor@443
|
113 A mediados de 2005, Chris Mason tomó las características de quilt y
|
igor@443
|
114 escribió una extensión que llamó Colas de Mercurial\ndt{Mercurial
|
igor@443
|
115 Queues}, que proporcionó un comportamiento a Mercurial al estilo
|
igor@443
|
116 quilt.
|
igor@443
|
117
|
igor@443
|
118 La diferencia clave entre quilt y MQ es que quilt no sabe nada acerca
|
igor@443
|
119 del sistema de control de revisiones, mientras que MQ está
|
igor@443
|
120 \emph{integrado} con Mercurial. Cada parche que usted introduce se
|
igor@443
|
121 representa como un conjunto de cambios en Mercurial. Si sustrae un
|
igor@443
|
122 parche, el conjunto de cambios desaparece.\ndt{introduce originalmente es
|
igor@443
|
123 push y pop es sustraer en este contexto, usaremos el original en inglés
|
igor@443
|
124 cuando encontremos que facilita la comprensión}
|
igor@443
|
125
|
igor@443
|
126 Dado que quilt no se preocupa por las herramientas de control de
|
igor@443
|
127 revisiones, continúa siendo una porción de software tremendamente útil
|
igor@443
|
128 para aquellas situaciones en las cuales no puede usar Mercurial y MQ.
|
igor@443
|
129
|
igor@443
|
130 \section{La gran ventaja de MQ}
|
igor@443
|
131
|
igor@443
|
132 No puedo sobreestimar el valor que MQ ofrece en la unificación de
|
igor@443
|
133 parches y el control de revisiones.
|
igor@443
|
134
|
igor@443
|
135 La principal razón por la cual los parches han persistido en el mundo
|
igor@443
|
136 del software libre y de fuentes abiertas--a pesar de la creciente
|
igor@443
|
137 disponibilidad de herramientas poderosas de control de revisiones-- es
|
igor@443
|
138 la \emph{agilidad} que ofrecen.
|
igor@443
|
139
|
igor@443
|
140 Las herramientas tradicionales de control de revisiones llevan un
|
igor@443
|
141 registro permanente e irreversible de todo lo que usted hace. A pesar
|
igor@443
|
142 de que esto tiene gran valor, también es bastante sutil. Si requiere
|
igor@443
|
143 realizar un experimento ((((wild-eyed)))), debe ser cuidadoso en cómo
|
igor@443
|
144 lo hace, o puede dejar trazas innecesarias--o peor aún,
|
igor@443
|
145 desconcertantes o desestabilizantes--- de los pasos y errores en el
|
igor@443
|
146 registro de revisiones de forma permanente.
|
igor@443
|
147
|
igor@443
|
148 En contraste, con la cohesión de MQ con el control de revisiones
|
igor@443
|
149 distribuidos y los parches, resulta más sencillo aislar su trabajo.
|
igor@443
|
150 Sus parches viven encima de la historia de revisiones normales, y
|
igor@443
|
151 puede hacer que ellos desaparezcan o reaparezcan cuando lo desee. Si
|
igor@443
|
152 no le gusta un parche, puede desecharlo. Si un parche no satisface
|
igor@443
|
153 todo lo que usted desea, puede arreglarlo---tantas veces como lo
|
igor@443
|
154 requiera, hasta que lo haya refinado lo suficiente hacia sus
|
igor@443
|
155 expectativas.
|
igor@443
|
156
|
igor@443
|
157 Por ejemplo, la integración de parches con el control de revisiones
|
igor@443
|
158 hace que el entender los parches y revisar sus efectos---y sus
|
igor@443
|
159 interacciones con el código en el cuál están enlazados--- sea
|
igor@443
|
160 \emph{mucho} más sencillo. Dado que todo parche que se aplique tiene
|
igor@443
|
161 un conjunto de cambios asociado, puede usar
|
igor@443
|
162 \hgcmdargs{log}{\emph{filename}} para ver qué conjuntos de cambios y
|
igor@443
|
163 parches afectaron un fichero. Puede usar la orden \hgext{bisect} para
|
igor@443
|
164 hacer una búsqueda binaria sobre todos los conjuntos de cambios y
|
igor@443
|
165 parches aplicados para ver dónde se introdujo un fallo o dónde fue
|
igor@443
|
166 arreglado. Puede usar la orden \hgcmd{annotate} para ver qué
|
igor@443
|
167 conjuntos de cambios o parches modificaron una línea particular de un
|
igor@443
|
168 archivo fuente. Y mucho más.
|
igor@443
|
169
|
igor@443
|
170 \section{Entender los parches}
|
jerojasro@336
|
171 \label{sec:mq:patch}
|
jerojasro@336
|
172
|
igor@443
|
173 Dado que MQ no esconde su naturaleza parche-céntrica, es muy útil para
|
igor@443
|
174 entender de qué se tratan los parches, y un poco acerca de las
|
igor@443
|
175 herramientas que trabajan con ellos.
|
igor@443
|
176
|
igor@443
|
177 La orden de Unix tradicional \command{diff} compara dos ficheros, e
|
igor@443
|
178 imprime una lista de diferencias de sus líneas. La orden
|
igor@443
|
179 \command{patch} entiende esas diferencias como \emph{modificaciones}
|
igor@443
|
180 para construir un fichero. Vea en la figura~\ref{ex:mq:diff} un
|
igor@443
|
181 ejemplo sencillo de tales órdenes en acción.
|
jerojasro@336
|
182
|
jerojasro@336
|
183 \begin{figure}[ht]
|
jerojasro@336
|
184 \interaction{mq.dodiff.diff}
|
igor@443
|
185 \caption{Uso sencillo de las órdenes \command{diff} y \command{patch}}
|
jerojasro@336
|
186 \label{ex:mq:diff}
|
jerojasro@336
|
187 \end{figure}
|
jerojasro@336
|
188
|
igor@443
|
189 El tipo de fichero que \command{diff} genera (y que \command{patch}
|
igor@443
|
190 toma como entrada) se llama un ``parche'' o un ``diff''; no hay
|
igor@443
|
191 diferencia entre un parche y un diff. (Usaremos el término ``parche'',
|
igor@443
|
192 dado que es el que más comunmente se usa.)
|
igor@443
|
193
|
igor@443
|
194 Un parche puede comenzar con un texto arbitrario; la orden \command{patch}
|
igor@443
|
195 ignora este texto, pero MQ lo usa como el mensaje de consignación
|
igor@443
|
196 cuando se crean conjuntos de cambios. Para encontrar el inicio del
|
igor@443
|
197 contenido de un parche, la orden \command{patch} busca la primera
|
igor@443
|
198 línea que comience con la cadena ``\texttt{diff~-}''.
|
igor@443
|
199
|
igor@443
|
200 MQ trabaja con diffs \emph{unificados} (\command{patch} acepta varios
|
igor@443
|
201 formatos de diff adicionales, pero MQ no). Un diff unificado contiene
|
igor@443
|
202 dos clases de encabezados. El \emph{encabezado de fichero} describe
|
igor@443
|
203 el fichero que se está modificando; contiene el nombre del fichero a
|
igor@443
|
204 modificar. Cuando \command{patch} ve un nuevo encabezado de fichero,
|
igor@443
|
205 busca un fichero con ese nombre para modificarlo.
|
igor@443
|
206
|
igor@443
|
207 Después del encabezaado vienen varios \emph{trozos}. Cada trozo
|
igor@443
|
208 comienza con un encabezado; que identifica el rango de líneas del
|
igor@443
|
209 fichero que el trozo debe modificar. Después del encabezado, un trozo
|
igor@443
|
210 comienza y termina con unas pocas líneas(usualmente tres) de texto del
|
igor@443
|
211 fichero que no han sido modificadas; las cuales llamamos el
|
igor@443
|
212 \emph{contexto} del trozo. Si solamente hay una pequeña cantidad de
|
igor@443
|
213 contexto entre trozos sucesivos, \command{diff} no imprime un nuevo
|
igor@443
|
214 encabezado para el trozo, continua integrando los trozos, con unas
|
igor@443
|
215 líneas de contexto entre las modificaciones.
|
igor@443
|
216
|
igor@443
|
217 Cada línea de contexto comienza con un caracter de espacio. En el
|
igor@443
|
218 trozo, si una línea comienza con ``\texttt{-}'' significa ``elimine
|
igor@443
|
219 esta línea'', si la línea comienza con un ``\texttt{+}'' significa
|
igor@443
|
220 ``inserte esta línea''. Por ejemplo, una línea que se modifica se
|
igor@443
|
221 representa con una línea eliminada y una línea insertada.
|
igor@443
|
222
|
igor@443
|
223 Retomaremos aspectos más sutiles acerca de parches posteriormente(en
|
igor@443
|
224 la sección~\ref{sec:mq:adv-patch}), pero en el momento usted ya
|
igor@443
|
225 debería tener suficiente información para usar MQ.
|
igor@443
|
226
|
igor@443
|
227 \section{Comenzar a usar Colas de Mercurial}
|
jerojasro@336
|
228 \label{sec:mq:start}
|
jerojasro@336
|
229
|
igor@443
|
230 Dado que MQ está implementado como una extensión, debe habilitarla
|
igor@443
|
231 explícitamente antes de comenzar a usarla. (No necesita descargar
|
igor@443
|
232 nada; MQ viene con la distribución estándar de Mercurial.) Para
|
igor@443
|
233 habilitar MQ, edite su fichero \tildefile{.hgrc}, y añada las líneas
|
igor@443
|
234 de la figura~\ref{ex:mq:config}.
|
jerojasro@336
|
235
|
jerojasro@336
|
236 \begin{figure}[ht]
|
jerojasro@336
|
237 \begin{codesample4}
|
jerojasro@336
|
238 [extensions]
|
jerojasro@336
|
239 hgext.mq =
|
jerojasro@336
|
240 \end{codesample4}
|
jerojasro@336
|
241 \label{ex:mq:config}
|
igor@443
|
242 \caption{Líneas a añadir en \tildefile{.hgrc} para habilitar la extensión MQ}
|
igor@443
|
243 \end{figure}
|
igor@443
|
244
|
igor@443
|
245 Cuando la extensión esté habilitada, aparecerán varios comandos. Para
|
igor@443
|
246 verificar que la extensión está trabajando, puede usar \hgcmd{help}
|
igor@443
|
247 para ver si la orden \hgxcmd{mq}{qinit} está disponible; vea un
|
igor@443
|
248 ejemplo en la figura~\ref{ex:mq:enabled}.
|
jerojasro@336
|
249
|
jerojasro@336
|
250 \begin{figure}[ht]
|
jerojasro@336
|
251 \interaction{mq.qinit-help.help}
|
igor@443
|
252 \caption{Cómo verificar que MQ está habilitado}
|
jerojasro@336
|
253 \label{ex:mq:enabled}
|
jerojasro@336
|
254 \end{figure}
|
jerojasro@336
|
255
|
igor@443
|
256 Puede usar MQ en \emph{cualquier} repositorio de Mercurial, y sus
|
igor@443
|
257 comandos solamente operarán con tal repositorio. Para comenzar, basta
|
igor@443
|
258 con preparar el repositorio con la orden \hgxcmd{mq}{qinit}(ver la
|
igor@443
|
259 figura~\ref{ex:mq:qinit}). Esta orden crea un directorio vacío
|
igor@443
|
260 llamado \sdirname{.hg/patches}, donde MQ mantendrá sus metadatos. Como
|
igor@443
|
261 otras ordenes de Mercurial, la orden \hgxcmd{mq}{qinit} no imprime
|
igor@443
|
262 nada cuando es exitosa.
|
jerojasro@336
|
263
|
jerojasro@336
|
264 \begin{figure}[ht]
|
jerojasro@336
|
265 \interaction{mq.tutorial.qinit}
|
igor@443
|
266 \caption{Preparar un repositorio para usar MQ}
|
jerojasro@336
|
267 \label{ex:mq:qinit}
|
jerojasro@336
|
268 \end{figure}
|
jerojasro@336
|
269
|
jerojasro@336
|
270 \begin{figure}[ht]
|
jerojasro@336
|
271 \interaction{mq.tutorial.qnew}
|
igor@443
|
272 \caption{Crear un nuevo parche}
|
jerojasro@336
|
273 \label{ex:mq:qnew}
|
jerojasro@336
|
274 \end{figure}
|
jerojasro@336
|
275
|
igor@443
|
276 \subsection{Crear un nuevo parche}
|
igor@443
|
277
|
igor@443
|
278 Para comenzar a trabajar en un nuevo parche use la orden
|
igor@443
|
279 \hgxcmd{mq}{qnew}. Esta orden recibe un argumento, el nombre del
|
igor@443
|
280 parche a crear. MQ lo usará como el nombre del fichero en el
|
igor@443
|
281 directorio \sdirname{.hg/patches}, como puede apreciarlo en la
|
igor@443
|
282 figura~\ref{ex:mq:qnew}.
|
igor@443
|
283
|
igor@443
|
284 También hay otros dos nuevos ficheros en el directorio
|
igor@443
|
285 \sdirname{.hg/patches}: \sfilename{series} y \sfilename{status}. El
|
igor@443
|
286 fichero \sfilename{series} lista todos los parches de los cuales MQ
|
igor@443
|
287 tiene noticia para este repositorio, con un parche por línea.
|
igor@443
|
288 Mercurial usa el fichero \sfilename{status} para mantener registros
|
igor@443
|
289 interns; da seguimiento a todos los parches que MQ ha \emph{aplicado}
|
igor@443
|
290 en el repositorio.
|
jerojasro@336
|
291
|
jerojasro@336
|
292 \begin{note}
|
igor@443
|
293 En ciertas ocasiones usted querrá editar el fichero
|
igor@443
|
294 \sfilename{series} a mano; por ejemplo, cambiar el orden en que se
|
igor@443
|
295 aplican ciertos parches. A pesar de esto, es una mala idea editar
|
igor@443
|
296 manualmente el fichero \sfilename{status}, dado que es fácil
|
igor@443
|
297 desorientar a MQ acerca de lo que está pasando.
|
jerojasro@336
|
298 \end{note}
|
jerojasro@336
|
299
|
igor@443
|
300 Una vez que haya creado un nuevo parche, puede editar los ficheros en
|
igor@443
|
301 el directorio de trabajo, como lo haría usualmente. Toda las órdenes
|
igor@443
|
302 que de a Mercurial, tales como \hgcmd{diff} y \hgcmd{annotate},
|
igor@443
|
303 trabajarán de la misma forma como lo han hecho antes.
|
igor@443
|
304
|
igor@443
|
305 \subsection{Refrescar un parche}
|
igor@443
|
306
|
igor@443
|
307 Cuando usted llega a un punto en el cual desea guardar su trabajo, use
|
igor@443
|
308 la orden \hgxcmd{mq}{qrefresh}(figura~\ref{ex:mq:qnew}) para
|
igor@443
|
309 actualizar el parche en el cual está trabajando. Esta orden almacena
|
igor@443
|
310 los cambios que haya hecho al directorio actual de trabajo en su
|
igor@443
|
311 parche, y almacena el conjunto de cambios correspondiente que contiene
|
igor@443
|
312 los cambios.
|
jerojasro@336
|
313
|
jerojasro@336
|
314 \begin{figure}[ht]
|
jerojasro@336
|
315 \interaction{mq.tutorial.qrefresh}
|
igor@443
|
316 \caption{Refrescar un parche}
|
jerojasro@336
|
317 \label{ex:mq:qrefresh}
|
jerojasro@336
|
318 \end{figure}
|
jerojasro@336
|
319
|
igor@443
|
320 Puede ejecutar la orden \hgxcmd{mq}{qrefresh} tan seguido como quiera,
|
igor@443
|
321 y es una buena forma de ``colocar marcas'' a su trabajo. Refresque su
|
igor@443
|
322 parche en momentos oportunos; intente un experimento; si el
|
igor@443
|
323 experimento no funciona, Use \hgcmd{revert} sobre sus modificaciones
|
igor@443
|
324 para volver al refresco anterior.
|
jerojasro@336
|
325
|
jerojasro@336
|
326 \begin{figure}[ht]
|
jerojasro@336
|
327 \interaction{mq.tutorial.qrefresh2}
|
igor@443
|
328 \caption{Refrescar un parche muchas veces para acumular cambios}
|
jerojasro@336
|
329 \label{ex:mq:qrefresh2}
|
jerojasro@336
|
330 \end{figure}
|
jerojasro@336
|
331
|
igor@443
|
332 \subsection{Aplicar un parche tras otro y dar seguimiento}
|
igor@443
|
333
|
igor@443
|
334 Cuando haya terminado de trabajar en un parche, o necesite trabajar en
|
igor@443
|
335 otro, puede usar la orden \hgxcmd{mq}{qnew} para crear un nuevo
|
igor@443
|
336 parche. Mercurial aplicará este parche sobre su parche anterior.
|
igor@443
|
337 Para un ejemplo, ver la figura~\ref{ex:mq:qnew2}. Note que el parche
|
igor@443
|
338 contiene los cambios en nuestro parche anterior como parte de su
|
igor@443
|
339 contexto( lo verá más claramente en la salida de \hgcmd{annotate}).
|
jerojasro@336
|
340
|
jerojasro@336
|
341 \begin{figure}[ht]
|
jerojasro@336
|
342 \interaction{mq.tutorial.qnew2}
|
igor@443
|
343 \caption{Aplicar un parche después del primero}
|
jerojasro@336
|
344 \label{ex:mq:qnew2}
|
jerojasro@336
|
345 \end{figure}
|
jerojasro@336
|
346
|
igor@443
|
347 Hasta ahora, con excepción de \hgxcmd{mq}{qnew} y
|
igor@443
|
348 \hgxcmd{mq}{qrefresh}, hemos sido cuidadosos para aplicar únicamente
|
igor@443
|
349 órdenes usuaales de Mercurial. De todas maneras, MQ ofrece muchos
|
igor@443
|
350 comandos que son más sencillos de usar cuando esté pensando acerca de
|
igor@443
|
351 parches, como se puede ver en la figura~\ref{ex:mq:qseries}:
|
jerojasro@336
|
352
|
jerojasro@336
|
353 \begin{itemize}
|
igor@443
|
354 \item La orden \hgxcmd{mq}{qseries} lista cada parche del cual MQ
|
igor@443
|
355 tiene noticia en este repositorio, desde el más antiguo hasta el más
|
igor@443
|
356 nuevo(El último \emph{creado}).
|
igor@443
|
357 \item La orden \hgxcmd{mq}{qapplied} lista cada parche que MQ haya
|
igor@443
|
358 \emph{aplicado} en este repositorio, de nuevo, desde el más antiguo
|
igor@443
|
359 hasta el más nuevo (El aplicado más recientemente).
|
jerojasro@336
|
360 \end{itemize}
|
jerojasro@336
|
361
|
jerojasro@336
|
362 \begin{figure}[ht]
|
jerojasro@336
|
363 \interaction{mq.tutorial.qseries}
|
igor@443
|
364 \caption{Entender la pila de parches con \hgxcmd{mq}{qseries} y
|
jerojasro@336
|
365 \hgxcmd{mq}{qapplied}}
|
jerojasro@336
|
366 \label{ex:mq:qseries}
|
jerojasro@336
|
367 \end{figure}
|
jerojasro@336
|
368
|
igor@443
|
369 \subsection{Manipular la pila de parches}
|
igor@443
|
370
|
igor@443
|
371 La discusión previa indicó que debe haber una diferencia entre los
|
igor@443
|
372 parches ``conocidos'' y ``aplicados'', y efectivamente la hay. MQ
|
igor@443
|
373 puede manejar un parche sin que este haya sido aplicado al
|
igor@443
|
374 repositorio.
|
igor@443
|
375
|
igor@443
|
376 Un parche \emph{aplicado} tiene su correspondiente conjunto de cambios
|
igor@443
|
377 en el repositorio, y los efectos del parche y el conjunto de cambios
|
igor@443
|
378 son visibles en el directorio de trabajo. Puede deshacer la
|
igor@443
|
379 aplicación de un parche con la orden \hgxcmd{mq}{qpop}. MQ
|
igor@443
|
380 \emph{sabe acerca de}, o maneja un parche sustraído, pero el parche ya
|
igor@443
|
381 no tendrá un conjunto de cambios correspondientes en el repositorio, y
|
igor@443
|
382 el directorio de trabajo no contendrá los cambios hechos por el
|
igor@443
|
383 parche. La figura~\ref{fig:mq:stack} ilustra la diferencia entre
|
igor@443
|
384 parches aplicados y seguidos.
|
jerojasro@336
|
385
|
jerojasro@336
|
386 \begin{figure}[ht]
|
jerojasro@336
|
387 \centering
|
jerojasro@336
|
388 \grafix{mq-stack}
|
igor@443
|
389 \caption{Parches aplicados y no aplicados en la pila de parches de MQ}
|
jerojasro@336
|
390 \label{fig:mq:stack}
|
jerojasro@336
|
391 \end{figure}
|
jerojasro@336
|
392
|
igor@443
|
393 Puede reaplicar un parche no aplicado o sustraído con la orden
|
igor@443
|
394 \hgxcmd{mq}{qpush}. Esto crea un nuevo conjunto de cambios
|
igor@443
|
395 correspondiente al parche, y los cambios del parche estarán presentes
|
igor@443
|
396 de nuevo en el directorio de trabajo. Vea ejemplos de
|
igor@443
|
397 \hgxcmd{mq}{qpop} y \hgxcmd{mq}{qpush} en acción en la
|
igor@443
|
398 figura~\ref{ex:mq:qpop}. Vea que hemos sustraído uno o dos parches,
|
igor@443
|
399 la salida de\hgxcmd{mq}{qseries} continúa igual, mientras que
|
igor@443
|
400 \hgxcmd{mq}{qapplied} ha cambiado.
|
jerojasro@336
|
401
|
jerojasro@336
|
402 \begin{figure}[ht]
|
jerojasro@336
|
403 \interaction{mq.tutorial.qpop}
|
igor@443
|
404 \caption{Modificar la pila de parches aplicados}
|
jerojasro@336
|
405 \label{ex:mq:qpop}
|
jerojasro@336
|
406 \end{figure}
|
jerojasro@336
|
407
|
igor@443
|
408 \subsection{Introducir y sustraer muchos parches}
|
igor@443
|
409
|
igor@443
|
410 Mientras que \hgxcmd{mq}{qpush} y \hgxcmd{mq}{qpop} operan sobre un
|
igor@443
|
411 único parche cada vez, puede introducir y sustraer varios parches de
|
igor@443
|
412 una vez. La opción \hgxopt{mq}{qpush}{-a} de \hgxcmd{mq}{qpush}
|
igor@443
|
413 introduce todos los cambios que no hayan sido aplicados, mientras que
|
igor@443
|
414 la opción \hgxopt{mq}{qpop}{-a} de \hgxcmd{mq}{qpop} sustrae todos los
|
igor@443
|
415 cambios aplicados. (Vea la sección~\ref{sec:mq:perf} más adelante
|
igor@443
|
416 en la cual se explican otras formas de de introducir y sustraer varios
|
igor@443
|
417 cambios.)
|
jerojasro@336
|
418
|
jerojasro@336
|
419 \begin{figure}[ht]
|
jerojasro@336
|
420 \interaction{mq.tutorial.qpush-a}
|
jerojasro@336
|
421 \caption{Pushing all unapplied patches}
|
jerojasro@336
|
422 \label{ex:mq:qpush-a}
|
jerojasro@336
|
423 \end{figure}
|
jerojasro@336
|
424
|
igor@443
|
425 \subsection{Medidas de seguridad y cómo saltarlas}
|
igor@443
|
426
|
igor@443
|
427 Muchas órdenes MQ revisan el directorio de trabajo antes de hacer
|
igor@443
|
428 cualquier cosa, y fallan si encuentran alguna modificación. Lo hacen
|
igor@443
|
429 para garantizar que usted no pierda cambio alguno de los que haya
|
igor@443
|
430 hecho, pero que no hayan sido incorporados en algún parche. La
|
igor@443
|
431 figura~\ref{ex:mq:add} ilusta esto; la orden \hgxcmd{mq}{qnew} no
|
igor@443
|
432 creará un nuevo parche si hay cambios notorios, causados en este caso
|
igor@443
|
433 por aplicado la orden \hgcmd{add} a \filename{file3}.
|
jerojasro@336
|
434
|
jerojasro@336
|
435 \begin{figure}[ht]
|
jerojasro@336
|
436 \interaction{mq.tutorial.add}
|
igor@443
|
437 \caption{Crear un parche a la fuerza}
|
jerojasro@336
|
438 \label{ex:mq:add}
|
jerojasro@336
|
439 \end{figure}
|
jerojasro@336
|
440
|
igor@443
|
441 Las órdenes que revisan el directorio actual cuentan con una opción
|
igor@443
|
442 ``Se lo que estoy haciendo'', que siempre está nombrada como
|
igor@443
|
443 \option{-f}. El significado exacto de \option{-f} depende de la
|
igor@443
|
444 orden. Por ejemplo, \hgcmdargs{qnew}{\hgxopt{mq}{qnew}{-f}}
|
igor@443
|
445 incorporarán cualquier cambio notorio en el nuevo parche que crea pero
|
igor@443
|
446 \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-f}} revertirá las modificaciones a
|
igor@443
|
447 cualquier fichero que haya sido afectado por el parche que está siendo
|
igor@443
|
448 sustraído. ¡Asegúrese de leer la documentación de la opción \option{-f}
|
igor@443
|
449 de cada comando antes de usarla!
|
igor@443
|
450
|
igor@443
|
451 \subsection{Trabajar con varios parches a la vez}
|
igor@443
|
452
|
igor@443
|
453 La orden \hgxcmd{mq}{qrefresh} siempre refresca el \emph{último}
|
igor@443
|
454 parche aplicado. Esto significa que usted puede suspender su trabajo
|
igor@443
|
455 en un parche (refrescándolo), sustraerlo o introducirlo para lograr
|
igor@443
|
456 que otro parche esté de último y trabajar en \emph{ese} parche por un
|
igor@443
|
457 rato.
|
igor@443
|
458
|
igor@443
|
459 A continuación un ejemplo que ilustra cómo puede usar esta habilidad.
|
igor@443
|
460 Digamos que está desarrollando una nueva característica en dos
|
igor@443
|
461 parches. El primero es un cambio en la parte fundamental de su
|
igor@443
|
462 programa, y el segundo--sobre el primero---cambia la interfaz de
|
igor@443
|
463 usuario para usar el código que ha añadido a la parte fundamental. Si
|
igor@443
|
464 ve que hay un fallo en la parte fundamental mientras está trabajando
|
igor@443
|
465 en el parche de UI\ndt{Interfaz de Usuario, User Interface en inglés}, es fácil arreglar la parte fundamental.
|
igor@443
|
466 Simplemente use \hgxcmd{mq}{qrefresh} sobre el parche de la UI para
|
igor@443
|
467 guardar los cambios de su trabajo en progreso, y use \hgxcmd{mq}{qpop}
|
igor@443
|
468 para sacar sustraer el parche de la parte fundamental. Arregla el
|
igor@443
|
469 fallo sobre la parte fundamental, aplique \hgxcmd{mq}{qrefresh} sobre
|
igor@443
|
470 el parche fundamental, y aplique \hgxcmd{mq}{qpush} sobre el parche de
|
igor@443
|
471 UI para continuar donde había quedado.
|
jerojasro@336
|
472
|
jerojasro@336
|
473 \section{More about patches}
|
jerojasro@336
|
474 \label{sec:mq:adv-patch}
|
jerojasro@336
|
475
|
jerojasro@336
|
476 MQ uses the GNU \command{patch} command to apply patches, so it's
|
jerojasro@336
|
477 helpful to know a few more detailed aspects of how \command{patch}
|
jerojasro@336
|
478 works, and about patches themselves.
|
jerojasro@336
|
479
|
jerojasro@336
|
480 \subsection{The strip count}
|
jerojasro@336
|
481
|
jerojasro@336
|
482 If you look at the file headers in a patch, you will notice that the
|
jerojasro@336
|
483 pathnames usually have an extra component on the front that isn't
|
jerojasro@336
|
484 present in the actual path name. This is a holdover from the way that
|
jerojasro@336
|
485 people used to generate patches (people still do this, but it's
|
jerojasro@336
|
486 somewhat rare with modern revision control tools).
|
jerojasro@336
|
487
|
jerojasro@336
|
488 Alice would unpack a tarball, edit her files, then decide that she
|
jerojasro@336
|
489 wanted to create a patch. So she'd rename her working directory,
|
jerojasro@336
|
490 unpack the tarball again (hence the need for the rename), and use the
|
jerojasro@336
|
491 \cmdopt{diff}{-r} and \cmdopt{diff}{-N} options to \command{diff} to
|
jerojasro@336
|
492 recursively generate a patch between the unmodified directory and the
|
jerojasro@336
|
493 modified one. The result would be that the name of the unmodified
|
jerojasro@336
|
494 directory would be at the front of the left-hand path in every file
|
jerojasro@336
|
495 header, and the name of the modified directory would be at the front
|
jerojasro@336
|
496 of the right-hand path.
|
jerojasro@336
|
497
|
jerojasro@336
|
498 Since someone receiving a patch from the Alices of the net would be
|
jerojasro@336
|
499 unlikely to have unmodified and modified directories with exactly the
|
jerojasro@336
|
500 same names, the \command{patch} command has a \cmdopt{patch}{-p}
|
jerojasro@336
|
501 option that indicates the number of leading path name components to
|
jerojasro@336
|
502 strip when trying to apply a patch. This number is called the
|
jerojasro@336
|
503 \emph{strip count}.
|
jerojasro@336
|
504
|
jerojasro@336
|
505 An option of ``\texttt{-p1}'' means ``use a strip count of one''. If
|
jerojasro@336
|
506 \command{patch} sees a file name \filename{foo/bar/baz} in a file
|
jerojasro@336
|
507 header, it will strip \filename{foo} and try to patch a file named
|
jerojasro@336
|
508 \filename{bar/baz}. (Strictly speaking, the strip count refers to the
|
jerojasro@336
|
509 number of \emph{path separators} (and the components that go with them
|
jerojasro@336
|
510 ) to strip. A strip count of one will turn \filename{foo/bar} into
|
jerojasro@336
|
511 \filename{bar}, but \filename{/foo/bar} (notice the extra leading
|
jerojasro@336
|
512 slash) into \filename{foo/bar}.)
|
jerojasro@336
|
513
|
jerojasro@336
|
514 The ``standard'' strip count for patches is one; almost all patches
|
jerojasro@336
|
515 contain one leading path name component that needs to be stripped.
|
jerojasro@336
|
516 Mercurial's \hgcmd{diff} command generates path names in this form,
|
jerojasro@336
|
517 and the \hgcmd{import} command and MQ expect patches to have a strip
|
jerojasro@336
|
518 count of one.
|
jerojasro@336
|
519
|
jerojasro@336
|
520 If you receive a patch from someone that you want to add to your patch
|
jerojasro@336
|
521 queue, and the patch needs a strip count other than one, you cannot
|
jerojasro@336
|
522 just \hgxcmd{mq}{qimport} the patch, because \hgxcmd{mq}{qimport} does not yet
|
jerojasro@336
|
523 have a \texttt{-p} option (see~\bug{311}). Your best bet is to
|
jerojasro@336
|
524 \hgxcmd{mq}{qnew} a patch of your own, then use \cmdargs{patch}{-p\emph{N}}
|
jerojasro@336
|
525 to apply their patch, followed by \hgcmd{addremove} to pick up any
|
jerojasro@336
|
526 files added or removed by the patch, followed by \hgxcmd{mq}{qrefresh}.
|
jerojasro@336
|
527 This complexity may become unnecessary; see~\bug{311} for details.
|
jerojasro@336
|
528 \subsection{Strategies for applying a patch}
|
jerojasro@336
|
529
|
jerojasro@336
|
530 When \command{patch} applies a hunk, it tries a handful of
|
jerojasro@336
|
531 successively less accurate strategies to try to make the hunk apply.
|
jerojasro@336
|
532 This falling-back technique often makes it possible to take a patch
|
jerojasro@336
|
533 that was generated against an old version of a file, and apply it
|
jerojasro@336
|
534 against a newer version of that file.
|
jerojasro@336
|
535
|
jerojasro@336
|
536 First, \command{patch} tries an exact match, where the line numbers,
|
jerojasro@336
|
537 the context, and the text to be modified must apply exactly. If it
|
jerojasro@336
|
538 cannot make an exact match, it tries to find an exact match for the
|
jerojasro@336
|
539 context, without honouring the line numbering information. If this
|
jerojasro@336
|
540 succeeds, it prints a line of output saying that the hunk was applied,
|
jerojasro@336
|
541 but at some \emph{offset} from the original line number.
|
jerojasro@336
|
542
|
jerojasro@336
|
543 If a context-only match fails, \command{patch} removes the first and
|
jerojasro@336
|
544 last lines of the context, and tries a \emph{reduced} context-only
|
jerojasro@336
|
545 match. If the hunk with reduced context succeeds, it prints a message
|
jerojasro@336
|
546 saying that it applied the hunk with a \emph{fuzz factor} (the number
|
jerojasro@336
|
547 after the fuzz factor indicates how many lines of context
|
jerojasro@336
|
548 \command{patch} had to trim before the patch applied).
|
jerojasro@336
|
549
|
jerojasro@336
|
550 When neither of these techniques works, \command{patch} prints a
|
jerojasro@336
|
551 message saying that the hunk in question was rejected. It saves
|
jerojasro@336
|
552 rejected hunks (also simply called ``rejects'') to a file with the
|
jerojasro@336
|
553 same name, and an added \sfilename{.rej} extension. It also saves an
|
jerojasro@336
|
554 unmodified copy of the file with a \sfilename{.orig} extension; the
|
jerojasro@336
|
555 copy of the file without any extensions will contain any changes made
|
jerojasro@336
|
556 by hunks that \emph{did} apply cleanly. If you have a patch that
|
jerojasro@336
|
557 modifies \filename{foo} with six hunks, and one of them fails to
|
jerojasro@336
|
558 apply, you will have: an unmodified \filename{foo.orig}, a
|
jerojasro@336
|
559 \filename{foo.rej} containing one hunk, and \filename{foo}, containing
|
jerojasro@336
|
560 the changes made by the five successful five hunks.
|
jerojasro@336
|
561
|
jerojasro@336
|
562 \subsection{Some quirks of patch representation}
|
jerojasro@336
|
563
|
jerojasro@336
|
564 There are a few useful things to know about how \command{patch} works
|
jerojasro@336
|
565 with files.
|
jerojasro@336
|
566 \begin{itemize}
|
jerojasro@336
|
567 \item This should already be obvious, but \command{patch} cannot
|
jerojasro@336
|
568 handle binary files.
|
jerojasro@336
|
569 \item Neither does it care about the executable bit; it creates new
|
jerojasro@336
|
570 files as readable, but not executable.
|
jerojasro@336
|
571 \item \command{patch} treats the removal of a file as a diff between
|
jerojasro@336
|
572 the file to be removed and the empty file. So your idea of ``I
|
jerojasro@336
|
573 deleted this file'' looks like ``every line of this file was
|
jerojasro@336
|
574 deleted'' in a patch.
|
jerojasro@336
|
575 \item It treats the addition of a file as a diff between the empty
|
jerojasro@336
|
576 file and the file to be added. So in a patch, your idea of ``I
|
jerojasro@336
|
577 added this file'' looks like ``every line of this file was added''.
|
jerojasro@336
|
578 \item It treats a renamed file as the removal of the old name, and the
|
jerojasro@336
|
579 addition of the new name. This means that renamed files have a big
|
jerojasro@336
|
580 footprint in patches. (Note also that Mercurial does not currently
|
jerojasro@336
|
581 try to infer when files have been renamed or copied in a patch.)
|
jerojasro@336
|
582 \item \command{patch} cannot represent empty files, so you cannot use
|
jerojasro@336
|
583 a patch to represent the notion ``I added this empty file to the
|
jerojasro@336
|
584 tree''.
|
jerojasro@336
|
585 \end{itemize}
|
jerojasro@336
|
586 \subsection{Beware the fuzz}
|
jerojasro@336
|
587
|
jerojasro@336
|
588 While applying a hunk at an offset, or with a fuzz factor, will often
|
jerojasro@336
|
589 be completely successful, these inexact techniques naturally leave
|
jerojasro@336
|
590 open the possibility of corrupting the patched file. The most common
|
jerojasro@336
|
591 cases typically involve applying a patch twice, or at an incorrect
|
jerojasro@336
|
592 location in the file. If \command{patch} or \hgxcmd{mq}{qpush} ever
|
jerojasro@336
|
593 mentions an offset or fuzz factor, you should make sure that the
|
jerojasro@336
|
594 modified files are correct afterwards.
|
jerojasro@336
|
595
|
jerojasro@336
|
596 It's often a good idea to refresh a patch that has applied with an
|
jerojasro@336
|
597 offset or fuzz factor; refreshing the patch generates new context
|
jerojasro@336
|
598 information that will make it apply cleanly. I say ``often,'' not
|
jerojasro@336
|
599 ``always,'' because sometimes refreshing a patch will make it fail to
|
jerojasro@336
|
600 apply against a different revision of the underlying files. In some
|
jerojasro@336
|
601 cases, such as when you're maintaining a patch that must sit on top of
|
jerojasro@336
|
602 multiple versions of a source tree, it's acceptable to have a patch
|
jerojasro@336
|
603 apply with some fuzz, provided you've verified the results of the
|
jerojasro@336
|
604 patching process in such cases.
|
jerojasro@336
|
605
|
jerojasro@336
|
606 \subsection{Handling rejection}
|
jerojasro@336
|
607
|
jerojasro@336
|
608 If \hgxcmd{mq}{qpush} fails to apply a patch, it will print an error
|
jerojasro@336
|
609 message and exit. If it has left \sfilename{.rej} files behind, it is
|
jerojasro@336
|
610 usually best to fix up the rejected hunks before you push more patches
|
jerojasro@336
|
611 or do any further work.
|
jerojasro@336
|
612
|
jerojasro@336
|
613 If your patch \emph{used to} apply cleanly, and no longer does because
|
jerojasro@336
|
614 you've changed the underlying code that your patches are based on,
|
jerojasro@336
|
615 Mercurial Queues can help; see section~\ref{sec:mq:merge} for details.
|
jerojasro@336
|
616
|
jerojasro@336
|
617 Unfortunately, there aren't any great techniques for dealing with
|
jerojasro@336
|
618 rejected hunks. Most often, you'll need to view the \sfilename{.rej}
|
jerojasro@336
|
619 file and edit the target file, applying the rejected hunks by hand.
|
jerojasro@336
|
620
|
jerojasro@336
|
621 If you're feeling adventurous, Neil Brown, a Linux kernel hacker,
|
jerojasro@336
|
622 wrote a tool called \command{wiggle}~\cite{web:wiggle}, which is more
|
jerojasro@336
|
623 vigorous than \command{patch} in its attempts to make a patch apply.
|
jerojasro@336
|
624
|
jerojasro@336
|
625 Another Linux kernel hacker, Chris Mason (the author of Mercurial
|
jerojasro@336
|
626 Queues), wrote a similar tool called
|
jerojasro@336
|
627 \command{mpatch}~\cite{web:mpatch}, which takes a simple approach to
|
jerojasro@336
|
628 automating the application of hunks rejected by \command{patch}. The
|
jerojasro@336
|
629 \command{mpatch} command can help with four common reasons that a hunk
|
jerojasro@336
|
630 may be rejected:
|
jerojasro@336
|
631
|
jerojasro@336
|
632 \begin{itemize}
|
jerojasro@336
|
633 \item The context in the middle of a hunk has changed.
|
jerojasro@336
|
634 \item A hunk is missing some context at the beginning or end.
|
jerojasro@336
|
635 \item A large hunk might apply better---either entirely or in
|
jerojasro@336
|
636 part---if it was broken up into smaller hunks.
|
jerojasro@336
|
637 \item A hunk removes lines with slightly different content than those
|
jerojasro@336
|
638 currently present in the file.
|
jerojasro@336
|
639 \end{itemize}
|
jerojasro@336
|
640
|
jerojasro@336
|
641 If you use \command{wiggle} or \command{mpatch}, you should be doubly
|
jerojasro@336
|
642 careful to check your results when you're done. In fact,
|
jerojasro@336
|
643 \command{mpatch} enforces this method of double-checking the tool's
|
jerojasro@336
|
644 output, by automatically dropping you into a merge program when it has
|
jerojasro@336
|
645 done its job, so that you can verify its work and finish off any
|
jerojasro@336
|
646 remaining merges.
|
jerojasro@336
|
647
|
jerojasro@336
|
648 \section{Getting the best performance out of MQ}
|
jerojasro@336
|
649 \label{sec:mq:perf}
|
jerojasro@336
|
650
|
jerojasro@336
|
651 MQ is very efficient at handling a large number of patches. I ran
|
jerojasro@336
|
652 some performance experiments in mid-2006 for a talk that I gave at the
|
jerojasro@336
|
653 2006 EuroPython conference~\cite{web:europython}. I used as my data
|
jerojasro@336
|
654 set the Linux 2.6.17-mm1 patch series, which consists of 1,738
|
jerojasro@336
|
655 patches. I applied these on top of a Linux kernel repository
|
jerojasro@336
|
656 containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux
|
jerojasro@336
|
657 2.6.17.
|
jerojasro@336
|
658
|
jerojasro@336
|
659 On my old, slow laptop, I was able to
|
jerojasro@336
|
660 \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} all 1,738 patches in 3.5 minutes,
|
jerojasro@336
|
661 and \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} them all in 30 seconds. (On a
|
jerojasro@336
|
662 newer laptop, the time to push all patches dropped to two minutes.) I
|
jerojasro@336
|
663 could \hgxcmd{mq}{qrefresh} one of the biggest patches (which made 22,779
|
jerojasro@336
|
664 lines of changes to 287 files) in 6.6 seconds.
|
jerojasro@336
|
665
|
jerojasro@336
|
666 Clearly, MQ is well suited to working in large trees, but there are a
|
jerojasro@336
|
667 few tricks you can use to get the best performance of it.
|
jerojasro@336
|
668
|
jerojasro@336
|
669 First of all, try to ``batch'' operations together. Every time you
|
jerojasro@336
|
670 run \hgxcmd{mq}{qpush} or \hgxcmd{mq}{qpop}, these commands scan the working
|
jerojasro@336
|
671 directory once to make sure you haven't made some changes and then
|
jerojasro@336
|
672 forgotten to run \hgxcmd{mq}{qrefresh}. On a small tree, the time that
|
jerojasro@336
|
673 this scan takes is unnoticeable. However, on a medium-sized tree
|
jerojasro@336
|
674 (containing tens of thousands of files), it can take a second or more.
|
jerojasro@336
|
675
|
jerojasro@336
|
676 The \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} commands allow you to push and pop
|
jerojasro@336
|
677 multiple patches at a time. You can identify the ``destination
|
jerojasro@336
|
678 patch'' that you want to end up at. When you \hgxcmd{mq}{qpush} with a
|
jerojasro@336
|
679 destination specified, it will push patches until that patch is at the
|
jerojasro@336
|
680 top of the applied stack. When you \hgxcmd{mq}{qpop} to a destination, MQ
|
jerojasro@336
|
681 will pop patches until the destination patch is at the top.
|
jerojasro@336
|
682
|
jerojasro@336
|
683 You can identify a destination patch using either the name of the
|
jerojasro@336
|
684 patch, or by number. If you use numeric addressing, patches are
|
jerojasro@336
|
685 counted from zero; this means that the first patch is zero, the second
|
jerojasro@336
|
686 is one, and so on.
|
jerojasro@336
|
687
|
jerojasro@336
|
688 \section{Updating your patches when the underlying code changes}
|
jerojasro@336
|
689 \label{sec:mq:merge}
|
jerojasro@336
|
690
|
jerojasro@336
|
691 It's common to have a stack of patches on top of an underlying
|
jerojasro@336
|
692 repository that you don't modify directly. If you're working on
|
jerojasro@336
|
693 changes to third-party code, or on a feature that is taking longer to
|
jerojasro@336
|
694 develop than the rate of change of the code beneath, you will often
|
jerojasro@336
|
695 need to sync up with the underlying code, and fix up any hunks in your
|
jerojasro@336
|
696 patches that no longer apply. This is called \emph{rebasing} your
|
jerojasro@336
|
697 patch series.
|
jerojasro@336
|
698
|
jerojasro@336
|
699 The simplest way to do this is to \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}}
|
jerojasro@336
|
700 your patches, then \hgcmd{pull} changes into the underlying
|
jerojasro@336
|
701 repository, and finally \hgcmdargs{qpush}{\hgxopt{mq}{qpop}{-a}} your
|
jerojasro@336
|
702 patches again. MQ will stop pushing any time it runs across a patch
|
jerojasro@336
|
703 that fails to apply during conflicts, allowing you to fix your
|
jerojasro@336
|
704 conflicts, \hgxcmd{mq}{qrefresh} the affected patch, and continue pushing
|
jerojasro@336
|
705 until you have fixed your entire stack.
|
jerojasro@336
|
706
|
jerojasro@336
|
707 This approach is easy to use and works well if you don't expect
|
jerojasro@336
|
708 changes to the underlying code to affect how well your patches apply.
|
jerojasro@336
|
709 If your patch stack touches code that is modified frequently or
|
jerojasro@336
|
710 invasively in the underlying repository, however, fixing up rejected
|
jerojasro@336
|
711 hunks by hand quickly becomes tiresome.
|
jerojasro@336
|
712
|
jerojasro@336
|
713 It's possible to partially automate the rebasing process. If your
|
jerojasro@336
|
714 patches apply cleanly against some revision of the underlying repo, MQ
|
jerojasro@336
|
715 can use this information to help you to resolve conflicts between your
|
jerojasro@336
|
716 patches and a different revision.
|
jerojasro@336
|
717
|
jerojasro@336
|
718 The process is a little involved.
|
jerojasro@336
|
719 \begin{enumerate}
|
jerojasro@336
|
720 \item To begin, \hgcmdargs{qpush}{-a} all of your patches on top of
|
jerojasro@336
|
721 the revision where you know that they apply cleanly.
|
jerojasro@336
|
722 \item Save a backup copy of your patch directory using
|
jerojasro@336
|
723 \hgcmdargs{qsave}{\hgxopt{mq}{qsave}{-e} \hgxopt{mq}{qsave}{-c}}. This prints
|
jerojasro@336
|
724 the name of the directory that it has saved the patches in. It will
|
jerojasro@336
|
725 save the patches to a directory called
|
jerojasro@336
|
726 \sdirname{.hg/patches.\emph{N}}, where \texttt{\emph{N}} is a small
|
jerojasro@336
|
727 integer. It also commits a ``save changeset'' on top of your
|
jerojasro@336
|
728 applied patches; this is for internal book-keeping, and records the
|
jerojasro@336
|
729 states of the \sfilename{series} and \sfilename{status} files.
|
jerojasro@336
|
730 \item Use \hgcmd{pull} to bring new changes into the underlying
|
jerojasro@336
|
731 repository. (Don't run \hgcmdargs{pull}{-u}; see below for why.)
|
jerojasro@336
|
732 \item Update to the new tip revision, using
|
jerojasro@336
|
733 \hgcmdargs{update}{\hgopt{update}{-C}} to override the patches you
|
jerojasro@336
|
734 have pushed.
|
jerojasro@336
|
735 \item Merge all patches using \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}
|
jerojasro@336
|
736 \hgxopt{mq}{qpush}{-a}}. The \hgxopt{mq}{qpush}{-m} option to \hgxcmd{mq}{qpush}
|
jerojasro@336
|
737 tells MQ to perform a three-way merge if the patch fails to apply.
|
jerojasro@336
|
738 \end{enumerate}
|
jerojasro@336
|
739
|
jerojasro@336
|
740 During the \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}}, each patch in the
|
jerojasro@336
|
741 \sfilename{series} file is applied normally. If a patch applies with
|
jerojasro@336
|
742 fuzz or rejects, MQ looks at the queue you \hgxcmd{mq}{qsave}d, and
|
jerojasro@336
|
743 performs a three-way merge with the corresponding changeset. This
|
jerojasro@336
|
744 merge uses Mercurial's normal merge machinery, so it may pop up a GUI
|
jerojasro@336
|
745 merge tool to help you to resolve problems.
|
jerojasro@336
|
746
|
jerojasro@336
|
747 When you finish resolving the effects of a patch, MQ refreshes your
|
jerojasro@336
|
748 patch based on the result of the merge.
|
jerojasro@336
|
749
|
jerojasro@336
|
750 At the end of this process, your repository will have one extra head
|
jerojasro@336
|
751 from the old patch queue, and a copy of the old patch queue will be in
|
jerojasro@336
|
752 \sdirname{.hg/patches.\emph{N}}. You can remove the extra head using
|
jerojasro@336
|
753 \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a} \hgxopt{mq}{qpop}{-n} patches.\emph{N}}
|
jerojasro@336
|
754 or \hgcmd{strip}. You can delete \sdirname{.hg/patches.\emph{N}} once
|
jerojasro@336
|
755 you are sure that you no longer need it as a backup.
|
jerojasro@336
|
756
|
jerojasro@336
|
757 \section{Identifying patches}
|
jerojasro@336
|
758
|
jerojasro@336
|
759 MQ commands that work with patches let you refer to a patch either by
|
jerojasro@336
|
760 using its name or by a number. By name is obvious enough; pass the
|
jerojasro@336
|
761 name \filename{foo.patch} to \hgxcmd{mq}{qpush}, for example, and it will
|
jerojasro@336
|
762 push patches until \filename{foo.patch} is applied.
|
jerojasro@336
|
763
|
jerojasro@336
|
764 As a shortcut, you can refer to a patch using both a name and a
|
jerojasro@336
|
765 numeric offset; \texttt{foo.patch-2} means ``two patches before
|
jerojasro@336
|
766 \texttt{foo.patch}'', while \texttt{bar.patch+4} means ``four patches
|
jerojasro@336
|
767 after \texttt{bar.patch}''.
|
jerojasro@336
|
768
|
jerojasro@336
|
769 Referring to a patch by index isn't much different. The first patch
|
jerojasro@336
|
770 printed in the output of \hgxcmd{mq}{qseries} is patch zero (yes, it's one
|
jerojasro@336
|
771 of those start-at-zero counting systems); the second is patch one; and
|
jerojasro@336
|
772 so on.
|
jerojasro@336
|
773
|
jerojasro@336
|
774 MQ also makes it easy to work with patches when you are using normal
|
jerojasro@336
|
775 Mercurial commands. Every command that accepts a changeset ID will
|
jerojasro@336
|
776 also accept the name of an applied patch. MQ augments the tags
|
jerojasro@336
|
777 normally in the repository with an eponymous one for each applied
|
jerojasro@336
|
778 patch. In addition, the special tags \index{tags!special tag
|
jerojasro@336
|
779 names!\texttt{qbase}}\texttt{qbase} and \index{tags!special tag
|
jerojasro@336
|
780 names!\texttt{qtip}}\texttt{qtip} identify the ``bottom-most'' and
|
jerojasro@336
|
781 topmost applied patches, respectively.
|
jerojasro@336
|
782
|
jerojasro@336
|
783 These additions to Mercurial's normal tagging capabilities make
|
jerojasro@336
|
784 dealing with patches even more of a breeze.
|
jerojasro@336
|
785 \begin{itemize}
|
jerojasro@336
|
786 \item Want to patchbomb a mailing list with your latest series of
|
jerojasro@336
|
787 changes?
|
jerojasro@336
|
788 \begin{codesample4}
|
jerojasro@336
|
789 hg email qbase:qtip
|
jerojasro@336
|
790 \end{codesample4}
|
jerojasro@336
|
791 (Don't know what ``patchbombing'' is? See
|
jerojasro@336
|
792 section~\ref{sec:hgext:patchbomb}.)
|
jerojasro@336
|
793 \item Need to see all of the patches since \texttt{foo.patch} that
|
jerojasro@336
|
794 have touched files in a subdirectory of your tree?
|
jerojasro@336
|
795 \begin{codesample4}
|
jerojasro@336
|
796 hg log -r foo.patch:qtip \emph{subdir}
|
jerojasro@336
|
797 \end{codesample4}
|
jerojasro@336
|
798 \end{itemize}
|
jerojasro@336
|
799
|
jerojasro@336
|
800 Because MQ makes the names of patches available to the rest of
|
jerojasro@336
|
801 Mercurial through its normal internal tag machinery, you don't need to
|
jerojasro@336
|
802 type in the entire name of a patch when you want to identify it by
|
jerojasro@336
|
803 name.
|
jerojasro@336
|
804
|
jerojasro@336
|
805 \begin{figure}[ht]
|
jerojasro@336
|
806 \interaction{mq.id.output}
|
jerojasro@336
|
807 \caption{Using MQ's tag features to work with patches}
|
jerojasro@336
|
808 \label{ex:mq:id}
|
jerojasro@336
|
809 \end{figure}
|
jerojasro@336
|
810
|
jerojasro@336
|
811 Another nice consequence of representing patch names as tags is that
|
jerojasro@336
|
812 when you run the \hgcmd{log} command, it will display a patch's name
|
jerojasro@336
|
813 as a tag, simply as part of its normal output. This makes it easy to
|
jerojasro@336
|
814 visually distinguish applied patches from underlying ``normal''
|
jerojasro@336
|
815 revisions. Figure~\ref{ex:mq:id} shows a few normal Mercurial
|
jerojasro@336
|
816 commands in use with applied patches.
|
jerojasro@336
|
817
|
jerojasro@336
|
818 \section{Useful things to know about}
|
jerojasro@336
|
819
|
jerojasro@336
|
820 There are a number of aspects of MQ usage that don't fit tidily into
|
jerojasro@336
|
821 sections of their own, but that are good to know. Here they are, in
|
jerojasro@336
|
822 one place.
|
jerojasro@336
|
823
|
jerojasro@336
|
824 \begin{itemize}
|
jerojasro@336
|
825 \item Normally, when you \hgxcmd{mq}{qpop} a patch and \hgxcmd{mq}{qpush} it
|
jerojasro@336
|
826 again, the changeset that represents the patch after the pop/push
|
jerojasro@336
|
827 will have a \emph{different identity} than the changeset that
|
jerojasro@336
|
828 represented the hash beforehand. See
|
jerojasro@336
|
829 section~\ref{sec:mqref:cmd:qpush} for information as to why this is.
|
jerojasro@336
|
830 \item It's not a good idea to \hgcmd{merge} changes from another
|
jerojasro@336
|
831 branch with a patch changeset, at least if you want to maintain the
|
jerojasro@336
|
832 ``patchiness'' of that changeset and changesets below it on the
|
jerojasro@336
|
833 patch stack. If you try to do this, it will appear to succeed, but
|
jerojasro@336
|
834 MQ will become confused.
|
jerojasro@336
|
835 \end{itemize}
|
jerojasro@336
|
836
|
jerojasro@336
|
837 \section{Managing patches in a repository}
|
jerojasro@336
|
838 \label{sec:mq:repo}
|
jerojasro@336
|
839
|
jerojasro@336
|
840 Because MQ's \sdirname{.hg/patches} directory resides outside a
|
jerojasro@336
|
841 Mercurial repository's working directory, the ``underlying'' Mercurial
|
jerojasro@336
|
842 repository knows nothing about the management or presence of patches.
|
jerojasro@336
|
843
|
jerojasro@336
|
844 This presents the interesting possibility of managing the contents of
|
jerojasro@336
|
845 the patch directory as a Mercurial repository in its own right. This
|
jerojasro@336
|
846 can be a useful way to work. For example, you can work on a patch for
|
jerojasro@336
|
847 a while, \hgxcmd{mq}{qrefresh} it, then \hgcmd{commit} the current state of
|
jerojasro@336
|
848 the patch. This lets you ``roll back'' to that version of the patch
|
jerojasro@336
|
849 later on.
|
jerojasro@336
|
850
|
jerojasro@336
|
851 You can then share different versions of the same patch stack among
|
jerojasro@336
|
852 multiple underlying repositories. I use this when I am developing a
|
jerojasro@336
|
853 Linux kernel feature. I have a pristine copy of my kernel sources for
|
jerojasro@336
|
854 each of several CPU architectures, and a cloned repository under each
|
jerojasro@336
|
855 that contains the patches I am working on. When I want to test a
|
jerojasro@336
|
856 change on a different architecture, I push my current patches to the
|
jerojasro@336
|
857 patch repository associated with that kernel tree, pop and push all of
|
jerojasro@336
|
858 my patches, and build and test that kernel.
|
jerojasro@336
|
859
|
jerojasro@336
|
860 Managing patches in a repository makes it possible for multiple
|
jerojasro@336
|
861 developers to work on the same patch series without colliding with
|
jerojasro@336
|
862 each other, all on top of an underlying source base that they may or
|
jerojasro@336
|
863 may not control.
|
jerojasro@336
|
864
|
jerojasro@336
|
865 \subsection{MQ support for patch repositories}
|
jerojasro@336
|
866
|
jerojasro@336
|
867 MQ helps you to work with the \sdirname{.hg/patches} directory as a
|
jerojasro@336
|
868 repository; when you prepare a repository for working with patches
|
jerojasro@336
|
869 using \hgxcmd{mq}{qinit}, you can pass the \hgxopt{mq}{qinit}{-c} option to
|
jerojasro@336
|
870 create the \sdirname{.hg/patches} directory as a Mercurial repository.
|
jerojasro@336
|
871
|
jerojasro@336
|
872 \begin{note}
|
jerojasro@336
|
873 If you forget to use the \hgxopt{mq}{qinit}{-c} option, you can simply go
|
jerojasro@336
|
874 into the \sdirname{.hg/patches} directory at any time and run
|
jerojasro@336
|
875 \hgcmd{init}. Don't forget to add an entry for the
|
jerojasro@336
|
876 \sfilename{status} file to the \sfilename{.hgignore} file, though
|
jerojasro@336
|
877
|
jerojasro@336
|
878 (\hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} does this for you
|
jerojasro@336
|
879 automatically); you \emph{really} don't want to manage the
|
jerojasro@336
|
880 \sfilename{status} file.
|
jerojasro@336
|
881 \end{note}
|
jerojasro@336
|
882
|
jerojasro@336
|
883 As a convenience, if MQ notices that the \dirname{.hg/patches}
|
jerojasro@336
|
884 directory is a repository, it will automatically \hgcmd{add} every
|
jerojasro@336
|
885 patch that you create and import.
|
jerojasro@336
|
886
|
jerojasro@336
|
887 MQ provides a shortcut command, \hgxcmd{mq}{qcommit}, that runs
|
jerojasro@336
|
888 \hgcmd{commit} in the \sdirname{.hg/patches} directory. This saves
|
jerojasro@336
|
889 some bothersome typing.
|
jerojasro@336
|
890
|
jerojasro@336
|
891 Finally, as a convenience to manage the patch directory, you can
|
jerojasro@336
|
892 define the alias \command{mq} on Unix systems. For example, on Linux
|
jerojasro@336
|
893 systems using the \command{bash} shell, you can include the following
|
jerojasro@336
|
894 snippet in your \tildefile{.bashrc}.
|
jerojasro@336
|
895
|
jerojasro@336
|
896 \begin{codesample2}
|
jerojasro@336
|
897 alias mq=`hg -R \$(hg root)/.hg/patches'
|
jerojasro@336
|
898 \end{codesample2}
|
jerojasro@336
|
899
|
jerojasro@336
|
900 You can then issue commands of the form \cmdargs{mq}{pull} from
|
jerojasro@336
|
901 the main repository.
|
jerojasro@336
|
902
|
jerojasro@336
|
903 \subsection{A few things to watch out for}
|
jerojasro@336
|
904
|
jerojasro@336
|
905 MQ's support for working with a repository full of patches is limited
|
jerojasro@336
|
906 in a few small respects.
|
jerojasro@336
|
907
|
jerojasro@336
|
908 MQ cannot automatically detect changes that you make to the patch
|
jerojasro@336
|
909 directory. If you \hgcmd{pull}, manually edit, or \hgcmd{update}
|
jerojasro@336
|
910 changes to patches or the \sfilename{series} file, you will have to
|
jerojasro@336
|
911 \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} and then
|
jerojasro@336
|
912 \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} in the underlying repository to
|
jerojasro@336
|
913 see those changes show up there. If you forget to do this, you can
|
jerojasro@336
|
914 confuse MQ's idea of which patches are applied.
|
jerojasro@336
|
915
|
jerojasro@336
|
916 \section{Third party tools for working with patches}
|
jerojasro@336
|
917 \label{sec:mq:tools}
|
jerojasro@336
|
918
|
jerojasro@336
|
919 Once you've been working with patches for a while, you'll find
|
jerojasro@336
|
920 yourself hungry for tools that will help you to understand and
|
jerojasro@336
|
921 manipulate the patches you're dealing with.
|
jerojasro@336
|
922
|
jerojasro@336
|
923 The \command{diffstat} command~\cite{web:diffstat} generates a
|
jerojasro@336
|
924 histogram of the modifications made to each file in a patch. It
|
jerojasro@336
|
925 provides a good way to ``get a sense of'' a patch---which files it
|
jerojasro@336
|
926 affects, and how much change it introduces to each file and as a
|
jerojasro@336
|
927 whole. (I find that it's a good idea to use \command{diffstat}'s
|
jerojasro@336
|
928 \cmdopt{diffstat}{-p} option as a matter of course, as otherwise it
|
jerojasro@336
|
929 will try to do clever things with prefixes of file names that
|
jerojasro@336
|
930 inevitably confuse at least me.)
|
jerojasro@336
|
931
|
jerojasro@336
|
932 \begin{figure}[ht]
|
jerojasro@336
|
933 \interaction{mq.tools.tools}
|
jerojasro@336
|
934 \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands}
|
jerojasro@336
|
935 \label{ex:mq:tools}
|
jerojasro@336
|
936 \end{figure}
|
jerojasro@336
|
937
|
jerojasro@336
|
938 The \package{patchutils} package~\cite{web:patchutils} is invaluable.
|
jerojasro@336
|
939 It provides a set of small utilities that follow the ``Unix
|
jerojasro@336
|
940 philosophy;'' each does one useful thing with a patch. The
|
jerojasro@336
|
941 \package{patchutils} command I use most is \command{filterdiff}, which
|
jerojasro@336
|
942 extracts subsets from a patch file. For example, given a patch that
|
jerojasro@336
|
943 modifies hundreds of files across dozens of directories, a single
|
jerojasro@336
|
944 invocation of \command{filterdiff} can generate a smaller patch that
|
jerojasro@336
|
945 only touches files whose names match a particular glob pattern. See
|
jerojasro@336
|
946 section~\ref{mq-collab:tips:interdiff} for another example.
|
jerojasro@336
|
947
|
jerojasro@336
|
948 \section{Good ways to work with patches}
|
jerojasro@336
|
949
|
jerojasro@336
|
950 Whether you are working on a patch series to submit to a free software
|
jerojasro@336
|
951 or open source project, or a series that you intend to treat as a
|
jerojasro@336
|
952 sequence of regular changesets when you're done, you can use some
|
jerojasro@336
|
953 simple techniques to keep your work well organised.
|
jerojasro@336
|
954
|
jerojasro@336
|
955 Give your patches descriptive names. A good name for a patch might be
|
jerojasro@336
|
956 \filename{rework-device-alloc.patch}, because it will immediately give
|
jerojasro@336
|
957 you a hint what the purpose of the patch is. Long names shouldn't be
|
jerojasro@336
|
958 a problem; you won't be typing the names often, but you \emph{will} be
|
jerojasro@336
|
959 running commands like \hgxcmd{mq}{qapplied} and \hgxcmd{mq}{qtop} over and over.
|
jerojasro@336
|
960 Good naming becomes especially important when you have a number of
|
jerojasro@336
|
961 patches to work with, or if you are juggling a number of different
|
jerojasro@336
|
962 tasks and your patches only get a fraction of your attention.
|
jerojasro@336
|
963
|
jerojasro@336
|
964 Be aware of what patch you're working on. Use the \hgxcmd{mq}{qtop}
|
jerojasro@336
|
965 command and skim over the text of your patches frequently---for
|
jerojasro@336
|
966 example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where
|
jerojasro@336
|
967 you stand. I have several times worked on and \hgxcmd{mq}{qrefresh}ed a
|
jerojasro@336
|
968 patch other than the one I intended, and it's often tricky to migrate
|
jerojasro@336
|
969 changes into the right patch after making them in the wrong one.
|
jerojasro@336
|
970
|
jerojasro@336
|
971 For this reason, it is very much worth investing a little time to
|
jerojasro@336
|
972 learn how to use some of the third-party tools I described in
|
jerojasro@336
|
973 section~\ref{sec:mq:tools}, particularly \command{diffstat} and
|
jerojasro@336
|
974 \command{filterdiff}. The former will give you a quick idea of what
|
jerojasro@336
|
975 changes your patch is making, while the latter makes it easy to splice
|
jerojasro@336
|
976 hunks selectively out of one patch and into another.
|
jerojasro@336
|
977
|
jerojasro@336
|
978 \section{MQ cookbook}
|
jerojasro@336
|
979
|
jerojasro@336
|
980 \subsection{Manage ``trivial'' patches}
|
jerojasro@336
|
981
|
jerojasro@336
|
982 Because the overhead of dropping files into a new Mercurial repository
|
jerojasro@336
|
983 is so low, it makes a lot of sense to manage patches this way even if
|
jerojasro@336
|
984 you simply want to make a few changes to a source tarball that you
|
jerojasro@336
|
985 downloaded.
|
jerojasro@336
|
986
|
jerojasro@336
|
987 Begin by downloading and unpacking the source tarball,
|
jerojasro@336
|
988 and turning it into a Mercurial repository.
|
jerojasro@336
|
989 \interaction{mq.tarball.download}
|
jerojasro@336
|
990
|
jerojasro@336
|
991 Continue by creating a patch stack and making your changes.
|
jerojasro@336
|
992 \interaction{mq.tarball.qinit}
|
jerojasro@336
|
993
|
jerojasro@336
|
994 Let's say a few weeks or months pass, and your package author releases
|
jerojasro@336
|
995 a new version. First, bring their changes into the repository.
|
jerojasro@336
|
996 \interaction{mq.tarball.newsource}
|
jerojasro@336
|
997 The pipeline starting with \hgcmd{locate} above deletes all files in
|
jerojasro@336
|
998 the working directory, so that \hgcmd{commit}'s
|
jerojasro@336
|
999 \hgopt{commit}{--addremove} option can actually tell which files have
|
jerojasro@336
|
1000 really been removed in the newer version of the source.
|
jerojasro@336
|
1001
|
jerojasro@336
|
1002 Finally, you can apply your patches on top of the new tree.
|
jerojasro@336
|
1003 \interaction{mq.tarball.repush}
|
jerojasro@336
|
1004
|
jerojasro@336
|
1005 \subsection{Combining entire patches}
|
jerojasro@336
|
1006 \label{sec:mq:combine}
|
jerojasro@336
|
1007
|
jerojasro@336
|
1008 MQ provides a command, \hgxcmd{mq}{qfold} that lets you combine entire
|
jerojasro@336
|
1009 patches. This ``folds'' the patches you name, in the order you name
|
jerojasro@336
|
1010 them, into the topmost applied patch, and concatenates their
|
jerojasro@336
|
1011 descriptions onto the end of its description. The patches that you
|
jerojasro@336
|
1012 fold must be unapplied before you fold them.
|
jerojasro@336
|
1013
|
jerojasro@336
|
1014 The order in which you fold patches matters. If your topmost applied
|
jerojasro@336
|
1015 patch is \texttt{foo}, and you \hgxcmd{mq}{qfold} \texttt{bar} and
|
jerojasro@336
|
1016 \texttt{quux} into it, you will end up with a patch that has the same
|
jerojasro@336
|
1017 effect as if you applied first \texttt{foo}, then \texttt{bar},
|
jerojasro@336
|
1018 followed by \texttt{quux}.
|
jerojasro@336
|
1019
|
jerojasro@336
|
1020 \subsection{Merging part of one patch into another}
|
jerojasro@336
|
1021
|
jerojasro@336
|
1022 Merging \emph{part} of one patch into another is more difficult than
|
jerojasro@336
|
1023 combining entire patches.
|
jerojasro@336
|
1024
|
jerojasro@336
|
1025 If you want to move changes to entire files, you can use
|
jerojasro@336
|
1026 \command{filterdiff}'s \cmdopt{filterdiff}{-i} and
|
jerojasro@336
|
1027 \cmdopt{filterdiff}{-x} options to choose the modifications to snip
|
jerojasro@336
|
1028 out of one patch, concatenating its output onto the end of the patch
|
jerojasro@336
|
1029 you want to merge into. You usually won't need to modify the patch
|
jerojasro@336
|
1030 you've merged the changes from. Instead, MQ will report some rejected
|
jerojasro@336
|
1031 hunks when you \hgxcmd{mq}{qpush} it (from the hunks you moved into the
|
jerojasro@336
|
1032 other patch), and you can simply \hgxcmd{mq}{qrefresh} the patch to drop
|
jerojasro@336
|
1033 the duplicate hunks.
|
jerojasro@336
|
1034
|
jerojasro@336
|
1035 If you have a patch that has multiple hunks modifying a file, and you
|
jerojasro@336
|
1036 only want to move a few of those hunks, the job becomes more messy,
|
jerojasro@336
|
1037 but you can still partly automate it. Use \cmdargs{lsdiff}{-nvv} to
|
jerojasro@336
|
1038 print some metadata about the patch.
|
jerojasro@336
|
1039 \interaction{mq.tools.lsdiff}
|
jerojasro@336
|
1040
|
jerojasro@336
|
1041 This command prints three different kinds of number:
|
jerojasro@336
|
1042 \begin{itemize}
|
jerojasro@336
|
1043 \item (in the first column) a \emph{file number} to identify each file
|
jerojasro@336
|
1044 modified in the patch;
|
jerojasro@336
|
1045 \item (on the next line, indented) the line number within a modified
|
jerojasro@336
|
1046 file where a hunk starts; and
|
jerojasro@336
|
1047 \item (on the same line) a \emph{hunk number} to identify that hunk.
|
jerojasro@336
|
1048 \end{itemize}
|
jerojasro@336
|
1049
|
jerojasro@336
|
1050 You'll have to use some visual inspection, and reading of the patch,
|
jerojasro@336
|
1051 to identify the file and hunk numbers you'll want, but you can then
|
jerojasro@336
|
1052 pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files}
|
jerojasro@336
|
1053 and \cmdopt{filterdiff}{--hunks} options, to select exactly the file
|
jerojasro@336
|
1054 and hunk you want to extract.
|
jerojasro@336
|
1055
|
jerojasro@336
|
1056 Once you have this hunk, you can concatenate it onto the end of your
|
jerojasro@336
|
1057 destination patch and continue with the remainder of
|
jerojasro@336
|
1058 section~\ref{sec:mq:combine}.
|
jerojasro@336
|
1059
|
jerojasro@336
|
1060 \section{Differences between quilt and MQ}
|
jerojasro@336
|
1061
|
jerojasro@336
|
1062 If you are already familiar with quilt, MQ provides a similar command
|
jerojasro@336
|
1063 set. There are a few differences in the way that it works.
|
jerojasro@336
|
1064
|
jerojasro@336
|
1065 You will already have noticed that most quilt commands have MQ
|
jerojasro@336
|
1066 counterparts that simply begin with a ``\texttt{q}''. The exceptions
|
jerojasro@336
|
1067 are quilt's \texttt{add} and \texttt{remove} commands, the
|
jerojasro@336
|
1068 counterparts for which are the normal Mercurial \hgcmd{add} and
|
jerojasro@336
|
1069 \hgcmd{remove} commands. There is no MQ equivalent of the quilt
|
jerojasro@336
|
1070 \texttt{edit} command.
|
jerojasro@336
|
1071
|
jerojasro@336
|
1072 %%% Local Variables:
|
jerojasro@336
|
1073 %%% mode: latex
|
jerojasro@336
|
1074 %%% TeX-master: "00book"
|
jerojasro@336
|
1075 %%% End:
|