hgbook

annotate es/mq.tex @ 447:93e7700c0322

Some more mq paragraphs translated
author Igor TAmara <igor@tamarapatino.org>
date Wed Dec 10 22:51:01 2008 -0500 (2008-12-10)
parents 40ba5d8583c7
children c17848cfbf75
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
igor@444 473 \section{Más acerca de parches}
jerojasro@336 474 \label{sec:mq:adv-patch}
jerojasro@336 475
igor@444 476 MQ usa la orden GNU \command{patch} para aplicar los parches, por lo
igor@444 477 tanto es útil conocer ciertos detalles de cómo trabaja
igor@444 478 \command{patch}, y también acerca de los parches.
igor@444 479
igor@444 480 \subsection{La cantidad de franjas}
igor@444 481
igor@444 482 Si ve el encabezado de un parche, notará que la ruta al archivo tiene
igor@444 483 un componente adicional al principio, que no está presente en la
igor@444 484 ruta. Esta es una traza de cómo generaba anteriormente los parches la
igor@444 485 gente(algunos aún lo hacen, pero es raro con las herramientas de
igor@444 486 control de revisiones del actuales).
igor@444 487
igor@444 488 Alicia desempaquetaría un comprimido, editaría sus archivos, y querría
igor@444 489 crear un parche. Por lo tanto ella renombraría su directorio de
igor@444 490 trabajo, desempacaría el comprimido de nuevo(para lo cual necesitó el
igor@444 491 renombramiento), y usaría las opciones \cmdopt{diff}{-r} y
igor@444 492 \cmdopt{diff}{-N} de \command{diff} para generar recursivamente un
igor@444 493 parche entre el directorio original y el modificado. El resultado
igor@444 494 sería que el nombre del directorio original estaría al principio de
igor@444 495 toda ruta en cada encabezado de fichero, y el nombre del directorio
igor@444 496 modificado estaría al frente de la porción derecha de la ruta del
igor@444 497 archivo.
jerojasro@336 498
igor@446 499 Como alguien que reciba un parche de Alicia en la red podría obtener
igor@446 500 dos directorios, uno original y el otro modificado con exactamente los
igor@446 501 mismos nombres, la orden \command{patch} tiene la opción
igor@446 502 \cmdopt{patch}{-p} que indica la cantidad de componentes de la ruta
igor@446 503 a eliminar cuando se vaya a aplicar el parche. Este número se
igor@446 504 llama la \emph{cantidad de eliminaciones}.
igor@446 505
igor@446 506 La opción con ``\texttt{-p1}'' significa ``elimine uno''. Si
igor@446 507 \command{patch} ve un nombre de fichero \filename{foo/bar/baz} en el
igor@446 508 encabezado del fichero, eliminará \filename{foo} y tratará de parchar
igor@446 509 un fichero llamado \filename{bar/baz}. (Hablando estrictamente, la
igor@446 510 cantidad de eliminaciones se refiere a la cantidad de \emph{separadores de
igor@446 511 ruta} (y los componentes que vayan con ellos) a eliminar. Si el
igor@446 512 contador es uno volverá \filename{foo/bar} en \filename{bar}, pero
igor@446 513 \filename{/foo/bar} (note la barra extra) en \filename{foo/bar}.)
igor@446 514
igor@446 515 La cantidad a eliminar``estándar'' para parches es uno; casi todos los
igor@446 516 parches contienen un componente inicial de la ruta que necesita ser
igor@446 517 eliminado. La orden \hgcmd{diff} de Mercurial genera nombres de ruta
igor@446 518 de esta forma, y la orden \hgcmd{import} y MQ esperan parches que
igor@446 519 tengan a uno como cuenta de eliminaciones.
igor@446 520
igor@446 521 Si recibe un parche de alguien de quien desea adicionar adicionar a su
igor@446 522 cola de parches, y el parche necesita una cuenta de eliminación que no
igor@446 523 sea uno, no podrá aplicar \hgxcmd{mq}{qimport} en primera medida,
igor@446 524 porque \hgxcmd{mq}{qimport} no tiene todavía una opción \texttt{-p}
igor@446 525 option (ver~\bug{311}). Lo mejor que puede hacer es aplicar
igor@446 526 \hgxcmd{mq}{qnew} por su cuenta, y después usar \cmdargs{patch}{-p\emph{N}}
igor@446 527 para aplicar tal parche, seguido de \hgcmd{addremove} para tener en
igor@446 528 cuenta cualquier fichero adicionado o eliminado por el parche, seguido
igor@446 529 de \hgxcmd{mq}{qrefresh}. Esta complejidad puede ser innecesaria;
igor@446 530 consulte~\bug{311} para más información.
igor@446 531
igor@446 532 \subsection{Estrategias para aplicar parches}
igor@446 533
igor@446 534 Cuando \command{patch} aplica un trozo, intenta varias estrategias
igor@446 535 sucesivas que decrecen en precisión para intentar aplicarlo. Esta
igor@446 536 técnica de pruebas y error aveces permite que un parche que fue
igor@446 537 generado contra una versión anterior de un fichero, sea aplicada sobre
igor@446 538 una versión más nueva del mismo.
igor@446 539
igor@446 540 Primero \command{patch} intenta una correspondencia perfecta donde los
igor@446 541 números de línea, el contexto y el texto a modificar deben coincidir
igor@446 542 perfectamente. Si no lo logra, intenta encontrar una correspondencia
igor@446 543 exacta del contexto, sin tener en cuenta el número de línea. Si es
igor@446 544 exitoso, imprime una línea indicando que el trozo fue aplicado, pero a
igor@446 545 un \emph{corrimiento} del número de línea original.
igor@446 546
igor@446 547 Si falla la correspondencia por contexto, \command{patch} elimina la
igor@446 548 primera y la última línea del contexto, e intenta una correspondencia
igor@446 549 \emph{reducida} del contexto. Si el trozo con contexto reducido es
igor@446 550 exitoso, imprime un mensaje indicando que aplicó el trozo con un
igor@446 551 \emph{factor difuso} (el número después del factor difuso indica
igor@446 552 cuántas líneas de contexto \command{patch} tuvo que eliminar antes de
igor@446 553 aplicar el parche).
igor@446 554
igor@446 555 Cuando ninguna de estas técnicas funciona, \command{patch} imprime un
igor@446 556 mensaje indicando que el trozo en cuestión se desechó. Almacena los
igor@446 557 trozos desechados(también llamados ``descartados'') en un fichero con
igor@446 558 el mismo nombre, y la extensión \sfilename{.rej} añadida. También
igor@446 559 almacena una copia igual al fichero original con la extensión
igor@446 560 \sfilename{.orig}; la copia del fichero sin extensión contendrá
igor@446 561 cualquier cambio hecho por los trozos que \emph{sí} se aplicaron sin
igor@446 562 problema. Si usted tiene un parche que modifica \filename{foo} con
igor@446 563 seis trozos, y uno de ellos falla al aplicarse, tendrá : un fichero
igor@446 564 original \filename{foo.orig}, un fichero \filename{foo.rej} que
igor@446 565 contiene el trozo, y \filename{foo}, que contiene los cambios que se
igor@446 566 aplicaron por los cinco trozos exitosos.
igor@446 567
igor@446 568 \subsection{Algunos detalles de la representación de parches}
igor@446 569
igor@446 570 Hay ciertas cosas útiles por saber acerca de cómo trabaja
igor@446 571 \command{patch} con los ficheros:
jerojasro@336 572 \begin{itemize}
igor@446 573 \item Debería ser obvio que \command{patch} no puede manipular
igor@446 574 ficheros binarios.
igor@446 575 \item No se preocupa por el bit ejecutable; crea ficheros nuevos en
igor@446 576 modo lectura, pero no ejecutable.
igor@446 577 \item \command{patch} intenta eliminar un fichero como una diferencia
igor@446 578 entre el fichero a eliminar y un fichero vacío. Y por lo tanto su
igor@446 579 idea de ``Borré este fichero'' debería pensarse como ``toda línea de
igor@446 580 este fichero fue eliminada'' en un parche.
igor@446 581 \item Trata la adición de un fichero como un diff entre un fichero
igor@446 582 vacío y el fichero a ser adicionado. Por lo tanto en un parche su
igor@446 583 idea de ``Añadí este fichero'' se vería como ``toda línea de este
igor@446 584 fichero fue añadida''.
igor@446 585 \item Trata el renombramiento de un fichero como la eliminación del
igor@446 586 nombre anterior y la adición del nuevo nombre. Esto significa que
igor@446 587 los ficheros renombrados dejan un rastro grande en los parches.
igor@446 588 (Tenga en cuenta que Mercurial no trata de inferir cuando los
igor@446 589 archivos han sido renombrados o copiados en un parche en este
igor@446 590 momento.)
igor@446 591 \item \command{patch} no puede representar ficheros vacíos, por lo
igor@446 592 tanto no puede usar un parche para representar la noción ``Añadí
igor@446 593 este fichero vacío al árbol''.
jerojasro@336 594 \end{itemize}
igor@446 595 \subsection{Cuidado con los difusos}
jerojasro@336 596
igor@447 597 Cuando aplique un trozo con un corrimiento, o con un factor difuso,
igor@447 598 aveces será taotalmente exitoso, tales técnicas inexactas dejan
igor@447 599 claramente la posibilidad de corromper el archivo parchado. Los casos
igor@447 600 más típicos involucran aplicar un parche dos veces o en un sitio
igor@447 601 incorrecto del fichero. Si \command{patch} o \hgxcmd{mq}{qpush} llegan
igor@447 602 a mencionar un corrimiento o un factor difuso, debería asegurarse que
igor@447 603 los ficheros modificados estén correctos después del suceso.
igor@447 604
igor@447 605 Casi siempre es buena idea refrescar un parche que fue aplicado con un
igor@447 606 corrimiento o un factor difuso; refrescar el parche genera nueva
igor@447 607 información de contexto que permitirá aplicarlo limpiamente. Digo
igor@447 608 ``casi siempre,'' no ``siempre'', puesto que en ciertas ocasiones
igor@447 609 refrescar un parche lo hará fallar frente a una revisión diferente del
igor@447 610 fichero. En algunos casos, como por ejemplo, cuando usted está
igor@447 611 manteniendo un parche que debe estar encima de múltiples revisiones de
igor@447 612 un árbol de fuentes, es aceptable tener un parche aplicado algo
igor@447 613 difuso, siempre que haya verificado los resultados del proceso de
igor@447 614 parchar.
igor@447 615
igor@447 616 \subsection{Manejo de descartes}
igor@447 617
igor@447 618 Si \hgxcmd{mq}{qpush} falla al aplicar un parche, mostrará un texto de
igor@447 619 error y saldrá. Si ha dejado ficheros \sfilename{.rej}, es mejor
igor@447 620 arreglar los trozos descartados antes de introducir parches
igor@447 621 adicionales o hacer cualquier otra cosa.
igor@447 622
igor@447 623 Si su parche \emph{solía} aplicarse limpiamente, y ya no lo hace
igor@447 624 porque ha cambiado código subyacente en el cual se basa su parche, las
igor@447 625 Colas de Mercurial pueden ayudar; consulte la sección~\ref{sec:mq:merge}.
igor@447 626
igor@447 627 Desafortunadamente, no hay grandes técnicas para tratar los trozos
igor@447 628 descartados. Casi siempre deberá consultar el fichero
igor@447 629 \sfilename{.rej} y editar el fichero objetivo, aplicando los trozos
igor@447 630 descartados a mano.
igor@447 631
igor@447 632 Si es aventurero, Neil Brown, un hacker del núcleo Linux, escribió una
igor@447 633 herramienta llamada \command{wiggle}~\cite{web:wiggle}, que es más
igor@447 634 vigorosa que \command{patch} en su intento de hacer que se aplique un
igor@447 635 parche.
igor@447 636
igor@447 637 Otro hacker del nucleo Linux, Chris Mason (el autor de las Colas de
igor@447 638 Mercurial), escribió una herramienta similar llamada
igor@447 639 \command{mpatch}~\cite{web:mpatch}, que sigue una aproximación
igor@447 640 sencilla para automatizar la aplicación de trozos descartados por
igor@447 641 \command{patch}. La orden \command{mpatch} puede ayudar con cuatro
igor@447 642 razones comunes por las cuales un parche ha sido descartado:
jerojasro@336 643
jerojasro@336 644 \begin{itemize}
igor@447 645 \item El contexto en la mitad de un trozo ha cambiado.
igor@447 646 \item Un trozo ha perdido cierto contexto al principio o al final.
igor@447 647 \item Un trozo largo podría aplicarse mejor---por completo o una
igor@447 648 parte---si estaba cortado en trozos más pequeños.
igor@447 649 \item Un trozo remueve líneas con contenido ligeramente diferente que
igor@447 650 aquellas que están presentes en el fichero.
jerojasro@336 651 \end{itemize}
jerojasro@336 652
igor@447 653 Si usted usa \command{wiggle} o \command{mpatch}, debería ser
igor@447 654 doblemente cuidadoso al revisar sus resultados cuando haya terminado.
igor@447 655 De hecho, \command{mpatch} refuerza este método de revisar por partida
igor@447 656 doble su salida, dejándolo a usted en un programa de fusión cuando la
igor@447 657 herramienta haya terminado su trabajo, de tal forma que usted pueda
igor@447 658 verificar lo que ha hecho y pueda terminar de aplicar cualquier fusión
igor@447 659 faltante.
igor@447 660
igor@447 661 \section{Contar con el máximo rendimiento de MQ}
jerojasro@336 662 \label{sec:mq:perf}
jerojasro@336 663
igor@447 664 MQ es muy eficiente al tratar con una gran cantidad de parches. Corrí
igor@447 665 unos experimentos de desempeño a mediados del 2006 para una charla que
igor@447 666 dí en la conferencia EuroPython 2006~\cite{web:europython}. Empleé la
igor@447 667 serie de parches para el núcleo Linux 2.6.17-mm1, que contaba con 1.738
igor@447 668 parches. Los apliqué sobre un repositorio del núcleo de Linux con
igor@447 669 todas las 27.472 revisiones entre 2.6.12-rc2 y 2.6.17.
igor@447 670
igor@447 671 En mi viejo y lento portátil, logré aplicar
igor@447 672 \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} a los 1.738 parches en 3.5
igor@447 673 minutos, y \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} en 30 segundos.
igor@447 674 (En un portátil más nuevo, el tiempo para introducir todos los
igor@447 675 parches, se logró en menos de dos minutos.) Apliqué
igor@447 676 \hgxcmd{mq}{qrefresh} sobre uno de los parches más grandes(que hizo
igor@447 677 22.779 líneas de cambios en 287 ficheros) en 6,6 segundos.
igor@447 678
igor@447 679 Claramente, MQ funciona adecuadamente en árboles grandes, y además hay
igor@447 680 unos trucos que pueden emplearse para obtener el máximo desempeño.
igor@447 681
igor@447 682 En primer lugar, trate de hacer ``en lote'' las operaciones. Cada vez
igor@447 683 que ejecute \hgxcmd{mq}{qpush} o \hgxcmd{mq}{qpop}, tales órdenes
igor@447 684 revisan el directorio de trabajo para asegurarse de que usted no ha
igor@447 685 hecho cambios y ha olvidado ejecutar \hgxcmd{mq}{qrefresh}. En un
igor@447 686 árbol pequeño, el tiempo de esta revisión puede ser mínimo, Pero en
igor@447 687 un árbol mediano(con decenas de miles de ficheros), puede tomar un
igor@447 688 segundo o más.
igor@447 689
igor@447 690 Las órdenes \hgxcmd{mq}{qpush} y \hgxcmd{mq}{qpop} le permiten
igor@447 691 introducir o sustraer varios parches en una operación. Puede
igor@447 692 identificar el ``parche destino'' que desee. Cuando aplique
igor@447 693 \hgxcmd{mq}{qpush} con un destino, introducirá tantos parches como sea
igor@447 694 necesario hasta que el especificado esté en el tope de la pila.
igor@447 695 Cuando emplee \hgxcmd{mq}{qpop} con un destino, MQ sustraerá parches
igor@447 696 hasta que el parche destino esté en el tope.
igor@447 697
igor@447 698 Puede identificar un parche destino con el nombre del parche o con el
igor@447 699 número. Si se refiere al número, los parches se contarán desde cero;
igor@447 700 esto significa que el primer parche es cero, el segundo es uno y así
igor@447 701 sucesivamente.
jerojasro@336 702
jerojasro@336 703 \section{Updating your patches when the underlying code changes}
jerojasro@336 704 \label{sec:mq:merge}
jerojasro@336 705
jerojasro@336 706 It's common to have a stack of patches on top of an underlying
jerojasro@336 707 repository that you don't modify directly. If you're working on
jerojasro@336 708 changes to third-party code, or on a feature that is taking longer to
jerojasro@336 709 develop than the rate of change of the code beneath, you will often
jerojasro@336 710 need to sync up with the underlying code, and fix up any hunks in your
jerojasro@336 711 patches that no longer apply. This is called \emph{rebasing} your
jerojasro@336 712 patch series.
jerojasro@336 713
jerojasro@336 714 The simplest way to do this is to \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}}
jerojasro@336 715 your patches, then \hgcmd{pull} changes into the underlying
jerojasro@336 716 repository, and finally \hgcmdargs{qpush}{\hgxopt{mq}{qpop}{-a}} your
jerojasro@336 717 patches again. MQ will stop pushing any time it runs across a patch
jerojasro@336 718 that fails to apply during conflicts, allowing you to fix your
jerojasro@336 719 conflicts, \hgxcmd{mq}{qrefresh} the affected patch, and continue pushing
jerojasro@336 720 until you have fixed your entire stack.
jerojasro@336 721
jerojasro@336 722 This approach is easy to use and works well if you don't expect
jerojasro@336 723 changes to the underlying code to affect how well your patches apply.
jerojasro@336 724 If your patch stack touches code that is modified frequently or
jerojasro@336 725 invasively in the underlying repository, however, fixing up rejected
jerojasro@336 726 hunks by hand quickly becomes tiresome.
jerojasro@336 727
jerojasro@336 728 It's possible to partially automate the rebasing process. If your
jerojasro@336 729 patches apply cleanly against some revision of the underlying repo, MQ
jerojasro@336 730 can use this information to help you to resolve conflicts between your
jerojasro@336 731 patches and a different revision.
jerojasro@336 732
jerojasro@336 733 The process is a little involved.
jerojasro@336 734 \begin{enumerate}
jerojasro@336 735 \item To begin, \hgcmdargs{qpush}{-a} all of your patches on top of
jerojasro@336 736 the revision where you know that they apply cleanly.
jerojasro@336 737 \item Save a backup copy of your patch directory using
jerojasro@336 738 \hgcmdargs{qsave}{\hgxopt{mq}{qsave}{-e} \hgxopt{mq}{qsave}{-c}}. This prints
jerojasro@336 739 the name of the directory that it has saved the patches in. It will
jerojasro@336 740 save the patches to a directory called
jerojasro@336 741 \sdirname{.hg/patches.\emph{N}}, where \texttt{\emph{N}} is a small
jerojasro@336 742 integer. It also commits a ``save changeset'' on top of your
jerojasro@336 743 applied patches; this is for internal book-keeping, and records the
jerojasro@336 744 states of the \sfilename{series} and \sfilename{status} files.
jerojasro@336 745 \item Use \hgcmd{pull} to bring new changes into the underlying
jerojasro@336 746 repository. (Don't run \hgcmdargs{pull}{-u}; see below for why.)
jerojasro@336 747 \item Update to the new tip revision, using
jerojasro@336 748 \hgcmdargs{update}{\hgopt{update}{-C}} to override the patches you
jerojasro@336 749 have pushed.
jerojasro@336 750 \item Merge all patches using \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}
jerojasro@336 751 \hgxopt{mq}{qpush}{-a}}. The \hgxopt{mq}{qpush}{-m} option to \hgxcmd{mq}{qpush}
jerojasro@336 752 tells MQ to perform a three-way merge if the patch fails to apply.
jerojasro@336 753 \end{enumerate}
jerojasro@336 754
jerojasro@336 755 During the \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}}, each patch in the
jerojasro@336 756 \sfilename{series} file is applied normally. If a patch applies with
jerojasro@336 757 fuzz or rejects, MQ looks at the queue you \hgxcmd{mq}{qsave}d, and
jerojasro@336 758 performs a three-way merge with the corresponding changeset. This
jerojasro@336 759 merge uses Mercurial's normal merge machinery, so it may pop up a GUI
jerojasro@336 760 merge tool to help you to resolve problems.
jerojasro@336 761
jerojasro@336 762 When you finish resolving the effects of a patch, MQ refreshes your
jerojasro@336 763 patch based on the result of the merge.
jerojasro@336 764
jerojasro@336 765 At the end of this process, your repository will have one extra head
jerojasro@336 766 from the old patch queue, and a copy of the old patch queue will be in
jerojasro@336 767 \sdirname{.hg/patches.\emph{N}}. You can remove the extra head using
jerojasro@336 768 \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a} \hgxopt{mq}{qpop}{-n} patches.\emph{N}}
jerojasro@336 769 or \hgcmd{strip}. You can delete \sdirname{.hg/patches.\emph{N}} once
jerojasro@336 770 you are sure that you no longer need it as a backup.
jerojasro@336 771
jerojasro@336 772 \section{Identifying patches}
jerojasro@336 773
jerojasro@336 774 MQ commands that work with patches let you refer to a patch either by
jerojasro@336 775 using its name or by a number. By name is obvious enough; pass the
jerojasro@336 776 name \filename{foo.patch} to \hgxcmd{mq}{qpush}, for example, and it will
jerojasro@336 777 push patches until \filename{foo.patch} is applied.
jerojasro@336 778
jerojasro@336 779 As a shortcut, you can refer to a patch using both a name and a
jerojasro@336 780 numeric offset; \texttt{foo.patch-2} means ``two patches before
jerojasro@336 781 \texttt{foo.patch}'', while \texttt{bar.patch+4} means ``four patches
jerojasro@336 782 after \texttt{bar.patch}''.
jerojasro@336 783
jerojasro@336 784 Referring to a patch by index isn't much different. The first patch
jerojasro@336 785 printed in the output of \hgxcmd{mq}{qseries} is patch zero (yes, it's one
jerojasro@336 786 of those start-at-zero counting systems); the second is patch one; and
jerojasro@336 787 so on.
jerojasro@336 788
jerojasro@336 789 MQ also makes it easy to work with patches when you are using normal
jerojasro@336 790 Mercurial commands. Every command that accepts a changeset ID will
jerojasro@336 791 also accept the name of an applied patch. MQ augments the tags
jerojasro@336 792 normally in the repository with an eponymous one for each applied
jerojasro@336 793 patch. In addition, the special tags \index{tags!special tag
jerojasro@336 794 names!\texttt{qbase}}\texttt{qbase} and \index{tags!special tag
jerojasro@336 795 names!\texttt{qtip}}\texttt{qtip} identify the ``bottom-most'' and
jerojasro@336 796 topmost applied patches, respectively.
jerojasro@336 797
jerojasro@336 798 These additions to Mercurial's normal tagging capabilities make
jerojasro@336 799 dealing with patches even more of a breeze.
jerojasro@336 800 \begin{itemize}
jerojasro@336 801 \item Want to patchbomb a mailing list with your latest series of
jerojasro@336 802 changes?
jerojasro@336 803 \begin{codesample4}
jerojasro@336 804 hg email qbase:qtip
jerojasro@336 805 \end{codesample4}
jerojasro@336 806 (Don't know what ``patchbombing'' is? See
jerojasro@336 807 section~\ref{sec:hgext:patchbomb}.)
jerojasro@336 808 \item Need to see all of the patches since \texttt{foo.patch} that
jerojasro@336 809 have touched files in a subdirectory of your tree?
jerojasro@336 810 \begin{codesample4}
jerojasro@336 811 hg log -r foo.patch:qtip \emph{subdir}
jerojasro@336 812 \end{codesample4}
jerojasro@336 813 \end{itemize}
jerojasro@336 814
jerojasro@336 815 Because MQ makes the names of patches available to the rest of
jerojasro@336 816 Mercurial through its normal internal tag machinery, you don't need to
jerojasro@336 817 type in the entire name of a patch when you want to identify it by
jerojasro@336 818 name.
jerojasro@336 819
jerojasro@336 820 \begin{figure}[ht]
jerojasro@336 821 \interaction{mq.id.output}
jerojasro@336 822 \caption{Using MQ's tag features to work with patches}
jerojasro@336 823 \label{ex:mq:id}
jerojasro@336 824 \end{figure}
jerojasro@336 825
jerojasro@336 826 Another nice consequence of representing patch names as tags is that
jerojasro@336 827 when you run the \hgcmd{log} command, it will display a patch's name
jerojasro@336 828 as a tag, simply as part of its normal output. This makes it easy to
jerojasro@336 829 visually distinguish applied patches from underlying ``normal''
jerojasro@336 830 revisions. Figure~\ref{ex:mq:id} shows a few normal Mercurial
jerojasro@336 831 commands in use with applied patches.
jerojasro@336 832
jerojasro@336 833 \section{Useful things to know about}
jerojasro@336 834
jerojasro@336 835 There are a number of aspects of MQ usage that don't fit tidily into
jerojasro@336 836 sections of their own, but that are good to know. Here they are, in
jerojasro@336 837 one place.
jerojasro@336 838
jerojasro@336 839 \begin{itemize}
jerojasro@336 840 \item Normally, when you \hgxcmd{mq}{qpop} a patch and \hgxcmd{mq}{qpush} it
jerojasro@336 841 again, the changeset that represents the patch after the pop/push
jerojasro@336 842 will have a \emph{different identity} than the changeset that
jerojasro@336 843 represented the hash beforehand. See
jerojasro@336 844 section~\ref{sec:mqref:cmd:qpush} for information as to why this is.
jerojasro@336 845 \item It's not a good idea to \hgcmd{merge} changes from another
jerojasro@336 846 branch with a patch changeset, at least if you want to maintain the
jerojasro@336 847 ``patchiness'' of that changeset and changesets below it on the
jerojasro@336 848 patch stack. If you try to do this, it will appear to succeed, but
jerojasro@336 849 MQ will become confused.
jerojasro@336 850 \end{itemize}
jerojasro@336 851
jerojasro@336 852 \section{Managing patches in a repository}
jerojasro@336 853 \label{sec:mq:repo}
jerojasro@336 854
jerojasro@336 855 Because MQ's \sdirname{.hg/patches} directory resides outside a
jerojasro@336 856 Mercurial repository's working directory, the ``underlying'' Mercurial
jerojasro@336 857 repository knows nothing about the management or presence of patches.
jerojasro@336 858
jerojasro@336 859 This presents the interesting possibility of managing the contents of
jerojasro@336 860 the patch directory as a Mercurial repository in its own right. This
jerojasro@336 861 can be a useful way to work. For example, you can work on a patch for
jerojasro@336 862 a while, \hgxcmd{mq}{qrefresh} it, then \hgcmd{commit} the current state of
jerojasro@336 863 the patch. This lets you ``roll back'' to that version of the patch
jerojasro@336 864 later on.
jerojasro@336 865
jerojasro@336 866 You can then share different versions of the same patch stack among
jerojasro@336 867 multiple underlying repositories. I use this when I am developing a
jerojasro@336 868 Linux kernel feature. I have a pristine copy of my kernel sources for
jerojasro@336 869 each of several CPU architectures, and a cloned repository under each
jerojasro@336 870 that contains the patches I am working on. When I want to test a
jerojasro@336 871 change on a different architecture, I push my current patches to the
jerojasro@336 872 patch repository associated with that kernel tree, pop and push all of
jerojasro@336 873 my patches, and build and test that kernel.
jerojasro@336 874
jerojasro@336 875 Managing patches in a repository makes it possible for multiple
jerojasro@336 876 developers to work on the same patch series without colliding with
jerojasro@336 877 each other, all on top of an underlying source base that they may or
jerojasro@336 878 may not control.
jerojasro@336 879
jerojasro@336 880 \subsection{MQ support for patch repositories}
jerojasro@336 881
jerojasro@336 882 MQ helps you to work with the \sdirname{.hg/patches} directory as a
jerojasro@336 883 repository; when you prepare a repository for working with patches
jerojasro@336 884 using \hgxcmd{mq}{qinit}, you can pass the \hgxopt{mq}{qinit}{-c} option to
jerojasro@336 885 create the \sdirname{.hg/patches} directory as a Mercurial repository.
jerojasro@336 886
jerojasro@336 887 \begin{note}
jerojasro@336 888 If you forget to use the \hgxopt{mq}{qinit}{-c} option, you can simply go
jerojasro@336 889 into the \sdirname{.hg/patches} directory at any time and run
jerojasro@336 890 \hgcmd{init}. Don't forget to add an entry for the
jerojasro@336 891 \sfilename{status} file to the \sfilename{.hgignore} file, though
jerojasro@336 892
jerojasro@336 893 (\hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} does this for you
jerojasro@336 894 automatically); you \emph{really} don't want to manage the
jerojasro@336 895 \sfilename{status} file.
jerojasro@336 896 \end{note}
jerojasro@336 897
jerojasro@336 898 As a convenience, if MQ notices that the \dirname{.hg/patches}
jerojasro@336 899 directory is a repository, it will automatically \hgcmd{add} every
jerojasro@336 900 patch that you create and import.
jerojasro@336 901
jerojasro@336 902 MQ provides a shortcut command, \hgxcmd{mq}{qcommit}, that runs
jerojasro@336 903 \hgcmd{commit} in the \sdirname{.hg/patches} directory. This saves
jerojasro@336 904 some bothersome typing.
jerojasro@336 905
jerojasro@336 906 Finally, as a convenience to manage the patch directory, you can
jerojasro@336 907 define the alias \command{mq} on Unix systems. For example, on Linux
jerojasro@336 908 systems using the \command{bash} shell, you can include the following
jerojasro@336 909 snippet in your \tildefile{.bashrc}.
jerojasro@336 910
jerojasro@336 911 \begin{codesample2}
jerojasro@336 912 alias mq=`hg -R \$(hg root)/.hg/patches'
jerojasro@336 913 \end{codesample2}
jerojasro@336 914
jerojasro@336 915 You can then issue commands of the form \cmdargs{mq}{pull} from
jerojasro@336 916 the main repository.
jerojasro@336 917
jerojasro@336 918 \subsection{A few things to watch out for}
jerojasro@336 919
jerojasro@336 920 MQ's support for working with a repository full of patches is limited
jerojasro@336 921 in a few small respects.
jerojasro@336 922
jerojasro@336 923 MQ cannot automatically detect changes that you make to the patch
jerojasro@336 924 directory. If you \hgcmd{pull}, manually edit, or \hgcmd{update}
jerojasro@336 925 changes to patches or the \sfilename{series} file, you will have to
jerojasro@336 926 \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} and then
jerojasro@336 927 \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} in the underlying repository to
jerojasro@336 928 see those changes show up there. If you forget to do this, you can
jerojasro@336 929 confuse MQ's idea of which patches are applied.
jerojasro@336 930
jerojasro@336 931 \section{Third party tools for working with patches}
jerojasro@336 932 \label{sec:mq:tools}
jerojasro@336 933
jerojasro@336 934 Once you've been working with patches for a while, you'll find
jerojasro@336 935 yourself hungry for tools that will help you to understand and
jerojasro@336 936 manipulate the patches you're dealing with.
jerojasro@336 937
jerojasro@336 938 The \command{diffstat} command~\cite{web:diffstat} generates a
jerojasro@336 939 histogram of the modifications made to each file in a patch. It
jerojasro@336 940 provides a good way to ``get a sense of'' a patch---which files it
jerojasro@336 941 affects, and how much change it introduces to each file and as a
jerojasro@336 942 whole. (I find that it's a good idea to use \command{diffstat}'s
jerojasro@336 943 \cmdopt{diffstat}{-p} option as a matter of course, as otherwise it
jerojasro@336 944 will try to do clever things with prefixes of file names that
jerojasro@336 945 inevitably confuse at least me.)
jerojasro@336 946
jerojasro@336 947 \begin{figure}[ht]
jerojasro@336 948 \interaction{mq.tools.tools}
jerojasro@336 949 \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands}
jerojasro@336 950 \label{ex:mq:tools}
jerojasro@336 951 \end{figure}
jerojasro@336 952
jerojasro@336 953 The \package{patchutils} package~\cite{web:patchutils} is invaluable.
jerojasro@336 954 It provides a set of small utilities that follow the ``Unix
jerojasro@336 955 philosophy;'' each does one useful thing with a patch. The
jerojasro@336 956 \package{patchutils} command I use most is \command{filterdiff}, which
jerojasro@336 957 extracts subsets from a patch file. For example, given a patch that
jerojasro@336 958 modifies hundreds of files across dozens of directories, a single
jerojasro@336 959 invocation of \command{filterdiff} can generate a smaller patch that
jerojasro@336 960 only touches files whose names match a particular glob pattern. See
jerojasro@336 961 section~\ref{mq-collab:tips:interdiff} for another example.
jerojasro@336 962
jerojasro@336 963 \section{Good ways to work with patches}
jerojasro@336 964
jerojasro@336 965 Whether you are working on a patch series to submit to a free software
jerojasro@336 966 or open source project, or a series that you intend to treat as a
jerojasro@336 967 sequence of regular changesets when you're done, you can use some
jerojasro@336 968 simple techniques to keep your work well organised.
jerojasro@336 969
jerojasro@336 970 Give your patches descriptive names. A good name for a patch might be
jerojasro@336 971 \filename{rework-device-alloc.patch}, because it will immediately give
jerojasro@336 972 you a hint what the purpose of the patch is. Long names shouldn't be
jerojasro@336 973 a problem; you won't be typing the names often, but you \emph{will} be
jerojasro@336 974 running commands like \hgxcmd{mq}{qapplied} and \hgxcmd{mq}{qtop} over and over.
jerojasro@336 975 Good naming becomes especially important when you have a number of
jerojasro@336 976 patches to work with, or if you are juggling a number of different
jerojasro@336 977 tasks and your patches only get a fraction of your attention.
jerojasro@336 978
jerojasro@336 979 Be aware of what patch you're working on. Use the \hgxcmd{mq}{qtop}
jerojasro@336 980 command and skim over the text of your patches frequently---for
jerojasro@336 981 example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where
jerojasro@336 982 you stand. I have several times worked on and \hgxcmd{mq}{qrefresh}ed a
jerojasro@336 983 patch other than the one I intended, and it's often tricky to migrate
jerojasro@336 984 changes into the right patch after making them in the wrong one.
jerojasro@336 985
jerojasro@336 986 For this reason, it is very much worth investing a little time to
jerojasro@336 987 learn how to use some of the third-party tools I described in
jerojasro@336 988 section~\ref{sec:mq:tools}, particularly \command{diffstat} and
jerojasro@336 989 \command{filterdiff}. The former will give you a quick idea of what
jerojasro@336 990 changes your patch is making, while the latter makes it easy to splice
jerojasro@336 991 hunks selectively out of one patch and into another.
jerojasro@336 992
jerojasro@336 993 \section{MQ cookbook}
jerojasro@336 994
jerojasro@336 995 \subsection{Manage ``trivial'' patches}
jerojasro@336 996
jerojasro@336 997 Because the overhead of dropping files into a new Mercurial repository
jerojasro@336 998 is so low, it makes a lot of sense to manage patches this way even if
jerojasro@336 999 you simply want to make a few changes to a source tarball that you
jerojasro@336 1000 downloaded.
jerojasro@336 1001
jerojasro@336 1002 Begin by downloading and unpacking the source tarball,
jerojasro@336 1003 and turning it into a Mercurial repository.
jerojasro@336 1004 \interaction{mq.tarball.download}
jerojasro@336 1005
jerojasro@336 1006 Continue by creating a patch stack and making your changes.
jerojasro@336 1007 \interaction{mq.tarball.qinit}
jerojasro@336 1008
jerojasro@336 1009 Let's say a few weeks or months pass, and your package author releases
jerojasro@336 1010 a new version. First, bring their changes into the repository.
jerojasro@336 1011 \interaction{mq.tarball.newsource}
jerojasro@336 1012 The pipeline starting with \hgcmd{locate} above deletes all files in
jerojasro@336 1013 the working directory, so that \hgcmd{commit}'s
jerojasro@336 1014 \hgopt{commit}{--addremove} option can actually tell which files have
jerojasro@336 1015 really been removed in the newer version of the source.
jerojasro@336 1016
jerojasro@336 1017 Finally, you can apply your patches on top of the new tree.
jerojasro@336 1018 \interaction{mq.tarball.repush}
jerojasro@336 1019
jerojasro@336 1020 \subsection{Combining entire patches}
jerojasro@336 1021 \label{sec:mq:combine}
jerojasro@336 1022
jerojasro@336 1023 MQ provides a command, \hgxcmd{mq}{qfold} that lets you combine entire
jerojasro@336 1024 patches. This ``folds'' the patches you name, in the order you name
jerojasro@336 1025 them, into the topmost applied patch, and concatenates their
jerojasro@336 1026 descriptions onto the end of its description. The patches that you
jerojasro@336 1027 fold must be unapplied before you fold them.
jerojasro@336 1028
jerojasro@336 1029 The order in which you fold patches matters. If your topmost applied
jerojasro@336 1030 patch is \texttt{foo}, and you \hgxcmd{mq}{qfold} \texttt{bar} and
jerojasro@336 1031 \texttt{quux} into it, you will end up with a patch that has the same
jerojasro@336 1032 effect as if you applied first \texttt{foo}, then \texttt{bar},
jerojasro@336 1033 followed by \texttt{quux}.
jerojasro@336 1034
jerojasro@336 1035 \subsection{Merging part of one patch into another}
jerojasro@336 1036
jerojasro@336 1037 Merging \emph{part} of one patch into another is more difficult than
jerojasro@336 1038 combining entire patches.
jerojasro@336 1039
jerojasro@336 1040 If you want to move changes to entire files, you can use
jerojasro@336 1041 \command{filterdiff}'s \cmdopt{filterdiff}{-i} and
jerojasro@336 1042 \cmdopt{filterdiff}{-x} options to choose the modifications to snip
jerojasro@336 1043 out of one patch, concatenating its output onto the end of the patch
jerojasro@336 1044 you want to merge into. You usually won't need to modify the patch
jerojasro@336 1045 you've merged the changes from. Instead, MQ will report some rejected
jerojasro@336 1046 hunks when you \hgxcmd{mq}{qpush} it (from the hunks you moved into the
jerojasro@336 1047 other patch), and you can simply \hgxcmd{mq}{qrefresh} the patch to drop
jerojasro@336 1048 the duplicate hunks.
jerojasro@336 1049
jerojasro@336 1050 If you have a patch that has multiple hunks modifying a file, and you
jerojasro@336 1051 only want to move a few of those hunks, the job becomes more messy,
jerojasro@336 1052 but you can still partly automate it. Use \cmdargs{lsdiff}{-nvv} to
jerojasro@336 1053 print some metadata about the patch.
jerojasro@336 1054 \interaction{mq.tools.lsdiff}
jerojasro@336 1055
jerojasro@336 1056 This command prints three different kinds of number:
jerojasro@336 1057 \begin{itemize}
jerojasro@336 1058 \item (in the first column) a \emph{file number} to identify each file
jerojasro@336 1059 modified in the patch;
jerojasro@336 1060 \item (on the next line, indented) the line number within a modified
jerojasro@336 1061 file where a hunk starts; and
jerojasro@336 1062 \item (on the same line) a \emph{hunk number} to identify that hunk.
jerojasro@336 1063 \end{itemize}
jerojasro@336 1064
jerojasro@336 1065 You'll have to use some visual inspection, and reading of the patch,
jerojasro@336 1066 to identify the file and hunk numbers you'll want, but you can then
jerojasro@336 1067 pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files}
jerojasro@336 1068 and \cmdopt{filterdiff}{--hunks} options, to select exactly the file
jerojasro@336 1069 and hunk you want to extract.
jerojasro@336 1070
jerojasro@336 1071 Once you have this hunk, you can concatenate it onto the end of your
jerojasro@336 1072 destination patch and continue with the remainder of
jerojasro@336 1073 section~\ref{sec:mq:combine}.
jerojasro@336 1074
jerojasro@336 1075 \section{Differences between quilt and MQ}
jerojasro@336 1076
jerojasro@336 1077 If you are already familiar with quilt, MQ provides a similar command
jerojasro@336 1078 set. There are a few differences in the way that it works.
jerojasro@336 1079
jerojasro@336 1080 You will already have noticed that most quilt commands have MQ
jerojasro@336 1081 counterparts that simply begin with a ``\texttt{q}''. The exceptions
jerojasro@336 1082 are quilt's \texttt{add} and \texttt{remove} commands, the
jerojasro@336 1083 counterparts for which are the normal Mercurial \hgcmd{add} and
jerojasro@336 1084 \hgcmd{remove} commands. There is no MQ equivalent of the quilt
jerojasro@336 1085 \texttt{edit} command.
jerojasro@336 1086
jerojasro@336 1087 %%% Local Variables:
jerojasro@336 1088 %%% mode: latex
jerojasro@336 1089 %%% TeX-master: "00book"
jerojasro@336 1090 %%% End: