You are on page 1of 204

Control Distribuido de Revisiones con Mercurial

Bryan O’Sullivan Copyright c 2006, 2007 Bryan O’Sullivan. ´ Este material puede distribuirse unicamente bajo los t´ rminos y condiciones establecidos en la e versi´ n 1.0 de la Licencia de Publicaci´ n Abierta (OPL). Refi´ rase por favor al ap´ ndice D para o o e e encontrar el texto de la licencia. Este libro fue preparado a partir de rev fc4daaad6415, fechado 2009-02-10 00:28 -0500, usando Mercurial rev Mercurial Distributed SCM (version 1.0.1) .

´ Indice general
´ Indice general Prefacio 0.1. Este libro es un trabajo en progreso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0.2. Acerca de los ejemplos en este libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0.3. Colof´ n—este libro es Libre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o 1. Introducci´ n o 1.1. Acerca del control de revisiones . . . . . . . . . . . . . 1.1.1. ¿Por qu´ usar control de revisiones? . . . . . . . e 1.1.2. La cantidad de nombres del control de revisiones 1.2. Historia resumida del control de revisiones . . . . . . . . 1.3. Tendencias en el control de revisiones . . . . . . . . . . 1.4. Algunas ventajas del control distribuido de revisiones . . 1.4.1. Ventajas para proyectos de c´ digo abierto . . . . o 1.4.2. Ventajas para proyectos comerciales . . . . . . . 1.5. ¿Por qu´ elegir Mercurial? . . . . . . . . . . . . . . . . e 1.6. Comparaci´ n de Mercurial con otras herramientas . . . . o 1.6.1. Subversion . . . . . . . . . . . . . . . . . . . . 1.6.2. Git . . . . . . . . . . . . . . . . . . . . . . . . 1.6.3. CVS . . . . . . . . . . . . . . . . . . . . . . . . 1.6.4. Herramientas comerciales . . . . . . . . . . . . 1.6.5. Elegir una herramienta de control de revisiones . 1.7. Migrar de otra herramienta hacia Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
I

2 2 2 2 3 3 3 4 4 5 5 6 7 7 8 8 8 9 9 10 10 11 11 11 11 12 12 12 12 13 13 14 14 15 16 17

2. Una gira de Mercurial: lo b´ sico a 2.1. Instalar Mercurial en su sistema . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1. Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.2. Solaris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.3. Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.4. Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2. Arrancando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1. Ayuda integrada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3. Trabajar con un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1. Hacer una copia local de un repositorio . . . . . . . . . . . . . . . . . 2.3.2. Qu´ hay en un repositorio? . . . . . . . . . . . . . . . . . . . . . . . . e 2.4. Vistazo r´ pido al historial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a 2.4.1. Conjuntos de cambios, revisiones, y comunic´ ndose con otras personas a 2.4.2. Ver revisiones espec´ficas . . . . . . . . . . . . . . . . . . . . . . . . ı 2.4.3. Informaci´ n m´ s detallada . . . . . . . . . . . . . . . . . . . . . . . . o a
I

2.5. Todo acerca de las opciones para comandos . . . 2.6. Hacer y repasar cambios . . . . . . . . . . . . . 2.7. Grabar cambios en un nuevo conjunto de cambios 2.7.1. Definir un nombre de usuario . . . . . . 2.7.2. Escribir un mensaje de consignaci´ n . . . o 2.7.3. Escribir un buen mensaje de consignaci´ n o 2.7.4. Cancelar una consignaci´ n . . . . . . . . o 2.7.5. Admirar nuestro trabajo . . . . . . . . . 2.8. Compartir cambios . . . . . . . . . . . . . . . . 2.8.1. Jalar cambios desde otro repositorio . . . 2.8.2. Actualizar el directorio de trabajo . . . . 2.8.3. Empujar cambios a otro repositorio . . . 2.8.4. Compartir cambios a trav´ s de una red . . e 3. Una gira de Mercurial: fusionar trabajo 3.1. Fusionar l´neas de trabajo . . . . . . . . . . . . . ı 3.1.1. Conjuntos de cambios de frentes . . . . . 3.1.2. Hacer la fusi´ n . . . . . . . . . . . . . . o 3.1.3. Consignar los resultados de la fusi´ n . . . o 3.2. Fusionar cambios con conflictos . . . . . . . . . 3.2.1. Usar una herramienta gr´ fica para fusi´ n a o 3.2.2. Un ejemplo real . . . . . . . . . . . . . . 3.3. Simplificar el ciclo jalar-fusionar-consignar . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18 18 19 19 20 21 21 21 22 22 23 24 25 26 26 28 29 30 30 31 32 35 36 36 36 36 36 37 38 38 38 38 39 40 40 40 41 41 42 42 42 43 43 44 49 49 49 50 51

4. Tras bambalinas 4.1. Registro del historial de Mercurial . . . . . . . . . . . . ´ 4.1.1. Seguir el historial de un unico fichero . . . . . . 4.1.2. Administraci´ n de ficheros monitoreados . . . . o 4.1.3. Registro de informaci´ n del conjunto de cambios o 4.1.4. Relaciones entre revisiones . . . . . . . . . . . . 4.2. Almacenamiento seguro y eficiente . . . . . . . . . . . . 4.2.1. Almacenamiento eficiente . . . . . . . . . . . . 4.2.2. Operaci´ n segura . . . . . . . . . . . . . . . . . o 4.2.3. Recuperaci´ n r´ pida de datos . . . . . . . . . . o a 4.2.4. Identificaci´ n e integridad fuerte . . . . . . . . . o 4.3. Historial de revisiones, ramas y fusiones . . . . . . . . . 4.4. El directorio de trabajo . . . . . . . . . . . . . . . . . . 4.4.1. Qu´ pasa en una consignaci´ n . . . . . . . . . . e o 4.4.2. Creaci´ n de un nuevo frente . . . . . . . . . . . o 4.4.3. Fusi´ n de frentes . . . . . . . . . . . . . . . . . o 4.5. Otras caracter´sticas de dise˜ o interesantes . . . . . . . . ı n 4.5.1. Compresi´ n ingeniosa . . . . . . . . . . . . . . o 4.5.2. Reordenado de lectura/escritura y atomicidad . . 4.5.3. Acceso concurrente . . . . . . . . . . . . . . . . 4.5.4. Evitar movimientos de brazo . . . . . . . . . . . 4.5.5. Otros contenidos del estado de directorio . . . .

5. Mercurial d´a a d´a ı ı 5.1. C´ mo indicarle a Mercurial qu´ ficheros seguir . . . . . . . . o e 5.1.1. Nombramiento expl´cito e impl´cito de ficheros . . . . ı ı 5.1.2. Nota al margen: Mercurial trata ficheros, no directorios 5.2. C´ mo dejar de hacer seguimiento a un fichero . . . . . . . . . o
II

5.2.1. Al eliminar un fichero no se afecta su historial . . . . . . . . . . . . . . . . . . . . . 5.2.2. Ficheros perdidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.3. Nota al margen: ¿Por qu´ decirle expl´citamente a Mercurial que elimine un fichero? e ı ´ 5.2.4. Atajo util—agregar y eliminar ficheros en un solo paso . . . . . . . . . . . . . . . . 5.3. Copiar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.1. Resultados de copiar un fichero durante una fusi´ n . . . . . . . . . . . . . . . . . . o 5.3.2. ¿Por qu´ los cambios se reflejan en las copias? . . . . . . . . . . . . . . . . . . . . e 5.3.3. C´ mo hacer que los cambios no sigan a la copia? . . . . . . . . . . . . . . . . . . . o 5.3.4. Comportamiento de la orden “hg copy” . . . . . . . . . . . . . . . . . . . . . . . . 5.4. Renombrar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1. Renombrar ficheros y fusionar cambios . . . . . . . . . . . . . . . . . . . . . . . . 5.4.2. Cambios de nombre divergentes y fusi´ n . . . . . . . . . . . . . . . . . . . . . . . o 5.4.3. Cambios de nombre convergentes y fusi´ n . . . . . . . . . . . . . . . . . . . . . . o 5.4.4. Otros casos l´mite relacionados con renombramientos . . . . . . . . . . . . . . . . . ı 5.5. Recuperarse de equivocaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6. Colaborar con otros 6.1. La interfaz web de Mercurial . . . . . . . . . . . . . . . . . . . . . . . 6.2. Modelos de colaboraci´ n . . . . . . . . . . . . . . . . . . . . . . . . . o 6.2.1. Factores a tener en cuenta . . . . . . . . . . . . . . . . . . . . 6.2.2. Anarqu´a informal . . . . . . . . . . . . . . . . . . . . . . . . ı ´ 6.2.3. Un repositorio central unico . . . . . . . . . . . . . . . . . . . 6.2.4. Trabajo con muchas ramas . . . . . . . . . . . . . . . . . . . . 6.2.5. Ramas de caracter´sticas . . . . . . . . . . . . . . . . . . . . . ı 6.2.6. El tren de publicaci´ n . . . . . . . . . . . . . . . . . . . . . . o 6.2.7. El modelo del kernel Linux . . . . . . . . . . . . . . . . . . . . 6.2.8. Solamente jalar frente a colaboraci´ n p´ blica . . . . . . . . . . o u 6.2.9. Cuando la colaboraci´ n encuentra la administraci´ n ramificada o o 6.3. Aspectos t´ cnicos de la colaboraci´ n . . . . . . . . . . . . . . . . . . . e o 6.4. Compartir informalmente con “hg serve” . . . . . . . . . . . . . . . . 6.4.1. Cuestiones adicionales para tener en cuenta . . . . . . . . . . . 6.5. Uso del protocolo Secure Shell (ssh) . . . . . . . . . . . . . . . . . . . 6.5.1. C´ mo leer y escribir URLs de ssh . . . . . . . . . . . . . . . . o 6.5.2. Encontrar un cliente ssh para su sistema . . . . . . . . . . . . . 6.5.3. Generar un par de llaves . . . . . . . . . . . . . . . . . . . . . 6.5.4. Uso de un agente de autenticaci´ n . . . . . . . . . . . . . . . . o 6.5.5. Configurar el lado del servidor apropiadamente . . . . . . . . . 6.5.6. Compresi´ n con ssh . . . . . . . . . . . . . . . . . . . . . . . o 6.6. Servir sobre HTTP usando CGI . . . . . . . . . . . . . . . . . . . . . . 6.6.1. Lista de chequeo de la configuraci´ n del servidor web . . . . . o 6.6.2. Configuraci´ n b´ sica de CGI . . . . . . . . . . . . . . . . . . . o a 6.6.3. Compartir varios repositorios con un gui´ n CGI . . . . . . . . . o 6.6.4. Descarga de ficheros fuente . . . . . . . . . . . . . . . . . . . 6.6.5. Opciones de configuraci´ n en Web . . . . . . . . . . . . . . . . o 7. Nombres de ficheros y asociaci´ n de patrones o 7.1. Nombrado de ficheros simple . . . . . . . . . . . . . . . . . 7.2. Ejecuci´ n de comandos sin ning´ n nombre de fichero . . . . o u 7.3. Reportar que est´ pasando . . . . . . . . . . . . . . . . . . a 7.4. Uso de patrones para identificar ficheros . . . . . . . . . . . 7.4.1. Patrones glob estilo int´ rprete . . . . . . . . . . . . e 7.4.2. Asociaci´ n con patrones de expresiones regulares re o
III

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

51 51 52 52 52 53 54 54 54 55 56 56 57 57 58 59 59 59 60 60 60 61 63 63 63 64 64 65 65 65 65 66 66 67 67 67 69 69 69 70 72 73 73 75 75 75 77 77 77 78

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. .4. .2. . . No repita trabajo: fusi´ n entre ramas . .1. . . . . . . . . . 9. . .4. . e 9. . . . . . . . . . . . . . . . . . . . . .2. . . o 9. . . . . . . . u 7. . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . Hacer rollback una transacci´ n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9. . . o 9. Detecci´ n de conflictos de may´ sculas/min´ sculas o u u 7. . . . . . . . . . . . . . . . . . . .1. . . . . . IV .5. . . . . . . . .1. . . . . . . . . .7. . . . . . . ´ 8. . . . . . . . . . . . . . . .2. . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ignorar ficheros y directorios no deseados . . . .1. . . . Cuando las etiquetas permanentes son demasiado . . . . . . . . . . . 9. . . . . . . . . . . . . . . . . . . . . . . . 10. . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . Encontrar y arreglar sus equivocaciones 9. . . . . . .1. . . . . . . . .7. . . . . . . . . . . . . . . . . .1. . . . . . . . .6. . . . . . . .7. . . . .3. . . . . . .7. . . . . . . . .1.3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . Uso de la orden “hg bisect” . . . . . . Administraci´ n de versiones y desarrollo ramificado o 8.1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . Despu´ s de publicar. . 9. . . . . . . .4. . . . . . . . . . . . . Dar una entrada consistente . . . . . . . . . . e u 9. .1. . . .1. . . . . . . . . . . Dar un nombre persistente a una revisi´ n . . . . . . . . . 7. . . . 9. Administrar ramas en repositorios estilo gran cuadro . .3. . . . . . . . . .3. . . . . . . . . . . . . . Al encuentro de la fuente de un fallo . . . . . . . . . . . . . . . . . Revertir un cambio equivocado . . . . . . . 8. . . . . . . .2. . .5. . . . . . . . . . . . . . . . . . . . . . Nombres de ramas y fusiones . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . . . . . . . . . . . . . . . Filtrado de ficheros . . . . . . . . . . . . . . 9. . . . . . . . . . . . . . . . . . . . . . . . un roll back es futil . . . . . . . Borrar el historial local . . . . . . . . . . . . . . . . . . . . .5. . . .6.1. . . . . . . . . . .1. . . . . . . . . . . . . . . Arreglar un conflicto de may´ sculas/min´ sculas . . .2. . . . . M´ s control sobre el proceso de retroceso . . . . . 10. . . . . . . . Automatizar tanto como se pueda . . . . . . . . . . . . . . . . . . . . . . . . . . Erroneamente jalado . . . . . . . . . . . . . . . . . . . . .6. . El flujo de cambios—El gran cuadro vs. . . . . Errores al administrar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . 10. .6. . . . Solamente hay un roll back . 9. . . . . . . . . . . . . . . . . . . . . . 9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3.1. . . . . u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3.1. . . . . . . . . . . . .7. Tratamiento de varias ramas nombradas en un repositorio . . . . . . . 9. . . . . . . . Acotar la b´ squeda perezosamente . . . . . 8. . . . . . . . . . . . . . .1. . . . . . 9. .3. . . . . . . . . . . . Consejos para encontrar fallos efectivamente . . . . . . . . . . . . . . . . . . La consignaci´ n accidental . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . 9. . . . . u u . . . 9. . . . . . .3. . . . . . . . . . . . . . . 9. . . .5. .4.6. . . . Verificar los resultados . . . . . . . . . . . . . . . . . . . . . . 79 79 79 80 80 80 81 81 83 84 84 84 84 85 86 88 90 90 91 91 91 91 92 92 93 93 94 95 95 96 96 98 101 102 102 102 103 106 107 107 107 107 107 108 109 109 110 110 110 8. .4. . . . Manejo de eventos en repositorios mediante ganchos 10. . . . . . . . . el peque˜ o . . .2.2. . . . Tener en cuenta la interferencia entre fallos . . . e 9. . . . .6. . . . . . C´ mo protegerse de cambios que han “escapado” o 9. . . . . . 9. . . . . . . . . . . . . . . . . . . . .6. . . . . . . . . . . . . . . . . . . . . . . Retroceso de un cambio que no es la punta . . . . a 9. Los ganchos no se propagan . . . . Almacenamiento portable y seguro de repositorios 7. . . . . . .1. . . . . . . . . . . . 9. . . Tratar cambios consignados . . . . .2. .6. . . . . . . . . . . . . . . . . Por qu´ “hg backout” hace lo que hace . Manejo de conflictos entre etiquetas durante una fusi´ n o 8. .4. . . . . . . . . . . .7. . Ganchos y seguridad . . . . . . . . . . . .1. . . . . . . . . . . . . . . Retroceder un conjunto de cambios . . . . . . . . . . . 9. . . . . . .1. . Vistazo general de ganchos en Mercurial . Normalmente es util nombrar ramas . . . . . 7. . . . .3. . . . . . . . . . . . . . . . . . . . . . Retroceder el conjunto de cambios punta . . . .8. . . . . . . . Cambios que nunca debieron ocurrir . . . . . . .5. . . . . . . Los ganchos se ejecutan con sus privilegios de usuario 10. . . . . Nombrar ramas dentro de un repositorio . . o 8. . . . . . . . . . . . . . 9. . . . . . . 8. . . . . . . . . . 8. . 9. . . . . .3. . 8. . . . . . . n 8. o 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Limpieza despu´ s de la b´ squeda . . . . . . . Sensibilidad a may´ sculas . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . Etiquetas y clonado . . . . . . .2. . . .

. . . . . . . . . . . . . . . . . . . .9. . Referencia de ganchos . . . . . . . . . . .6. . .9.10. . . . . . . . . . .7. . Ejemplos de ganchos . . . . . . Valores de retorno de ganchos y control de actividades . .4. Palabras claves m´ s comunes en las plantillas a 11. . . . . . . o 10. . . Es posible hacer caso omiso de los ganchos . . . . .8. . . . . . . bugzilla—integraci´ n con Bugzilla . . .4. . . . . commit—luego de la creaci´ n de un nuevo conjunto de cambios . . .11. . . Comprobar espacios en blanco finales . .12. . a 11. . . . . . . . . . . . . . . . Ordenes que soportan estilos y plantillas . . . . . . . .8. . . . Controlar cu´ ndo puede llevarse a cabo una actividad . .2. . . . . . . . . . . o 10. . Ilustraci´ n del problema . . . . . . . . . . . . . . . . . . . Indicar a Mercurial que use un gancho interno . .3. . . . . . .1. . . . . . . . Ejecuci´ n de ganchos externos . . . . . . . . . . . . . . . . . . . . . . . . Escribir un gancho externo . . . . . . . .5. . . . . a 10. .5. . . . . . . . . . . . . . o 10. . . . Asegurarse de que ganchos cr´ticos sean ejecutados . . . . . . . . . .5.9.5. . . .tag—luego de etiquetar un conjunto de cambios . . . .9. . . . . . . . . . . .9. . . . . . . . . . . . . . . . . . . . . 11. . . . . Escoger c´ mo debe ejecutarse su gancho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9. . .5. . o 10. . . . o 10. . . . . o 10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pretag—antes de etiquetar un conjunto de cambios . . . . . .9. . . . . . . . . . . . . . . . . .9. 110 111 111 112 112 112 113 113 113 114 114 114 115 115 115 115 116 117 117 119 122 124 124 124 125 125 125 126 126 126 127 127 127 128 128 128 129 129 129 130 130 131 131 131 132 133 134 135 135 137 137 . . . . . n 10. . . . . . . . . o 10. Tutorial corto de uso de ganchos . . . . . . . . . . . . . . . . . . . . . . .8. . . .5. . .3. . . . . . Personalizar los mensajes de Mercurial 11. . . Averiguar de d´ nde vienen los conjuntos de cambios . . . . . . . . . . . .2.1. . . . 10. . . . . . . . . . . . . . a 11. . . . 10. . . . . . . . . . 10. . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Combinar filtros . . .5. . . . 11. . . . . . . . . . . . . . . . . Escribir sus propios ganchos . . . . changegroup—luego de a˜ adir conjuntos de cambios remotos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . precommit—antes de iniciar la consignaci´ n de un conjunto de cambios . . . . 10. . . . . . acl—control de acceso a partes de un repositorio .1. . . . . . . . . .2.update—luego de actualizar o fusionar el directorio de trabajo . . . . . . .10. . . . . . . . . .6. . .3. . .3. Uso de filtros con palabras claves . . . . . . . 10. .3. . .7. . . .1. . . . 10. . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . 10. . . . . . . . . . . . . . . . . . .2. . . . . . . . . . Ganchos adicionales . . . . .4. De plantillas a estilos . 11. . . . . . . . . . . . . . . . . .8. . . . . . . .1. . . . . . . . .9. . . . . . . . . .6. . . . . o 10. . .preupdate—antes de actualizar o fusionar el directorio de trabajo . . . . . . . . . . . . . . . . . . . ı 10. .6. . . . . . . . . . . . . . . . . .7. 10. . . . . . . . . . . . . . . . . .8. . . . . . . . . . . . . . .1. .9. . . . . . 10. . . . . . preoutgoing—antes de empezar la propagaci´ n de conjuntos de cambios . . . . . .6. 10. . . . . . . . . . . . . . . . . . o 10. . . . . . . . . . . . . . . .2. . . . . . .3. Sintaxis de ficheros de estilo . . . . . . 11. o 10. . . . . . . . . . . . . o 10. ´ 11. . . . . .5. . . . . .9. . . . . .2. . . . . . . . . . . .7. . .13. . . . . . . . .1. . . Par´ metros para ganchos . . . . . . . . . . .4. . . .4. . . . .9. . . . . . . . . . . . . . . . . . . . 10. . . . . . Secuencias de Control . . . . . . . a 10. . . . . . . . . . . . Ejecuci´ n de ganchos internos . . . .6. . . . . . . . . . . . . . . . . . . . . . . . . . . 11. . . . . . . . . . . Precauciones con ganchos pretxn en un repositorio de acceso compartido .7.4. . .9. . . . . . . . . . . Escribir un gancho interno . . . . . . . . V . . . . . . . . Escribir mensajes de consignaci´ n significativos . . . . . .2. . . .1. . . . . . . . . . Informaci´ n para escritores de ganchos .3. . . . . . . . . . 10. . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . .4. . 11. 10. . .7. . . prechangegroup—antes de empezar la adici´ n de conjuntos de cambios remotos .1. . . . . . . . Usar estilos que vienen con Mercurial . . . . .2.1. . . Llevar a cabo varias acciones por evento . . . . . Cuestiones b´ sicas de plantillas . . . . 10. . . . . . . . . . . 10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6. . . . . . . . Especificar un estilo predeterminado . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . pretxnchangegroup—antes de completar la adici´ n de conjuntos de cambios remotos o 10. 10. . 11. . . outgoing—luego de la propagaci´ n de los conjuntos de cambios . . . .9. . . . .5. . . . . . . . . . . notify—enviar notificaciones de correo electr´ nico . . o 10. . . . . . . . . . . . . . . . . . . incoming—luego de que un conjunto de cambios remoto es a˜ adido . . . . . o 10. . . . . . . . o 10. . . . . . . . . . .9. . . . . . . . . . . . . . . . . Los ficheros de estilo m´ s sencillos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . n 10. . .7. . . . .7. . . . . . . . .5. 10. . . . . . . . . . . . . . . . .pretxncommit—antes de completar la consignaci´ n de un nuevo conjunto de cambios o 10.

Dividir el fichero series . . . . . . . . . . . . . . . .2.5. . . . .6. . . . . . .14. . . . . . . . . . . . . . . . . . . . . . .2. . . . Reglas de MQ para aplicar parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. 12. . . . . . . . . . . . . . Introducir y sustraer muchos parches . a 12. . . . . . Trabajar con varios parches a la vez . . . . . . . . . . . . . . . . . . . . . . . . 11. . . . . . . . . . . . . . . . . . . . .14. 12. . . . . . . . . . . . . . . . . . . . . . . 12. . 12. . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . . . . Ejemplos de ficheros de estilos . . . . . . . . 13. . . . . . . . . 13. . . 12. . .Otra informaci´ n util . . . . . . . . . . . . . . . . . . . . . Estrategias para aplicar parches . . . . . . . . . . . . . . . . . . . . . . . . . . . a 12. . . . . . . . . . . .5. . . . . . . . Algunos detalles de la representaci´ n de parches . . . . . . . . . . .11. . . . . . . . . . . . . . . Refrescar un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . La prehistoria de las Colas de Mercurial . . . . . . .1. Podar el entorno de trabajo . . . . . . . . . . o 12. . . . . . . . . . . . . . . .15. . . . . . . . . . . . . . . . . .Detalles a tener en cuenta .8. . . . . . . . . . Crear un nuevo parche . . . . . 12. . maximizar el rendimiento de MQ . . . . . . . . . . 12. . . . . . . . . o 12. M´ s acerca de parches . . . . . . . . . . . .8. . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . 12. . .2. . . . . . . Comenzar a usar Colas de Mercurial . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . .2. . .14. . . . . . . . . . . . . . . . . Aplicar un parche tras otro y dar seguimiento .8. . . . . . . Usos avanzados de las Colas de Mercurial 13. . . . . Medidas de seguridad y c´ mo saltarlas . 12. . . .3. . . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10. . . 11. . . El problema de m´ ltiples objetivos .11. . . . . . Manipular la pila de parches . . . . . .12. . . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . . . . . . . .2. . . . . . 12. . . . . . . . . . . Manejo de descartes . . . . . . . . . . . . . . . . . . . .3. Identificar parches .1. . . . . . . El arte de escribir parches de backport . . .6. . . . 13. . . . . . . . . . . 12. . . . . . . . . . . . . . . . . . . . . . . . .7. Mantener la serie de parches . . . . . . . . . 12. . . Identificar equivocaciones en ficheros de estilo ´ 11. . . . . .6. . . . . . . . 13. . . . . . . . Pasar de trabajo con parches con Quilt hacia Colas de Mercurial 12. . . . . . . . . . . . . .8. . . . . . . . . . . . . . 12. . . . . . . . . . Cuidado con los difusos . . . . . . Aplicar parches condicionalmente mediante guardias . . . . . . . . . . . . . . . . . . . . . .6. . . . . . . . . .7. . . . . . . . . VI . . . . . . . . . . . . o ´ 12. .Otras herramientas para trabajar con parches . . . . .4. . . . . . . . . . . . . . . o 12. . .3. . . . . . . . . . . . . . .5. . .8. . . . . .Fusionar una porci´ n de un parche dentro de otro . . . . .11. . . . .5. . . . . . . . . . . . . .11. . . . . . . . . . . . . . . . . . . . . 12. . . .7. . . . .8. . . . . . . . .2. . . . . . . . . . . Controlar los guardias de un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . .Recetas de MQ . . . . . . . . . . . . . . 12.1. . . . . . . . .Combinar parches completos . . . . . . . .2. . . . .3. . . . . .1. . . . . . . . . .5. . . . . . . u 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14. . . . . . . . . . . . . . . . La gran ventaja de MQ . . . 12. . . . . . . . . . . . . . . .2. . . . . 12.1. . . . . . . . .6. La cantidad de franjas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 137 138 139 140 140 140 141 141 141 142 143 143 144 145 145 146 146 147 148 148 149 150 150 151 151 152 152 153 153 154 155 155 155 156 156 158 158 159 160 160 160 161 161 162 163 163 164 164 165 12. . . . . 12. . . . . .2. Trabajar parches con quilt . . . . . . . . . . . . . . . . Selecccionar los guardias a usar . . . . . . . . . . . . .Buenas pr´ cticas de trabajo con parches . . . . . . 13. . . . 13. . . .1. . . . .9. . . . . . .5. . . . . . . . . . . . . . .8. . . . . . . . .4. . . . . . . . . . . . . . .Diferencias entre quilt y MQ . . . . . . . . . . . . . . . . . . . . . . . . .5. .1.5. . . . . . .Soporte de MQ para repositorios de parches . . . Aproximaciones tentadoras que no funcionan adecuadamente 13.5. . . Identificar de forma unica un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Actualiar los parches cuando el c´ digo cambia . . . . . . . . . . . . . . .Administrar parches “triviales” . . . . . El problema de la administraci´ n de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mostrando salida parecida a Subversion . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . o 12. . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . .6. . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . .2. . . .4. . .6. .13. . . 12. .1. . . . . 13. . . . .4. . . . . . . . . . . . . . . . . . . . . . . 13.6. . . . . . . . . . . . . 12. o 12. . . . . . Entender los parches . . . . . . . . . . . . Administraci´ n de cambios con Colas de Mercurial o 12. . . . . . .Administrar parches en un repositorio . . . . . . . . . . . .

. . . . . . . . o 14. . . . . . . .2. . . . . . . Mejorar el desempe˜ o con la extensi´ n inotify . . . . “hg qpush”—introducir parches a la pila . . . . . . . . Anadir funcionalidad con extensiones 14. . . . . “hg diff”—imprime los cambios en el historial o el directorio actual . . . . .1. . . . . . . . . . . . . . . B. . . .1. . .1. . . . . . . . . . . . . .13. . . . . . . .5. . . . . . . . . . . . . . . . . . . B. . . . C. . . .9. . . . . . B. “hg qheader”—desplegar el encabezado/descripci´ n de un parche . . . . . 184 VII .1. . . . . . . . . . . . . . . . .4. . . . . . . B. .4. . . . . . . . . . . . n o 14. . . . . . . . . .11. . . . . . . . . . . . . . Enviar cambios v´a correo electr´ nico con la extensi´ n patchbomb ı o o 14. .14. . .1. . . . . . . . . .2. . . . B. . . . . . . . Referencia de ordenes MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o 14. .1. . . . . . . . . . . . .1. . . . . . . . . . . .1. . . . . . . .1. . . . Consejos y trucos . . . . . . Definici´ n de alias de comandos . . . . . . . . .9. . .2. . . . . . . . . . 165 ˜ 14. . . .1. . . . . .3.1. . . . . . . . .1. . . . . . . . . . .8. .´ 13. En Windows . . . . .17. . . . . . . . . . . . .1. . . . . . . . . “hg qimport”—importar el parche de un tercero en la cola . o B. . .1. . . . “hg qprev”—imprimir el nombre del parche anterior . “hg qtop”—imprime el nombre del parche actual . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . Referencia de ficheros de MQ . ´ B. . .1. . . . . Referencia de las Colas de Mercurial ´ B. . . . . . . . . . B. .4. . . . . . . . . . . . . .1. . . . . . . . . .1. B. . . . Instalar Mercurial desde las fuentes 184 C. “hg qnew”—crear un parche nuevo . . 165 13. . . . . . . . “hg qpop”—sustraer parches de la pila . . . . . . . . . . . . . . . 184 C. . . . . o B. . . . . . . 165 13. . . . . . . . . . . . . . . . B. . . . . .1. “hg qseries”—imprime la serie completa de parches . . . . . . . . . . . . . .12. . . . . . . . . . . . .2. . B. . . “hg qinit”—preparar un repositorio para trabajar con MQ . . . . .3. . . . . . . . . “hg qdelete”—eliminar un parche del fichero series . . . . . . . . . . . . . . . . .18. . . . . .2. . . . B. . . “hg qrename”—renombrar un parche . . . . . . . . . . . . . “hg qcommit”—consignar cambios en la cola del repositorio .3. “hg add”—A˜ ade ficheros en la pr´ xima consignaci´ n . . . . . . . . . . . .2. “hg qapplied”—imprimir los parches aplicados . . .1. . . . . . .2. . . . . . . . . . . . . B. . . . . . . . . . . . . . . A. 168 168 170 172 172 172 173 175 175 175 175 177 177 179 179 179 179 179 179 179 180 180 180 180 180 181 181 181 182 182 182 182 182 183 183 183 183 183 183 ´ A.6.1. . . . . . . . B. . . . . . . . . . . . . . . . .16. . . . El fichero series . n o o A. . . . . . . . . . . . . . . . . . . . . . “hg qunapplied”—imprimir los parches que a´ n no se han aplicado u B. . . . . . . .1. . . . . . . . . . . . .1. . . . . . . . . . . . . B. . . Organizar parches en directorios . . . . . . . . A. . . . B. . . . . . . . . . . . . . . . . . . . . . . . “hg strip”—remover una revisi´ n y sus descendientes . . . . . . . . . . . . . . B. . . . . B. . . . . . . . B. o B. .20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Options . . . “hg qrestore”—restaurar el estado almacenado de la cola . . . . o 14. . . . . . .1. . . . . . “hg qrefresh”—actualiza el ultimo parche aplicado . . . . . . . . . . . . . . . . . . . . . .9. . . Uso de la extensi´ n transplant para seleccionar . . . . . .15. . . . . . . . . . . . En un sistema tipo Unix . . . . . . . . . . . . . . . . . . . El fichero status . . . . . . . “hg qdiff”—imprimir la diferencia del ultimo parche aplicado . . . . . . . . . Soporte flexible de diff con la extensi´ n extdiff .1.9. . . .1. . . . . . . . . Consejos utiles para hacer desarrollo con MQ . . . . . .3.2. . . Ver el historial de un parche .21. . . . .1. . . . . ´ B. . .1. . . . . . . . . . . .1. . .1. . . . . . . . . . . . . .2. . . . . B. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . “hg qsave”—almacena el estado actual de la cola . . . . . .19. . . . . . . . “hg qnext”—imprimir el nombre del pr´ ximo parche . .7. . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . “hg qfold”—fusionar (“integrar”) varios parches en uno solo .2. . B. . . . . . . . . . . . . . .10. . . . . “hg version”—imprime la informaci´ n de versi´ n y derechos de reproducci´ n o o o A. . . . . . . . . . . . . . . Cambiar el comportamiento de las bombas de parches . . . . .1. . . Referencia de Ordenes A. . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . D. . Opciones de licencia . . . . . . .2. . . . . . . . . . . . . . . .4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bibliograf´a ı ´ Indice alfab´ tico e . . . .5. . . . . . . . . . D. . . . . . . Alcance de la licencia . . . . . . .6. . . . . . . . . . . . . . Requerimientos sobre trabajos modificados . . .1.D. . . . . . . . . a D. . . . . . . . . . . . . Licencia de Publicaci´ n Abierta o D. . . . . . .3. . . . 185 185 185 185 186 186 186 188 188 VIII . . . . . . . . . . . . . . . . o D. . . . . . . . . . . . . . . Requerimientos en versiones modificadas y no modificadas D. . . . . . . . . . . . . . . Recomendaciones de buenas pr´ cticas . . . . . . . . . . . . . . . . . . Derechos de reproducci´ n . . .

. . . . . . . . . . C´ mo verificar que MQ est´ habilitado .3. . . . .1. . . . . . . . . 4. . . . . . . . . . . 3. . . . . . . . . . . . . . . . . . . . . . 3. . . . . . . . . . . . . . 112 113 114 116 116 117 10.´ Indice de figuras 2. . Instant´ nea de un revlog. ı 6. . . . . . . . 136 o ´ 12. . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . Historial reciente divergente de los repositorios my-hello y my-new-hello . . . . . ı 9. . . . . . . . . 9. .2.1.7. . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fusi´ n manual de un retroceso . . . . . o a 12. . . . . . . 4. . Historial gr´ fico del repositorio hello . . . . . . . . . . . . . . . . . . Un gancho simple que se ejecuta al hacer la consignaci´ n de un conjunto de cambios o 10. . .4. 4. . . . . . . . . . . . . . . . . . . . . . . . . . . L´neas a a˜ adir en ˜/. . . . . . . . . . . . .2. . . . . . .4. . . . . . . . . . . . . . con deltas incrementales . . . . . . . . . . . . .5. . .6. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11. . ı o 10. 12. . . . . . . . . . 4. . . . Contenidos del repositorio despu´ s de jalar my-hello a my-new-hello . . . . . . . . . . . . . . . . . . . 4.1. . . . . . e Directorio de trabajo y repositorio durante la fusi´ n. . . . . . . . . . . . . . . . . . . . . 142 143 143 144 144 . . . .1. . . . . . . 3. . . .5. . . . . . . . . . o 10. . Definici´ n de un segundo gancho commit . . Usando kdiff3 para fusionar versiones de un fichero . . . . IX . . . . . . . . . . . Filtros de plantilla en acci´ n . . . . . . . . . . . . . . . . . . . . . . . . 4. . . . 4. . . . . 10. . 9. . . 12. 101 . . . . . . Un gancho que proh´be mensajes de consignaci´ n demasiado cortos . . . . . . . . 10. . . . . . . .1. . . . . . . . . . . . . . . . . . . .8.9. . . . . . . . . . . . . . . Un gancho simple que revisa si hay espacios en blanco finales . . . . . .5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .hgrc para habilitar la extensi´ n MQ ı n o 12. a 3. . . . . . . Uso sencillo de las ordenes diff y patch . . . . . . . . . . . . .4. . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . 9. . Crear un nuevo parche . . . . . . . . . . . .1. . . . . . . . . y consignaci´ n consecuente o o Cambios con conflictos a un documento . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . .6. . . Retroceso automatizado de un cambio a algo que no es la punta con la orden “hg backout” Retroceso usando la orden “hg backout” . . . . . . . . Despu´ s de una consignaci´ n hecha mientras se usaba un conjunto de cambios anterior e o Fusi´ n de dos frentes . o 5. . . . . . . .4. . . . . . . Simular un directorio vac´o con un fichero oculto . . . . . . . . . . . . .2. . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . o . . Template keywords in use .4. . . . . . 4. . . .5. . . . . . . . . 4. . . . . . . . . . . . . . a . . 100 . . . . El directorio de trabajo obtiene nuevos padres luego de una consignaci´ n . . . . . . . . . . . . . . . . 133 11. . . . . . o El directorio de trabajo. . . . . . . 98 . . . . . . . . . 97 . .2. El directorio de trabajo puede tener dos padres . . . . . . . . . . . . . . . . . . . . . . . . Retroceso de un cambio con la orden “hg backout” . .3. . . . . . . . actualizado a un conjunto de cambios anterior . 15 27 28 29 31 32 37 37 39 45 46 46 47 47 48 50 63 Relaci´ n entre ficheros en el directorio de trabajo y ficheros de registro en el repositorio o Relaciones entre metadatos . . . .3. . . . Ramas de Caracter´sticas . . . . . . . . . . . . . . . 3. . . . . . . . . . . . . . . . Preparar un repositorio para usar MQ . . . . Uso del gancho pretxncommit para controlar consignaciones . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . Un mejor gancho para espacios en blanco finales . . . . .

. . . ı ´ 12.13. . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . . . . . 12. . . .15. Refrescar un parche muchas veces para acumular cambios . Entender la pila de parches con “hg qseries” y “hg qapplied” 12. . . . . . . . . . . Aplicar un parche despu´ s del primero . . . . . . . . . .Pushing all unapplied patches . . . . . . . . . .11. . . . . .14. . .Las ordenes diffstat. . . . 12. . . . . 145 146 147 148 148 149 149 150 154 156 1 . . . . . . . . . . . . . . . . . . . . . . .6. . . filterdiff. . . . . . Refrescar un parche . . . . . . . . . . . . . . . y lsdiff . . . . . . . . . . . . . . . . . .Parches aplicados y no aplicados en la pila de parches de MQ . . . . . . . . .10. . . . . . 12. . . . . . . . . . . . . . . . . . . . . . . . .Modificar la pila de parches aplicados .8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . 12. . . .12. . .9. . . . . . . . . . .Uso de las caracter´sticas de etiquetamiento al trabajar con MQ . . . . e 12. . . . . . . . . . . . . . . . . .7. . . . . . . . . . . . . . . . . . .Crear un parche a la fuerza . . . . . . . . . . . . . . .12. . . . . . . . . .

todos los scripts de ejemplo son ejecutados autom´ ticamente. Cada vez que una copia del libro es construida desde su c´ digo fuente. y sin embargo escala a las demandas de retadores ambientes reales donde muchas otras herramientas de control de revisiones fallan. Cada ejemplo est´ “en directo”—cada uno es o a realmente el resultado de un script de shell que ejecuta los comandos de Mercurial que usted ve. o As´ que cuando usted lea los ejemplos. Colof´ n—este libro es Libre o Este libro est´ licenciado bajo la Licencia de Publicaci´ n Abierta. varios commits consecutivos en un ejemplo pueden aparecer como habiendo ocurrido durante el mismo segundo. Usted puede ver esto en el ejemplo bisect en la secci´ n 9. y es producido en su totalidad usando herramiena o A tas de Software Libre. no le d´ mucha importancia a las fechas o horas que vea en las salidas de ı e los comandos. mis scripts automatizados de ejemplos ejecutan muchos comandos en un segundo. en http://hg. las ilustraciones son dibujadas y generadas con Inkscape.1. Como un ejemplo de esto. Si yo actualizo la versi´ n de Mercurial o o que estoy documentando. Estoy escribiendo este libro acerca de control de revisiones distribuido porque creo que es un tema importante que merece una gu´a de campo.serpentine. El c´ digo fuente completo para este libro es publicado como un repositorio Mercurial. ı Donde un humano puede emitir no m´ s de un comando cada pocos segundos. con cualquier marca de tiempo resultante a correspondientemente separada. Este libro es un trabajo en progreso ´ Estoy liberando este libro mientras lo sigo escribiendo. 2 . y o a sus resultados actuales son comparados contra los resultados esperados. Pero tenga confianza en que el comportamiento que est´ viendo es consistente y reproducible. a 0.5. Acerca de los ejemplos en este libro Este libro toma un enfoque inusual hacia las muestras de c´ digo. y la salida de alg´ n comando cambia.2. que las fechas y horas que usted ver´ en los ejemplos tienden a n a estar “aplastadas” juntas de una forma que no ser´a posible si los mismos comandos fueran escritos por un humano. 0. ellos describen exactamente el comportamiento de la versi´ n de Mercurial que es mencionada en la portada del libro. o com/mercurial/book. y ha crecido hasta ahora gracias a a la voluntad que tiene la gente de salir y explorar territorios desconocidos. la construcci´ n falla.Prefacio El control distribuido de revisiones es un territorio relativamente nuevo. Es compuesto con LTEX. La ventaja de este enfoque es que los ejemplos siempre son precisos. Tambi´ n e espero que los lectores contribuir´ n como consideren adecuado. u o Hay una peque˜ a desventaja de este enfoque. Escog´ escribir acerca de Mercurial porque es la herramienta m´ s f´ cil para explorar ı ı a a el terreno. con la esperanza de que pueda ser util a otros. por ejemplo.3. a 0.

ahora manejan muchos ficheros y facilitan el trabajo en conjunto de varias personas. a Puede ayudarle a recuperarse de equivocaciones. Una herramienta de control o de revisiones que sea dif´cil de entender o usar impondr´ un costo alto.1. incluso puede ayudarle efectivamente a darse cuenta exactamente cu´ ndo se introdujo el error (para m´ s a a detalles ver la secci´ n 9. Llevar registro del historial y la evoluci´ n de su proyecto. a o cuando varias personas hacen cambios potencialmente incompatibles de forma casi simult´ nea. En las d´ cadas pasadas. De hecho. el programa le a ayudar´ a identificar y resolver tales conflictos.5). Acerca del control de revisiones El control de revisiones es el proceso de administrar diferentes versiones de una pieza de informaci´ n. a a u La mayor´a de estas razones son igualmente v´ lidas —por lo menos en teor´a— as´ est´ trabajando en un proyecto ı a ı ı e solo usted. ı a 3 . tendr´ una bit´ cora de qui´ n lo hizo. los programas de control de revisiones facilitan la colaboraci´ n. una herramienta realmente o buena. o con mucha gente. a a e e a e Cuando trabaja con m´ s personas. u Administrar manualmente muchas versiones de incluso s´ lo un fichero es una tarea propensa a errores. o Le ayudar´ a trabajar simult´ neamente. a pesar de o que hace bastante tiempo hay herramientas que ayudan en este proceso. y a manejar las diferencias entre m´ ltiples versiones de su proyecto.1. y de qu´ se trataba el cambio. lo graba con un a ı nuevo nombre que contiene un n´ mero. Algo fundamental acerca de lo pr´ ctico de un sistema de control de revisiones en estas dos escalas (“un hacker a solitario” y “un equipo gigantesco”) es c´ mo se comparan los beneficios con los costos. Por cada o cambio. el e alcance de las herramientas de control de revisiones ha ido aumentando considerablemente. para evitar hacer la tarea manualmente. cu´ ndo se hizo. Las mejores herramientas de control de revisiones de la actualidad no tienen problema con miles de personas trabajando en proyectos que consisten de cientos de miles de ficheros. 1. ¿Por qu´ usar control de revisiones? e Hay muchas razones por las cuales usted o su equipo desear´a usar una herramienta autom´ tica de control de ı a revisiones para un proyecto.1. Las primeras herramientas para automatizar el control de revisiones fueron pensadas para que un usuario administrara un solo fichero. puede revertirlo a una versi´ n previa a uno o muchos ficheros. cada uno mayor que el anterior. Por ejemplo.Cap´tulo 1 ı Introducci´ n o 1. Si aplica un cambio que posteriormente se evidencia como un error. En su forma o m´ s simple es algo que la mayor´a de gente hace a mano: cada vez que usted modifica un fichero. por qu´ se hizo.

2. Ninguna herramienta de control de revisiones puede salvar un proyecto mal administrado. CVS adquiri´ posteriormente la habilidad de operar sobre una o o conexi´ n de red. Historia resumida del control de revisiones La herramienta de control de revisiones m´ s antigua conocida es SCCS (Sistema de Control de C´ digo). a Por otra parte. impidiendo que otro pudiera modificar los ficheros en cuesti´ n sin la intervenci´ n del administrador. a Despu´ s en los ochenta. situaci´ n com´ n con SCCS y RCS. tan amplio que no hay un acr´ nimo o nombre unico. el historial o a ´ del proyecto est´ unicamente en el repositorio central. excluir´a la necesidad de usar una herramienta de control a ı de revisiones. 1. un “arreglo r´ pido” de una sola persona. Los espacios de trabajo de los clientes contienen unicamente a´ 4 . el costo de usar control de revisiones ni siquiera se ´ tiene en cuenta. puede aplicar el control de revisiones al proyecto m´ s peque˜ o con facilidad. a comienzos de los setentas (1970s). y requer´a que cada persona que trabajara en el proyecto tuviera acceso a un espacio compartido en un solo sistema. La ı o o gran innovaci´ n de CVS era que permit´a a los desarrolladores trabajar simult´ neamente de una forma m´ s o menos o ı a a independiente en sus propios espacios de trabajo. En este caso. o Control de Fuentes o Control de Versiones (VCS) Algunas personas aducen que estos t´ rminos tienen significados diversos. SCCS operaba sobre ficheros individuales. 1. Al mismo tiempo. pero en la pr´ ctica se sobreponen tanto que e a no hay una forma acordada o incluso adecuada de separarlos. pero la elecci´ n de o herramientas puede hacer una gran diferencia en la fluidez con la cual usted puede trabajar en un proyecto. Mercurial tiene alto desempe˜ o y su e n naturaleza peer-to-peer le permite escalar indoloramente para manejar grandes proyectos. el arbitramiento del acceso a los ficheros ı se hac´a con candados. y que posteriormente olvidara ı u quitarlos.2. cliente/servidor. ¿No es as´? ı ı ´ Mercurial soporta ambas escalas de de desarrollo de manera unica. A continuaci´ n o o presentamos un listado de nombres comunes y acr´ nimos que se podr´an encontrar: o ı Control de revisiones (RCS) Manejo de Configuraciones de Programas (SCM). La cantidad de nombres del control de revisiones ´ El control de revisiones es un campo amplio. La arquitectura de CVS es centralizada. Puede aprender lo b´ sico en pocos minutos. Era com´ n que la gente pusiera los candados a los ficheros. Ten´an que fusionar sus ediciones ı ı antes de consignar los cambios al repositorio central. escrito a o por Marc Rochkind en Bell Labs. puesto que sin el. Cada desarrollador ten´a una copia de o u ı todos los ficheros del proyecto y pod´a modificar sus copias independientemente. Brian Berliner tom´ los scripts originales de Grune y los reescribi´ en C.1. Al igual que SCCS.Un proyecto de quinientas personas es muy propenso a colapsar solamente con su peso inmediatamente sin una herramienta y un proceso de control de versiones. o administrac´ n de configuraciones o Administraci´ n de c´ digo fuente o o Control de C´ digo Fuente. el costo de usar una estar´a cerca del costo del proyecto. pero que renombr´ a CVS (Sistema Concurrente de Versiones). Los espacios de trabajo personales imped´an que los desarrolladores ı se pisaran las mangueras todo el tiempo. RCS requer´a que los desarrolladores trabajaran en ı ´ un unico espacio compartido y colocaran candados a los ficheros para evitar que varias personas los modificaran simult´ neamente. y a dado su bajo sobrecosto. que inicialmente llam´ cmt. ı Solamente una persona pod´a modificar un fichero en un momento dado. o o Walter Tichy desarroll´ una alternativa gratuita a SCCS a comienzos de los ochentas (1980s). llam´ a su programa o o RCS (Sistema de Control de Revisiones). porque casi seguramente. Su simplicidad a n ´ significa que no tendr´ que preocuparse por conceptos obtusos o secuencias de ordenes compitiendo por espacio a mental con lo que sea que realmente est´ tratando de hacer. el fracaso est´ casi garantizado. publicando en 1989 el c´ digo sobre el o o o cual se ha desarrollado la versi´ n moderna de CVS. Dick Grune us´ RCS como un bloque de construcci´ n para un conjunto de guiones de e o o l´nea de comando. dot´ ndolo de una arquitectura.

Es probablemente el sistema de control de revisiones m´ s extendido del planeta. y tiene una noci´ n integral a o de “confianza” para c´ digo de diversas fuentes. fue mucho m´ s all´ de las herramientas anteriores (y posteriores) de control de a a revisiones en varios aspectos innovadores. a A comienzos de los noventa (1990s). y administrando o o a e proyectos completos a la vez. Mientras que Monotone se enfocaba a evitar algunas fallas de dise˜ o de o n CVS con una arquitectura peer-to-peer. a M´ s o menos en forma simult´ nea Graydon Hoare comenz´ a trabajar en un ambicioso sistema distribuido de a a o control de versiones que llam´ Monotone. y han permitido que la gente distribuya sus datos de control de revisiones donde realmente se necesita. nacieron nuevos problemas. Las redes con poca estabilidad podr´an impedir que usuarios remotos se conectaran al servidor. La primera generaci´ n comenz´ administrando ficheros individuales en computadores por persona. Desde su versi´ n inicial. y pocos metadatos para indicar d´ nde est´ el servidor. Almacena o cambios simult´ neos a muchos ficheros de forma individual. Todos estos sistemas o ´ han eliminado la dependencia de un unico servidor central. es f´ cil desordenar un repositorio al renombrar ficheros o o ı a y directorios. Peor a´ n. En 2001. Algunas ventajas del control distribuido de revisiones A pesar de que las herramientas para el control distribuido de revisiones lleva varios a˜ os siendo tan robustas y n usables como la generaci´ n previa de sus contrapartes. escalar estas m´ quinas se convirti´ en un problema en proyectos realmente o a o grandes. se empez´ a evidenciar los problemas de CVS. Hay gran cantidad de situaciones en las cuales las herramientas distribuidas brillan frente a las centralizadas. en lugar de agruparlos como una operaci´ n unica y a o ´ at´ mica l´ gicamente. CVS ha tenido o a ´ un exito enorme.3. o o 1. TeamWare usaba SCCS. La colaboraci´ n a trav´ s de Internet ha cambiado las limitantes tecnol´ gicas o e o por la cuesti´ n de elecci´ n y consenso.) A medida que avanzaba la decada de los noventa. Las herramientas modernas pueden operar sin conexi´ n indefinidamente y o o o aut´ nomamente. o Mercurial naci´ en el 2005. gran rendimiento y escalabilidad para proyectos muy grandes. Algunos de sus aspectos de de dise˜ o fueron influenciados por Monotone. Un espacio de trabajo TeamWare contiene una copia completa del historial del proyecto. necesitando una conexi´ n de red solamente para sincronizar los cambios con otro repositorio. A pesar de que o o tales herramientas representaron un avance importante frente al control de revisiones manual. No maneja bien su jerarqu´a de ficheros. ı La generaci´ n actual de herramientas de control de revisiones es peer-to-peer por naturaleza. pero a˜ adi´ consignaciones at´ micas de varios ficheros. ı puesto que no pod´an guardar sus cambios. lo que hizo que su “umbral de dolor” para u o ı arreglar sus problemas arquitecturales fuera algo prohibitivo. Jim Blandy y Karl Fogel. no o a se separ´ del modelo centralizado cliente/servidor de CVS. Con la necesidad de ı comunicaci´ n frecuente con los servidores. mientras la gente se ha hecho familiar con las capacidades de sus herramientas y se ha visto e restringida por sus limitaciones. A medida que los proyectos crec´an. 5 .copias recientes de las versiones de los ficheros. Tendencias en el control de revisiones Ha habido una tendencia inconfundible en el desarrollo y uso de las herramientas de control de revisiones en las cuatro d´ cadas pasadas. Usa hashes criptogr´ ficos como identificadores. (CVS se basaba en RCS para el almacenamiento de su o historial. A medida que ı los proyectos de c´ digo abierto comenzaron a ofrecer acceso de s´ lo lectura de forma an´ nima a cualquiera. 1. algunas personas que usan las herramientas m´ s antiguas no o a se han percatado de sus ventajas. o n o o mejor manejo de espacios de nombres . comenzaron un proyecto ı para reemplazarlo con una herramienta con mejor arquitectura y c´ digo m´ s limpio. Sun MicroSystems desarrollo un temprano sistema distribuido de control de revisiones llamado TeamWare. su modelo de candados y la dependencia a un s´ lo computador los limit´ a equipos de trabajo peque˜ os y acoplados. pero Mero n curial se enfoca en la facilidad de uso. Subversion. TeamWare no tiene la noci´ n de repositorio central. la gente o o o sin permiso para consignar vio que no pod´an usar tales herramientas para interactuar en un proyecto de forma natural.4. dos desarrolladores que hab´an trabajado en CVS. El resultado. ı o ha ido creciendo en popularidad r´ pidamente. y otras caracter´sticas que lo hacen mejor que CVS. su c´ digo fuente es dif´cil de leer y mantener. o o n La segunda generaci´ n dej´ atr´ s esas limitaciones movi´ ndose a arquitecturas centradas en redes.

o Lo que las herramientas distribuidas hacen con respecto a las bifurcaciones. e Con esto usualmente se pierde algo o todo del historial de la revisi´ n de alguna de las partes. e injertar los cambios del otro equipo en el arbol de alguna manera.4. usted es de inmediato un par con la gente que se considera el “alma” del proyecto. La confiabilidad de su red afectar´ las herramientas distribuidas de una forma mucho menor que a las herramientas a centralizadas. No subestime el valor de una herramienta de respuesta r´ pida: Usted emplear´ mucho a a tiempo interactuando con su programa de control de revisiones. y que su ultima copia sea reciente y adem´ s funcione. se enmarcan en t´ rminos de bifurcaciones e y fusiones. el proceso t´ cnico de reconciliarse es doloroso. Usted tiene que e ´ decidir qu´ historial de revisiones va a “ganar”. algo a que es relativamente raro comparado con las operaciones locales. a a Por una raz´ n sencilla: Una herramienta centralizada necesita comunicarse por red para las operaciones m´ s usuales. o 1 N. Las herramientas distribuidas son indiferentes a los caprichos de su infraestructura de servidores. y se hace de forma muy manual. Lo que hacen las herramientas distribuidas es disminuir la posibilidad de una o bifurcaci´ n porque: o Eliminan la distinci´ n social que imponen las herramientas centralizadas: aqu´ lla entre miembros (personas con o e permiso de consignar) y forasteros (los que no tienen el permiso). a n Las bifurcaciones (forks) no son un problema Se ha mencionado que las herramientas de control distribuido de versiones albergan un riesgo a los proyectos de c´ digo abierto. Hasta entonces. Si usa un sistema centralizado y su servidor explota. debido a la replicaci´ n de metadatos en tantos lugares. no podr´ almacenar sus cambios y sus a modificaciones locales correr´ n el riesgo de da˜ arse cuando trate de actualizar su vista del repositorio. excepto por algunas o ´ ordenes muy limitadas. Con un sistema centralizado de ı control de revisiones. Con herramientas distribuidas. Una herramienta distribuida almacena todos sus metadatos localmente.Para un desarrollador individual. Con una ı a herramienta distribuida tiene tantas copias de seguridad disponibles como computadores de contribuidores. 6 . Una bio o furcaci´ n sucede cuando hay diferencias de opini´ n o actitud entre grupos de desarrolladores que desemboca en la o o decisi´ n de la imposibilidad de continuar trabajando juntos. porque todo lo que concierne al programa de o e o control de revisiones es una fusi´ n. hacer cambios y guardar su trabajo. Cada cambio que usted hace es potencialmente un punto de bifurcaci´ n. Cada parte toma una copia m´ s o menos completa del o a c´ digo fuente del proyecto y toma su propio rumbo. 1. es que las bifurcaciones son la unica ´ forma de desarrollar un proyecto. podr´a o a ı ´ nisiquiera darse cuenta. Ventajas para proyectos de c´ digo abierto o ´ Si descubre un proyecto de c´ digo abierto y decide que desea comenzar a trabajar en el. Si tiene colaboradores remotos en su equipo. entonces a aquello a lo que se refiere en el mundo del c´ digo abierto a una “bifurcaci´ n” se convierte o o puramente en una cuesti´ n social. comunicarse por red tiene un sobrecosto en a una herramienta centralizada.1. usando las mismas herramientas de la misma forma que ellos. usted debe usar el programa en un modo “s´ lo lectura” a menos que alguien le otorgue o permisos para consignar cambios en el repositorio central. La gran o fortaleza de esta aproximaci´ n es que las herramientas distribuidas de control de revisiones tiene que ser bueno al o fusionar las bifurcaciones. Usted no puede siquiera usar una herramienta centralizada sin conexi´ n de red. Si todas las porciones de trabajo que todos hacen. si sus conexi´ n cae mientras usted est´ trabajando. fork. o a debido a que los metadatos se almacenan en una sola copia en el servidor central. las herramientas distribuidas casi siempre son m´ s r´ pidas que las centralizadas. Facilitan la reconciliaci´ n despu´ s de una bifurcaci´ n social. Si ellos publican sus repositorios. con una herramienta centralizada. ojal´ los medios o a ´ f´sicos de su copia de seguridad sean confiables. porque las bifurcaciones son absolutamente fundamentales: pasan todo el tiempo. Lo unico que que no podr´ hacer es comunicarse con repositorios en otros computadores. puede ser importante. de nuevo. usted puede copiar inmediatamente el historial del proyecto. En contraste. todo el tiempo. Con todo lo dem´ s de la misma forma. o En algunas ocasiones los l´deres de las bifurcaciones reconcilian sus diferencias. puesto que se vuelve muy sencillo hacer una “bifurcaci´ n”1 del desarrollo del proyecto. del T. y ese proyecto usa una o herramienta de control distribuido de revisiones.

Mercurial se comporta a a muy bien con tareas de scripting y su limpieza interna junto con su implementaci´ n en Python permiten a˜ adir caraco n ´ ter´sticas f´ cilmente en forma de extensiones. por ejemplo. probar a diferentes arreglos de forma independiente y buscar de forma eficiente las fuentes de fallos en el historial y regresiones en los ambientes de los clientes. cada uno conteniendo decenas de miles de ficheros y centenas de megabytes de c´ digo fuente o Si la funcionalidad b´ sica de Mercurial no es suficiente para usted.2. Es f´ cil de acondicionar. es muy f´ cil extenderlo. a Es liviano.4. Dado que la carga en ı o un servidor central—si es que tiene uno—es muchas veces menor con una herramienta distribuida (debido a que los datos est´ n replicados en todas partes). hay muchas herramientas disponibles que pueden obtener el historial completo (aunque sea lentamente) y recrearlo en otro sitio que usted no controla. nı 1. deber´a estar listo para usar Mercurial en menos de cinco ı ´ minutos. ı a u desde ayudar a identificar fallos hasta mejorar su desempe˜ o. En todo caso. Quienes contribuyen y est´ n lejos de un repositorio central ver´ n una ejecuci´ n m´ s lenta de los comandos y tal vez menos confiabilidad. las respuestas t´picas de replicaci´ n tienden a ser costosas y complejas de instalar y administrar. todo sin necesidad de conectarse al servidor de su compa˜ ´a. y la replicaci´ n para balancear la carga se vuelve cosa de guiones. usted puede comenzar a trabajar con Mercurial en pocos momentos. puesto que: Es f´ cil de aprender y usar. de tal forma que no haya u comunicaci´ n redundante entre repositorios sobre enlaces de conexi´ n costosos. puesto ı que est´ impidiendo la fluidez de colaboraci´ n en lugar de prevenir que alguien se sienta impulsado a obtener una a o copia y hacer una bifurcaci´ n con su historial.5. Hay un buen n´ mero de extensiones utiles y populares en este momento. Escala de forma excelente. Las ordenes de Mercurial y su conjunto de caracter´sticas o a ı son uniformes y consistentes generalmente. Un sistema distribuido no padece estos problemas. La herramienta le permitir´ generar construcciones a la medida. Mejor a´ n. transferir cambios (localmente o por la red). a Si los sistemas de control de revisiones le son familiares. n 7 . puede colocar varios servidores autorizados. Si no. a o Si tiene un empleado en el campo. Mercurial buscar ser ligero y no incomodar en su camino combinando poca sobrecarga cognitiva con a operaciones asombrosamente r´ pidas. o o Los sistemas de control de revisiones distribuidos tienden a ser poco escalables. Crear nuevos camn bios y ramas. y basta con que siga unas pocas reglas generales en lugar de un mont´ n o de excepciones. En un proyecto peque˜ o. y las operaciones relacionadas con el estado y el historial son r´ pidas.Algunas personas se resisten a las herramientas distribuidas porque desean mantener control completo sobre sus proyectos. y usted publica sus repositorios de CVS o Subversion. se beneficiar´ grandemente de un sistema distribuido de control de versiones a al resolver problemas en el sitio del cliente. si este es su parecer. a a o a Los sistemas de control de revisi´ n comerciales intentan amortiguar estos problemas con adiciones de replicaci´ n o o remota que usualmente son muy costosos y complicados de administrar. o 1. Ventajas para proyectos comerciales Muchos proyectos comerciales tienen grupos de trabajo distribuidos alrededor del globo. uno por sitio. un solo servidor econ´ mico puede tratar las necesidades de equipos mucho a o m´ s grandes. Siendo as´ un control ilusorio. De nuevo. y creen que las herramientas centralizadas les dan tal control. a La utilidad de Mercurial no se limita a proyectos peque˜ os: est´ siendo usado por proyectos con centenas de miles n a de contribuyentes. ¿Por qu´ elegir Mercurial? e ´ Mercurial cuenta con un conjunto unico de propiedades que lo hacen una elecci´ n particularmente buena como o sistema de control de revisiones. s´ lo va a tomar unos pocos minutos m´ s. No es inusual que costosos sistemas centralizados caigan ante la carga combinada de unas cuantas docenas de usuarios concurrentes.

1.6.

Comparaci´ n de Mercurial con otras herramientas o

Antes de leer, por favor tenga en cuenta que esta secci´ n necesariamente refleja mis propias experiencias, intereses o y (tengo que decirlo) mis preferencias. He usado cada una de las herramientas de control de versiones listadas a continuaci´ n, y en muchos casos por varios a˜ os. o n

1.6.1.

Subversion

Subversion es una herramienta de control de revisiones muy popular, desarrollada para reemplazar a CVS. Tiene una arquitectura centralizada tipo cliente/servidor. Subversion y Mercurial tienen comandos con nombres similares para hacer las mismas operaciones, por lo que si le son familiares en una, ser´ sencillo aprender a usar la otra. Ambas herramientas son portables en todos los sistemas a operativos populares. Antes de la versi´ n 1.5, Subversion no ten´a soporte para fusiones. En el momento de la escritura, sus capcidades o ı para llevar cuenta de las funciones son nuevas, complicadas y poco estables2 . Mercurial tiene una ventaja considerable en desempe˜ o sobre Subversion en cualquier operaci´ n de control de n o revisiones que yo haya medido. He medido sus ventajas con factores desde dos hasta seis veces comparando con ale a a macenamiento de ficheros ra local Subversion 1.4.3, el cual es el m´ todo de acceso m´ s r´ pido. En los escenarios m´ s realistas incluyendo almacenamiento con la red de por medio, Subversion se encuentra en desventaja a´ n mayor. a u ´ Dado que casi todas las ordenes de Subversion deben tratar con el servidor y Subversion no tiene utilidades de replicaci´ n adecuadas, la capacidad del servidor y el ancho de banda se convierten en cuellos de botella para proyectos o modestamente grandes. Adicionalmente, Subversion tiene un sobrecosto considerable en almacenamiento para evitar transacciones por red en algunas operaciones, tales como encontrar ficheros modificados (status) y desplegar informaci´ n frente a la o revisi´ n actual (diff). Como resultado, la copia de trabajo de Subversion termina siendo del mismo tama˜ o o m´ s o n a grande que un repositorio de Mercurial y el directorio de trabajo, a pesar de que el repositorio de Mercurial contiene el historial completo del proyecto. Subversion tiene soporte amplio de otras herramientas. Mercurial por ahora est´ bastante atr´ s en este aspecto. a a Esta diferencia est´ disminuyendo, y algunas de las herramientas GUI3 , eclipsan sus equivalentes de Subversion. Al a igual que Mercurial, Subversion tiene un excelente manual de usuario. Dado que Subversion no almacena el historial de revisiones en el cliente, es muy bueno para administrar proyectos que tienen muchos ficheros binarios grandes y opacos. Si consigna cincuenta revisiones de un fichero de 10MB que no es comprimible, el esapacio en el cliente de Subversion se mantendr´ constante mientras que el espacio usado a por cualquier Sistema Distribuido de Control de Revisiones crecer´ r´ pidamente en proporci´ n con el n´ mero de a a o u revisiones, debido a que las diferencias entre cada revisi´ n es grande. o Adicionalmente, generalmente es dif´cil o m´ s bien, imposible mezclar diferentes versiones de un fichero binario. ı a La habilidad de Subversion para permitirle al usuario poner una cerradura a un fichero, de modo que tenga un permiso exclusivo para consignar cambios, puede ser una ventaja significativa en un proyecto donde los ficheros binarios sean usados ampliamente. Mercurial puede importar el historial de revisiones de un repositorio de Subversion. Tambi´ n puede exportar el e historial de revisiones a un repositorio de Subversion. De esta forma es sencillo “dar un vistazo” y usar Mercurial y Subversion en paralelo antes de decidirse a dar el paso. La conversi´ n del historial es incremental, de modo que o puede aplicar una conversi´ n inicial, y despu´ s conversiones peque˜ as y adicionales posteriormente para traer nuevos o e n cambios.

1.6.2.

Git

Git es una herramienta distribuida de control de revisiones desarrollada para administrar el arbol del kernel de Linux. Al igual que Mercurial los principios de su dise˜ o fueron influenciados por Monotone. n
3 N. 2 N.

del T. buggy del T. Interfaz de Usuario Gr´ fica a

8

´ ´ Git tiene un conjunto de ordenes muy grande; en la versi´ n 1.5.0 ofrece 139 ordenes individuales. Tiene cierta o reputaci´ n de ser dif´cil de aprender. Comparado con Git, Mercurial tiene un fuerte enfoque hacia la facilidad. o ı En t´ rminos de rendimiento, Git es extremadamente r´ pido. En muchos casos, es m´ s r´ pido que Mercurial, por lo e a a a menos en Linux, mientras que Mercurial se comporta mejor en otras operaciones. De todas maneras en Windows, el desempe˜ o y el nivel general de soporte que ofrece Git, al momento de la escritura, est´ bastante atr´ s de Mercurial. n a a Mientras que el repositorio de Mercurial no requiere mantenimiento, el repositorio de Git requiere frecuentes “reempaquetados” de sus metadatos. Sin estos, el desempe˜ o se degrada y el uso de espacio crece r´ pidamente. Un n a servidor que contenga repositorios de Git que no sean reempacados rigurosa y frecuentemente requerir´ trabajo ina tenso de disco durante las copias de seguridad, y ha habido situaciones en copias de seguridad diaria que toman m´ s a de 24 horas como resultado. Un repositorio reci´ n reempacado de Git es un poco m´ s peque˜ o que un repositorio de e a n ´ Mercurial, pero un repositorio sin reempacar es varios ordenes de magnitud m´ s grande. a ´ El coraz´ n de Git est´ escrito en C. Muchas ordenes de Git est´ n implementadas como guiones de l´nea de coo a a ı mandos o de Perl y la calidad de esos guiones var´a ampliamente. He encontrado muchas situaciones en las cuales los ı guiones no tuvieron en cuenta la presencia de errores que podr´an haber sido fatales. ı Mercurial puede importar el historial de revisiones de un repositorio de Git.

1.6.3.

CVS

CVS es probablemente la herramienta de control de revisiones m´ s ampliamente usada en el planeta. Debido a su a edad y su poca pulcritud interna, ha sido ligeramente mantenida en muchos a˜ os. n Tiene una arquitectura centralizada cliente/servidor. No agrupa cambios relacionados en consignaciones at´ micas, o pemitiendo que con facilidad la gente “rompa la construcci´ n”: una persona puede consignar exit´ samente parte del o o cambio y estar bloqueada por la necesidad de una mezcla, forzando a otras personas a ver solamente una porci´ n del o trabajo que estaban buscando hacer. Esto afecta tambi´ n la forma como usted trabaja con el historial del proyecto. Si e quiere ver todas las modificaciones que alguien hizo como parte de una tarea, necesitar´ inspeccionar manualmente a las descripciones y las marcas de tiempo de cambio de cada fichero involucrado (esto, si usted saber cu´ les eran tales a ficheros). CVS tiene una noci´ n confusa de etiquetas y ramas que yo no tratar´a incluso de describir. No soporta renomo ı bramiento de ficheros o directorios adecuadamente, facilitando el corromper un repositorio. Casi no tiene chequeo de consistencia interna, por lo tanto es casi imposible identificar por que o c´ mo se corrompi´ un repositorio. Yo no o o recomendar´a un repositorio de CVS para proyecto alguno, ni existente ni nuevo. ı Mercurial puede importar el historial de revisiones de CVS. De todas maneras hay ciertas precauciones que aplican; las cuales tambi´ n son necesarias para cualquier herramienta importadora de historial de CVS. Debido a la falta e de atomicidad de cambios y el no versionamiento de la jerarqu´a del sistema de ficheros, es imposible reconstruir ı completamente el historial de CVS con precisi´ n; hay cierto trabajo de conjetura involucrado y los renombramientos o tampoco se mostrar´ n. Debido a que gran parte de la administraci´ n avanzada de CVS tiene que hacerse manualmente a o y por lo tanto es proclive al error, es com´ n que los importadores de CVS encuentren muchos problemas con reposiu torios corruptos (marcas de tiempo totalmente desubicadas y ficheros que han permanecido con candados por m´ s de a una d´ cada son dos de los problemas menos interesantes de los que puedo retomar de mi experiencia personal). e Mercurial puede importar el historial de revisiones de un repositorio CVS.

1.6.4.

Herramientas comerciales

Perforce tiene una arquitectura centralizada cliente/servidor sin almacenamiento de dato alguno de cach´ en el e lado del cliente. A diferencia de las herramientas modernas de control de revisiones, Perforce requiere que un usuario ejecute un comando para informar al servidor acerca de todo fichero que se vaya a editar. El rendimiento de Perforce es muy bueno para equipos peque˜ os, pero se degrada r´ pidamente cuando el n´ mero n a u de usuarios va m´ s all´ de pocas docenas. Instalaciones modestamente grandes de Perforce requiere la organizaci´ n a a o de proxies para soportar la carga que sus usuarios generan.

9

1.6.5.

Elegir una herramienta de control de revisiones

´ Con la excepci´ n de CVS, toda las herramientas que se han listado anteriormente tienen fortalezas unicas que las o ´ hacen valiosas de acuerdo al tipo de trabajo. No hay una unica herramienta de control de revisiones que sea la mejor en todas las situaciones. Por ejemplo, Subversion es una buena elecci´ n para trabajar con edici´ n frecuente de ficheros binarios, debido a o o su naturaleza centralizada y soporte para poner candados a ficheros. Personalmente encuentro las propiedades de simplicidad, desempe˜ o, y buen soporte de fusiones de Mercurial una n combinaci´ n llamativa que ha dado buenos frutos por varios a˜ os. o n

1.7.

Migrar de otra herramienta hacia Mercurial

Mercurial viene con una extensi´ n llamada convert, que puede importar historiales de revisiones de forma increo mental desde varias herramientas de control de revisiones. Por “incremental”, quiero decir que puede migrar toda el historial de un proyecto en una primera instancia y despu´ s volver a ejecutar la migraci´ n posteriormente para obtener e o los nuevos cambios que han sucedido despu´ s de la migraci´ n inicial. e o A continuaci´ n presentamos las herramientas de revisiones que soporta el comando convert: o Subversion CVS Git Darcs Adicionalmente, convert puede exportar cambios de Mercurial hacia Subversion. Lo que hace posible probar Subversion y Mercurial en paralelo antes de lanzarse a un migraci´ n total, sin arriesgarse a perder trabajo alguno. o El comando “hg convert” es sencillo de usar. Basta con apuntarlo hacia la ruta o el URL del repositorio fuente, opcionalmente darle el nombre del nombre del repositorio destino y comenzar´ a hacer su trabajo. Despu´ s de la a e conversi´ n inicial, basta con invocar de nuevo el comando para importar cambios nuevos. o

10

Cap´tulo 2 ı

Una gira de Mercurial: lo b´ sico a
2.1. Instalar Mercurial en su sistema

Hay paquetes binarios precompilados de Mercurial disponibles para cada sistema operativo popular. Esto hace f´ cil empezar a usar Mercurial en su computador inmediatamente. a

2.1.1.

Linux

Dado que cada distribuci´ n de Linux tiene sus propias herramientas de manejo de paquetes, pol´ticas, y ritmos o ı de desarrollo, es dif´cil dar un conjunto exhaustivo de instrucciones sobre c´ mo instalar el paquete de Mercurial. La ı o versi´ n de Mercurial que usted tenga a disposici´ n puede variar dependiendo de qu´ tan activa sea la persona que o o e mantiene el paquete para su distribuci´ n. o Para mantener las cosas simples, me enfocar´ en instalar Mercurial desde la l´nea de comandos en las distribuciones e ı de Linux m´ s populares. La mayor´a de estas distribuciones proveen administradores de paquetes gr´ ficos que le a ı a permitir´ n instalar Mercurial con un solo clic; el nombre de paquete a buscar es mercurial. a Debian apt-get install mercurial 1 Fedora Core yum install mercurial 1 Gentoo emerge mercurial 1 OpenSUSE yum install mercurial 1 Ubuntu El paquete de Mercurial de Ubuntu est´ basado en el de Debian. Para instalarlo, ejecute el siguiente comando. a
1

apt-get install mercurial El paquete de Mercurial para Ubuntu tiende a atrasarse con respecto a la versi´ n de Debian por un margen de o tiempo considerable (al momento de escribir esto, 7 meses), lo que en algunos casos significar´ que usted puede a encontrarse con problemas que ya habr´ n sido resueltos en el paquete de Debian. a

2.1.2.

Solaris

SunFreeWare, en http://www.sunfreeware.com, es una buena fuente para un gran n´ mero de paquetes compiu lados para Solaris para las arquitecturas Intel y Sparc de 32 y 64 bits, incluyendo versiones actuales de Mercurial. 11

com. sudo port install mercurial.com> and others This is free software. Look at the help text for the pull command for important details about ssh:// URLs. 2.2. Esto es f´ cil de hacer.1. o o 1 2 3 4 5 6 $ hg version Mercurial Distributed SCM (version 1.2. usaremos el comando “hg version” para revisar si Mercurial est´ instalado adecuadamente. ı o a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ hg help init hg init [-e CMD] [--remotecmd CMD] [DEST] create a new repository in the given directory Initialize a new repository in the given directory.berkwood. Windows Lee Cantey publica un instalador de Mercurial para Windows en http://mercurial. Mac OS X Lee Cantey publica un instalador de Mercurial para Mac OS X en http://mercurial.1. Si est´ completamente atorado. it is created.com. Este paquete no tiene dependencias externas. deber´ hacer un trabajo adicional de configuraci´ n. XXX Terminar a o esto. Este paquete funciona en tanto en Macs basados en Intel como basados en PowerPC. It is possible to specify an ssh:// URL as the destination. the current directory is used. Ayuda integrada ´ Mercurial provee un sistema de ayuda integrada. junto con una descripci´ n de qu´ hace cada uno.4. 12 . Si usted desea compartir trabajo con usuarı ios de Unix. “simplemente funciona”.2.1. see the source for copying conditions.1) Copyright (C) 2005-2008 Matt Mackall <mpm@selenic. La a informaci´ n de la versi´ n que es impresa no es tan importante. lo que nos importa es si imprime algo en absoluto. Si usted tiene Fink. 2. Esto es invaluable para esas ocasiones en la que usted est´ atorado a tratando de recordar c´ mo ejecutar un comando. Si usa MacPorts. usted debe instalar una versi´ n compatible de Universal MacPython [BI]. directory does not exist. simplemente siga las o a instrucciones del sitio de Lee. Antes de que pueda usarlo. use sudo apt-get install mercurial-py25.berkwood.3.0. 2. simplemente ejecute “hg help”. not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. esto o a imprimir´ una breve lista de comandos. Arrancando Para empezar. Nota: La versi´ n de Windows de Mercurial no convierte autom´ ticamente los fines o a de l´nea entre estilos Windows y Unix. se imprime informaci´ n m´ s detallada. Tambi´ n es posible instalar Mercurial usando Fink o MacPorts. Si usted solicita ayuda sobre a o e un comando espec´fico (como abajo). dos administradores de paquetes gratuitos y pope ulares para Mac OS X. If the given If no directory is given. There is NO warranty.

Un repositorio clonado recuerda la ubicaci´ n de la que fue clonado. porque crea una copia id´ ntica de un repositorio existente. Este directorio contendr´ algunos ı a ficheros. u Lo que esto significa por ahora es que somos libres de experimentar con nuestro repositorio. es autocontenido e independiente. deber´amos tener un directorio local llamado hello. ni con ning´ n otro. Contiene su propia copia de los a ficheros y el historial de un proyecto. e e 13 . a menos que usted le indique que lo haga.15 16 17 18 19 20 options: -e --ssh --remotecmd specify ssh command to use specify hg command to run on the remote side use "hg -v help init" to show global options Para un nivel m´ s impresionante de detalle (que usted no va a necesitar usualmente) ejecute “hg help -v”. con la tranquilidad de saber que es una “caja de arena” privada que no afectar´ a nadie m´ s. Del t´ rmino “clonar” en ingl´ s. todo sucede dentro de un repositorio. o a o ı 2. usando bien sea la l´nea de comandos o su explorador de ficheros. Cada repositorio Mercurial est´ completo. a a 1 N. pero no se o comunica con ese repositorio.1. junto con un registro hist´ rico de los ficheros de ese proyecto. Este comando se llama “hg clone”1 .3.3.c Estos ficheros tienen el mismo contenido e historial en nuestro repositorio y en el repositorio que clonamos. y le indica a Mercurial que imprima m´ s informaci´ n de lo que har´a usualmente. es simplemente un arbol de directorios en su sistema a de ficheros que Mercurial trata como especial. Trabajar con un repositorio En Mercurial. del T. ı 2. 1 2 3 4 5 $ ls -l total 0 drwxr-xr-x 3 jerojasro jerojasro 120 Feb 10 18:23 hello $ ls hello Makefile hello. e 1 2 3 4 5 6 7 8 9 $ hg clone http://hg. 0 files unresolved ´ Si nuestro clonado tiene exito. o ´ No hay nada particularmente m´ gico acerca de un repositorio. El repositorio para un proyecto contiene todos los ficheros que ´ “pertenecen a” ese proyecto.serpentine. 0 files merged. 0 files removed. La opci´ n a o -v es la abreviaci´ n para --verbose.com/tutorial/hello destination directory: hello requesting all changes adding changesets adding manifests adding file changes added 5 changesets with 5 changes to 2 files updating working directory 2 files updated. Hacer una copia local de un repositorio Copiar un repositorio es s´ lo ligeramente especial. es mejor usar el comando integrado que Mercurial ofrece. Usted puede renombrar o borrar un repositorio en el momento que lo desee. Aunque usted podr´a usar un programa normal de copia de o ı ficheros para hacer una copia del repositorio.

y todos los ficheros y directorios que ı ´ coexisten con el est´ n en el directorio de trabajo.o file. 2.hg Makefile hello. es conocer su historial. Dentro de a la terminolog´a de Mercurial.com Fri Aug 26 01:20:50 2005 -0700 Create a standard "hello. . mientras que el directorio de trabajo contiene una instant´ nea de su proyecto en a un punto particular del historial.hg y sus subdirectorios son exclusivos de Mercurial. Aqu´ es ı donde Mercurial mantiene todos los metadatos del repositorio. Vistazo r´ pido al historial a Una de las primeras cosas que se desea hacer con un repositorio nuevo.. . world" program Por defecto este programa imprime un p´ rrafo breve por cada cambio al proyecto que haya sido grabado. podemos ver que contiene un directorio llamado . Para introducir algo de terminolog´a. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $ hg log changeset: tag: user: date: summary: changeset: user: date: summary: changeset: user: date: summary: changeset: user: date: summary: changeset: user: date: summary: 4:2278160e78d4 tip Bryan O’Sullivan <bos@serpentine.com Fri Aug 26 01:21:28 2005 -0700 Create a makefile 0:0a04b987be5a mpm@selenic.2. porque pueden contener un ı registro de cambios a varios ficheros.c Los contenidos del directorio . El comando “hg log” nos permite ver el mismo. 1:82e55d328c8c mpm@selenic. 3:0272e0d5a517 Bryan O’Sullivan <bos@serpentine. el directorio .3. 2:fef857204a0c Bryan O’Sullivan <bos@serpentine. 14 .4.hg.com> Sat Aug 16 22:08:02 2008 +0200 Get make to generate the final binary from a . 1 2 3 $ cd hello $ ls -a . cada uno de estos eventos es llamado conjunto de cambios.com> Sat Aug 16 22:05:04 2008 +0200 Introduce a typo into hello. Usted es libre de hacer lo que desee con cualquier otro fichero o directorio en el repositorio.c.2.hg es el repositorio “real”. Una forma sencilla de recordar esta distinci´ n es que el repositorio a o contiene el historial de su proyecto. poco conocido. Qu´ hay en un repositorio? e Cuando miramos en detalle dentro de un repositorio.com> Sat Aug 16 22:16:53 2008 +0200 Trim comments.

del T. Abreviatura para la expresi´ n “changeset” en ingl´ s. Conjunto de cambios. ambos muestran la fecha y hora para la persona que cre´ el conjunto de o cambios). del T. Este es un campo en el que se puede almacenar o cualquier valor.1: Historial gr´ fico del repositorio hello a 2. summary5 La primera l´nea del texto que us´ la persona que cre´ el conjunto de cambios para describir el mismo. 4 N. 5 N. Volveremos a esto varias veces en este cap´tulo y en los siguientes. Hay dos identificadores porque el n´ mero es m´ s corto y m´ s f´ cil de recordar que u a a a la cadena hexadecimal. Recuerde que el campo changeset en la salida de “hg log” identifica un conjunto de cambios usando tanto un n´ mero como una cadena hexadecimal. y algunas veces un se hace referencia a un conjunto de cambios como una “revisi´ n” o “rev”7 . o e 7 N. del T. (La fecha y hora son locales a dicha zona horaria. o Si bien no es relevante qu´ palabra use usted para referirse al concepto “conjunto de cambios”.1 es una representaci´ n gr´ fica del historial del repositorio hello. o date4 La fecha y hora en la que el conjunto de cambios fue creado. 15 . el control de o e e o e revisiones tiene una variedad de frases y palabras que tienen el mismo significado. De nuevo.1. Ambos son identificadores u para el conjunto de cambios. o La figura 2. pero en la mayor´a de los casos contiene el nombre de una persona y su direcci´ n de correo ı o electr´ nico. encontrar´ que la expresi´ n “conjunto de cambios” es abreviada a menudo como “cambio” a o o (por escrito) “cset”6 . y la zona horaria en la que fue creado.Los campos de la salida de “hg log” son los siguientes. Conjuntos de cambios. 2 N. ı o o El texto impreso por “hg log” es s´ lo un sumario. 6 N. seguido por un :. del T. como abreviaci´ n para el t´ rmino en ingl´ s para “revisi´ n” (“revision”). para hacer m´ s f´ cil ver en qu´ dio a a a e recci´ n est´ “fluyendo” el historial. omite una gran cantidad de detalles. Si usted habla acerca del historial de Mercurial con alguien. o a ı 4: 2278 (la más nueva) 4: 2278 3: 0272 2: fef8 número de revisión identificador del conjunto de cambios 1: 82e5 0: 0a04 (la más antigua) Figura 2. revisiones. del T. y comunic´ ndose con otras personas a ´ Ya que el ingl´ s es un lenguaje notablemente desordenado. y el area de ciencias de la computaci´ n tiene una e o notable historia de confusi´ n de t´ rminos (porqu´ usar s´ lo un t´ rmino cuando cuatro pueden servir?). u del T. Usuario. o e e o 3 N. el identificador que e usted use para referise a “un conjunto de cambios particular” es muy importante. Fecha. changeset2 Este campo tiene un n´ mero. seguido por una cadena hexadecimal.4. Sumario. user3 La identidad de la persona que cre´ el conjunto de cambios.

mientras que en otro aparecen como 1.o file. Si usted necesita hablar u o o con alguien acerca de un conjunto de cambios. y puede pasar tantas revisiones como desee.4. $ hg log -r 1 -r 4 changeset: 1:82e55d328c8c user: mpm@selenic. inclusive”. Si desea ver el historial de varias revisiones sin tener que mencionar cada una de ellas. esto le permite expresar el concepto “quiero ver todas las revisiones entre a y b. use la opci´ n -r (o --rev). Esto sucede porque el n´ mero de o u revisi´ n depende del orden en que llegan los cambios al repositorio. puede usar la notaci´ n de o rango. en un reporte de fallo).com> date: Sat Aug 16 22:08:02 2008 +0200 summary: Get make to generate the final binary from a .com date: Fri Aug 26 01:21:28 2005 -0700 summary: Create a makefile changeset: tag: user: date: summary: 4:2278160e78d4 tip Bryan O’Sullivan <bos@serpentine. 2. 16 . o llevar el registro de un conjunto de cambios por alguna otra raz´ n o (por ejemplo. u o o a Por otro lado. use el identificador hexadecimal. La diferencia es importante.com> date: Sat Aug 16 22:08:02 2008 +0200 summary: Get make to generate the final binary from a . 1 2 3 4 5 6 $ hg log -r 2:4 changeset: 2:fef857204a0c user: Bryan O’Sullivan <bos@serpentine. c pueden aparecer en un a repositorio como 0. Tres cambios dados a. Puede usar un n´ mero de o o u revisi´ n o un identificador hexadecimal de conjunto de cambios. Ver revisiones espec´ficas ı Para reducir la salida de “hg log” a una sola revisi´ n. Mercurial usa los n´ meros de revisi´ n simplemente como una abreviaci´ n conveniente. b.El n´ mero de revisi´ n s´ lo es v´ lido dentro del repositorio.c. 0. hay ı o o una probabilidad alta de que la revisi´ n 33 de esa persona no sea la misma suya. 2. y no hay ninguna garant´a de que los mismos o ı cambios llegar´ n en el mismo orden en diferentes repositorios. $ hg log -r 0272e0d5a517 changeset: 3:0272e0d5a517 user: Bryan O’Sullivan <bos@serpentine. 1. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 $ hg log -r 3 changeset: 3:0272e0d5a517 user: Bryan O’Sullivan <bos@serpentine. Si usted le env´a a alguien un correo electr´ nico hablando acerca de la “revisi´ n 33”.com> Sat Aug 16 22:16:53 2008 +0200 Trim comments. la cadena hexadecimal es el identificador permanente e inmutable que siempre identificar´ ese a´ conjunto de cambios en todas las copias del repositorio.com> date: Sat Aug 16 22:05:04 2008 +0200 summary: Introduce a typo into hello.o file.2. 2.

com> date: Sat Aug 16 22:05:04 2008 +0200 files: hello.c Fri Aug 26 01:21:28 2005 -0700 +++ b/hello.o file. si est´ tratando de o a averiguar si un conjunto de cambios dado es el que usted est´ buscando. Mercurial tambi´ n respeta el orden en que usted especifica las revisiones. Informaci´ n m´ s detallada o a ´ Aunque la informaci´ n presentada por “hg log” es util si usted sabe de antemano qu´ est´ buscando. Si desea ver tanto la descripci´ n como el contenido de un cambio.7 8 9 10 11 12 13 14 15 16 17 changeset: user: date: summary: changeset: tag: user: date: summary: 3:0272e0d5a517 Bryan O’Sullivan <bos@serpentine.a/hello. a˜ ada la opci´ n -p (o --patch).6 @@ int main(int argc. 2. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ hg log -v -p -r 2 changeset: 2:fef857204a0c user: Bryan O’Sullivan <bos@serpentine. o una lista de los ficheros que cambiaron. 3.3.c description: Introduce a typo into hello. 4 e ı mientras que “hg log -r 4:2” muestra 4.com> Sat Aug 16 22:08:02 2008 +0200 Get make to generate the final binary from a . diff -r 82e55d328c8c -r fef857204a0c hello. 2.c --.c Sat Aug 16 22:05:04 2008 +0200 @@ -11.4.6 +11.4 o para un vistazo global). vea la secci´ n 12.com> date: Sat Aug 16 22:08:02 2008 +0200 files: Makefile description: Get make to generate the final binary from a . char **argv) { 17 . 1 2 3 4 5 6 7 8 9 $ hg log -v -r 3 changeset: 3:0272e0d5a517 user: Bryan O’Sullivan <bos@serpentine. as´ que “hg log -r 2:4” muestra 2. La opci´ n -v (or --verbose) del comando a o “hg log” le da este nivel extra de detalle.com> Sat Aug 16 22:16:53 2008 +0200 Trim comments. 3. Esto muestra o n o el contenido de un cambio como un diff unificado (si usted nunca ha visto un diff unificado antes. puede o e a que necesite ver una descripci´ n completa del cambio. 4:2278160e78d4 tip Bryan O’Sullivan <bos@serpentine.o file.c.

e 1 2 3 4 5 $ cd . Silencioso. cada comando que le permite pasar un ID de conjunto de cambios o un n´ mero de revisi´ n acepta tanto la opci´ n -r como la --rev. e Muchos de los comandos que generan salida de alg´ n tipo mostrar´ n m´ s salida cuando se les pase la opci´ n -v u a a o (o --verbose8 ). a´ Mercurial tiene un enfoque directo y consistente en el manejo de las opciones que usted le puede pasar a los comandos. del cual usted puede hacer clones temporales para crear cajas de arena para cada tarea en la que desee trabajar. Muchas opciones tienen tambi´ n un nombre corto. del T. return 0. Esto s´ lo muestra mis preferencias. u o o En los ejemplos en este libro. uso las opciones cortas en vez de las largas. 0 files merged. printf("hello.g. En vez de --rev. mientras que las opciones cortas empiezan con uno (e. as´ que o ı no le d´ significado especial a eso. 8 N. Hacer y repasar cambios Ahora que tenemos una comprensi´ n adecuada sobre c´ mo revisar el historial en Mercurial. podemos usar -r. como ya hemos o o visto. Por ejemplo. el comando “hg log” acepta la opci´ n --rev. del T. clonar y e destruir repositorios no consume demasiados recursos.. 9 N. $ hg clone hello my-hello updating working directory 2 files updated. world!\"). Usaremos el comando “hg a clone”. Por ejemplo. ser´ util tener esto en mente a medida que avanza nuestra gira.17 18 19 20 21 + } printf("hello.6. El nombre y uso de las opciones es consistente en todos los comandos.5. es considerado buena pr´ ctica mantener una copia “pr´stina” de un repositorio remoto a o a ı mano.ej. 2. Prolijo. 0 files unresolved $ cd my-hello A manera de recomendaci´ n. Todo acerca de las opciones para comandos Tomemos un breve descanso de la tarea de explorar los comandos de Mercurial para hablar de un patr´ n en la o manera en que trabajan. pero no hace falta clonar una copia del repositorio remoto. (El motivo para que e algunas opciones no tengan nombres cortos es que dichas opciones se usan rara vez.) Las opciones largas empiezan con dos guiones (p. Como los clones locales son tan baratos. Esto le permite trabajar en m´ ltiples tareas en paralelo. y en la mayor´a de los casos clonar un a a e ı repositorio local usa menos espacio en disco tambi´ n. Como ya contamos con una copia local del mismo. lo que facilita hacerlo en cualquier momento. 0 files removed. hagamos algunos o o cambios y veamos c´ mo examinarlos. -r). 18 . y menos cuando se les pase la opci´ n -q (o --quiet9 ). teniendo cada una de ellas aislada de las otras hasta que est´ n u e completas y usted est´ listo para integrar los cambios de vuelta. world!\n"). o 2. Se siguen las convenciones para opciones que son comunes en sistemas Linux y Unix modernos. --rev). Cada opci´ n tiene un nombre largo. o Lo primero que haremos ser´ aislar nuestro experimento en un repositorio propio. podemos clonar esa. Esto es mucho m´ s r´ pido que clonar a trav´ s de la red.

c $ hg status M hello. ı ´ Es algo util saber que hemos modificado el fichero hello. 1 2 3 4 5 6 7 8 9 10 11 $ hg diff diff -r 2278160e78d4 hello. return 0. del T. o que lo modificamos una vez terminamos de hacerlo.c El comando “hg status” de Mercurial nos dice lo que Mercurial sabe acerca de los ficheros en el repositorio. “hg status” no imprimir´ nada respecto a los ficheros que ı a no han sido modificados. probablemente no querr´ usar sed. no est´ garantizado que lo logre. A menos que usted lo indique expl´citamente.c Tue Feb 10 18:23:34 2009 +0000 @@ -8. compilar y probar nuestros cambios.7. 1 $ sed -i ’/printf/a\\tprintf("hello again!\\n"). Hola. La “M” indica que Mercurial se dio cuenta de que nosotros modificamos hello. o a Dado que usted no tiene esta restricci´ n. use su editor de texto preferido para hacer o a lo mismo). s´ lo una l´nea empezando con “M” para el fichero o ı hello. para que m´ s adelante otros puedan saber qui´ n es el o a e responsable de cada cambio. hasta que estemos satisfechos con los resultados y lleguemos a un momento en el que sea natural que querramos guardar nuestro trabajo en un nuevo conjunto de cambios. hay un fichero hello. Mercurial registra a su nombre y direcci´ n en cada cambio que usted consigna.5 +8. en el orden presentado.a/hello. (Estoy usando el comando sed para hacer esto s´ lo porque es f´ cil escribir un ejemplo automatizado con el.1.7.c. No tuvimos que decirle a Mercurial que ´bamos a modificar ese fichero antes de hacerlo.6 @@ int main(int argc. Nos referiremos usualmente a esto como “hacer una consigna” o consignar. 2.c Sat Aug 16 22:16:53 2008 +0200 +++ b/hello. world!\"). + printf("hello again!\n"). Grabar cambios en un nuevo conjunto de cambios Podemos modificar. Definir un nombre de usuario Cuando usted trata de ejecutar “hg commit”11 por primera vez. Para averiguar esto. char **argv) { printf("hello. pero preferir´amos saber exactamente qu´ cambios ı e hicimos. del T. Mercurial trata de encontrar un nombre de usuario adecuado con el cual registrar la consignaci´ n. 10 N. Se intenta con cada uno de los siguientes m´ todos.En nuestro repositorio my-hello. y usar “hg status” y “hg diff” para revisar los mismos. o e 11 N. mundo. 1 2 3 4 $ ls Makefile hello.c.c El comando “hg status” no imprime nada para algunos ficheros.c --. } 2. usamos el comando “hg diff”. world”10 . Hacer una consignaci´ n o 19 . a Usaremos el cl´ sico y venerado comando sed para editar este fichero y hacer que imprima una segunda l´nea de a ı ´ salida. ı ´ el fue capaz de darse cuenta de esto por s´ mismo.c que contiene el cl´ sico programa “hello.c.’ hello. El comando “hg commit” nos permite crear un nuevo conjunto de cambios.

Para revisar c´ mo debe verse este fichero. o 1 $ hg commit 20 . use su editor de texto favorito para crear un fichero llamado . a 2. a Si todos estos procedimientos fallan. e interpretada por Mercurial. a El contenido inicial de su fichero .” ı o ı ı como “defina el valor del elemento username en la secci´ n ui”.2. Ser´ un registro de lo que hicimos y porqu´ lo hicimos. as´ que usted puede leer la l´nea “username = . Esto es conocido como un mensaje de consignaci´ n. Personas que env´an correo no solicitado. o o o se llega al final del fichero. a Crear el fichero de configuraci´ n de Mercurial o Para definir un nombre de usuario. se usa luego. Escribir un mensaje de consignaci´ n o Cuando consignamos un cambio. ı Escoger un nombre de usuario Usted puede usar el texto que desee como el valor del campo de configuraci´ n username. En este caso. Si usted pasa la opci´ n -u al comando “hg commit” en la l´nea de comandos.1. del T.. los detalles se encuentran m´ s adelante. Mercurial le pedir´ a su sistema buscar su nombre de usuario local. Mercurial fallar´ . o 3. para dificultar la tarea de las herramientas de recolecci´ n de direcciones de correo o que usan los spammersa . e imprimir´ un mensaje de error.hgrc en su directorio personal. para ingresar un mensaje que describa las modificaciones que hemos introducido en este conjunto de cambios.net> La l´nea “[ui]” define una section del fichero de configuraci´ n. seguido de un nombre de usuario.. refi´ rase a la secci´ n 2. Mercurial usar´ este fichero para obtener las configuraciones personalizadas que usted haya hecho. a o 5. Para uso normal. y construir´ un a a a nombre de usuario a partir de estos componentes. o e o a 4. ser´ usada a continuaci´ n. tambi´ n conocido como correo basura ı e 2. o Nota: El servidor web integrado de Mercurial ofusca las direcciones de correo. Ya que esto generalmente termina generando un nombre de ´ usuario no muy util. o [ui] username = Primernombre Apellido <correo.hgrc. Mercurial ignora las l´neas vac´as y considera cualquier texto desde el caracter “#” hasta ı ı el final de la l´nea como un comentario. Esto reduce la probabilidad de que usted empiece a recibir m´ s correo basura si publica un repositorio en la red. se imprimir´ una advertencia si es necesario hacerlo. ı ı 1 2 3 # Este es un fichero de configuraci´n de Mercurial. a o Trate de ver la variable de entorno HGUSER y la opci´ n -u del comando “hg commit” como formas de hacer caso o omiso de la selecci´ n de nombre de usuario que Mercurial hace normalmente. la manera m´ s simple y o a sencilla de definir un nombre de usuario para usted es crear un fichero .1 m´ s abajo. y ser´ impreso por “hg log” una vez hayamos o a e a hecho la consignaci´ n. Una secci´ n continua hasta que empieza otra nueva.hgrc. La convenci´ n que sigue la mayor´a de la gente es usar su a ı o ı nombre y direcci´ n de correo. como en el ejemplo anterior. Si usted crea un fichero en su directorio personal llamado . con una entrada username. ya que esta informaci´ n o o ser´ le´da por otras personas. Mercurial nos ubica dentro de un editor de texto.electronico@dominio.hgrc deber´a verse as´. A continuaci´ n se revisa si usted ha definido la variable de entorno HGUSER. Si usted ha definido la variable de entorno EMAIL. a a N.7. no le permia a tir´ hacer la consignaci´ n hasta que usted defina un nombre de usuario.7. o ı se le da a esto la m´ xima precedencia. y el nombre de m´ quina.

El editor en que “hg commit” nos ubica contendr´ una l´nea vac´a, seguida de varias l´neas que empiezan con la a ı ı ı cadena “HG:”.
1 2

l´nea vac´a ı ı HG: changed hello.c Mercurial ignora las l´neas que empiezan con “HG:”; s´ lo las usa para indicarnos para cu´ les ficheros est´ registrando ı o a a los cambios. Modificar o borrar estas l´neas no tiene ning´ n efecto. ı u

2.7.3.

Escribir un buen mensaje de consignaci´ n o

Ya que por defecto “hg log” s´ lo muestra la primera l´nea de un mensaje de consignaci´ n, lo mejor es escribir un o ı o mensaje cuya primera l´nea tenga significado por s´ misma. A continuaci´ n se encuentra un ejemplo de un mensaje de ı ı o consignaci´ n que no sigue esta pauta, y debido a ello tiene un sumario que no es legible. o
1 2 3 4

changeset: user: date: summary:

73:584af0e231be Persona Censurada <persona.censurada@ejemplo.org> Tue Sep 26 21:37:07 2006 -0700 se incluye buildmeister/commondefs. A˜ade un m´dulo n o

Con respecto al resto del contenido del mensaje de consignaci´ n, no hay reglas estrictas-y-r´ pidas. Mercurial no o a interpreta ni le da importancia a los contenidos del mensaje de consignaci´ n, aunque es posible que su proyecto tenga o pol´ticas que definan una manera particular de escribirlo. ı Mi preferencia personal es usar mensajes de consignaci´ n cortos pero informativos, que me digan algo que no o puedo inferir con una mirada r´ pida a la salida de “hg log --patch”. a

2.7.4.

Cancelar una consignaci´ n o

Si usted decide que no desea hacer la consignaci´ n mientras est´ editando el mensaje de la misma, simplemente o a cierre su editor sin guardar los cambios al fichero que est´ editando. Esto har´ que no pase nada ni en el repositorio ni a a en el directorio de trabajo. Si ejecutamos el comando “hg commit” sin ning´ n argumento, se registran todos los cambios que hemos hecho, u como lo indican “hg status” y “hg diff”.

2.7.5.

Admirar nuestro trabajo

Una vez hemos terminado la consignaci´ n, podemos usar el comando “hg tip”12 para mostrar el conjunto de o cambios que acabamos de crear. La salida de este comando es id´ ntica a la de “hg log”, pero s´ lo muestra la revisi´ n e o o m´ s reciente en el repositorio. a
1 2 3 4 5 6 7 8 9 10 11

$ hg tip -vp changeset: 5:fccff93807a3 tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:34 2009 +0000 files: hello.c description: Added an extra line of output

diff -r 2278160e78d4 -r fccff93807a3 hello.c
12 N.

del T. Punta.

21

12 13 14 15 16 17 18 19 20 21

--- a/hello.c Sat Aug 16 22:16:53 2008 +0200 +++ b/hello.c Tue Feb 10 18:23:34 2009 +0000 @@ -8,5 +8,6 @@ int main(int argc, char **argv) { printf("hello, world!\"); + printf("hello again!\n"); return 0; }

Nos referimos a la revisi´ n m´ s reciente en el repositorio como la revisi´ n de punta, o simplemente la punta. o a o

2.8.

Compartir cambios

Anteriormente mencionamos que los repositorios en Mercurial est´ n auto contenidos. Esto quiere decir que el a conjunto de cambios que acabamos de crear s´ lo existe en nuestro repositorio my-hello. Veamos unas cuantas formas o de propagar este cambio a otros repositorios.

2.8.1.

Jalar cambios desde otro repositorio

Para empezar, clonemos nuestro repositorio hello original, el cual no contiene el cambio que acabamos de consignar. Llamaremos a este repositorio temporal hello-pull.
1 2 3 4

$ cd .. $ hg clone hello hello-pull updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved Usaremos el comando “hg pull” para traer los cambios de my-hello y ponerlos en hello-pull. Sin embargo, traer cambios desconocidos y aplicarlos en un repositorio es una perspectiva que asusta al menos un poco. Mercurial cuenta con el comando “hg incoming”13 para decirnos qu´ cambios jalar´a el comando “hg pull” al repositorio, e ı sin jalarlos.

1 2 3 4 5 6 7 8 9 10

$ cd hello-pull $ hg incoming ../my-hello comparing with ../my-hello searching for changes changeset: 5:fccff93807a3 tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:34 2009 +0000 summary: Added an extra line of output

(Por supuesto, alguien podr´a enviar m´ s conjuntos de cambios al repositorio en el tiempo que pasa entre la ejecuci´ n ı a o de “hg incoming” y la ejecuci´ n de “hg pull” para jalar los cambios, as´ que es posible que terminemos jalando o ı cambios que no esper´ bamos.) a Traer cambios al repositorio simplemente es cuesti´ n de ejecutar el comando “hg pull”, indic´ ndole de qu´ reposo a e itorio debe jalarlos.
13 N.

del T. Entrante, o cambios entrantes.

22

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

$ hg tip changeset: tag: user: date: summary:

4:2278160e78d4 tip Bryan O’Sullivan <bos@serpentine.com> Sat Aug 16 22:16:53 2008 +0200 Trim comments.

$ hg pull ../my-hello pulling from ../my-hello searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (run ’hg update’ to get a working copy) $ hg tip changeset: 5:fccff93807a3 tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:34 2009 +0000 summary: Added an extra line of output

Como puede verse por las salidas antes-y-despu´ s de “hg tip”, hemos jalado exitosamente los cambios en nuestro e repositorio. A´ n falta un paso para que podamos ver estos cambios en nuestro directorio de trabajo. u

2.8.2.

Actualizar el directorio de trabajo

Hasta ahora hemos pasado por alto la relaci´ n entre un repositorio y su directorio de trabajo. El comando “hg o pull” que ejecutamos en la secci´ n 2.8.1 trajo los cambios al repositorio, pero si revisamos, no hay rastro de esos o cambios en el directorio de trabajo. Esto pasa porque “hg pull” (por defecto) no modifica el directorio de trabajo. En vez de eso, usamos el comando “hg update”14 para hacerlo.
1 2 3 4 5 6 7

$ grep printf hello.c printf("hello, world!\"); $ hg update tip 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ grep printf hello.c printf("hello, world!\"); printf("hello again!\n"); Puede parecer algo raro que “hg pull” no actualice el directorio de trabajo autom´ ticamente. De hecho, hay a una buena raz´ n para esto: usted puede usar “hg update” para actualizar el directorio de trabajo al estado en que se o encontraba en cualquier revisi´ n del historial del repositorio. Si usted hubiera actualizado el directorio de trabajo a una o revisi´ n anterior—digamos, para buscar el origen de un fallo—y hubiera corrido un “hg pull” que hubiera actualizado o el directorio de trabajo autom´ ticamente a la nueva revisi´ n, puede que no estuviera particularmente contento. a o Sin embargo, como jalar-y-actualizar es una secuencia de operaciones muy com´ n, Mercurial le permite combinau rlas al pasar la opci´ n -u a “hg pull”. o

1

hg pull -u
14 N.

del T. Actualizar.

23

Si mira de vuelta la salida de “hg pull” en la secci´ n 2.8.1 cuando lo ejecutamos sin la opci´ n -u, ver´ que el o o a comando imprimi´ un amable recordatorio de que tenemos que encargarnos expl´citamente de actualizar el directorio o ı de trabajo:
1

(run ’hg update’ to get a working copy) Para averiguar en qu´ revisi´ n se encuentra el directorio de trabajo, use el comando “hg parents”. e o

1 2 3 4 5 6 7

$ hg parents changeset: 5:fccff93807a3 tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:34 2009 +0000 summary: Added an extra line of output

Si mira de nuevo la figura 2.1, ver´ flechas conectando cada conjunto de cambios. En cada caso, el nodo del que la a flecha sale es un padre, y el nodo al que la flecha llega es su hijo. El directorio de trabajo tiene un padre exactamente ´ de la misma manera; ese es el conjunto de cambios que contiene actualmente el directorio de trabajo. Para actualizar el conjunto de trabajo a una revisi´ n particular, pase un n´ mero de revisi´ n o un ID de conjunto de o u o cambios al comando “hg update”.
1 2 3 4 5 6 7 8 9 10

$ hg update 2 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg parents changeset: 2:fef857204a0c user: Bryan O’Sullivan <bos@serpentine.com> date: Sat Aug 16 22:05:04 2008 +0200 summary: Introduce a typo into hello.c. $ hg update 2 files updated, 0 files merged, 0 files removed, 0 files unresolved Si no indica expl´citamente una revisi´ n, “hg update” actualizar´ hasta la revisi´ n de punta, como se vio en la segunda ı o a o llamada a “hg update” en el ejemplo anterior.

2.8.3.

Empujar cambios a otro repositorio

Mercurial nos permite empujar cambios a otro repositorio, desde el repositorio que estemos usando actualmente. De la misma forma que en el ejemplo de “hg pull” arriba, crearemos un repositorio temporal para empujar all´ nueı stros cambios.
1 2 3 4

$ cd .. $ hg clone hello hello-push updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved El comando “hg outgoing”15 nos dice qu´ cambios ser´an empujados en el otro repositorio. e ı

1 2

$ cd my-hello $ hg outgoing ../hello-push
15 N.

del T. Saliente. Cambios salientes.

24

/hello-push searching for changes changeset: 5:fccff93807a3 tag: tip user: Bryan O’Sullivan <bos@serpentine.serpentine../hello-push searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files Al igual que “hg pull”. (A diferencia de “hg pull”.com/tutorial/hello pushing to http://hg. “hg push” no ofrece la opci´ n -u para actualizar el directorio o de trabajo del otro repositorio. 1 2 3 4 5 6 7 $ hg push .serpentine.4.serpentine. de manera entendible.com/tutorial/hello searching for changes ssl required 25 .. 1 2 3 4 5 6 7 8 9 $ hg outgoing http://hg..serpentine. podemos ver qu´ cambios empujar´amos al repositorio remoto.com/tutorial/hello searching for changes changeset: 5:fccff93807a3 tag: tip user: Bryan O’Sullivan <bos@serpentine. Compartir cambios a trav´ s de una red e Los comandos que hemos presentando en las pocas secciones anteriores no est´ n limitados a trabajar con repositoa rios locales.8. Simplemente e o pase una URL en vez de una ruta local. 1 2 3 4 $ hg push ../hello-push searching for changes no changes found 2.) Qu´ pasa si tratamos de jalar o empujar cambios y el repositorio receptor ya tiene esos cambios? Nada emocioe nante.com> date: Tue Feb 10 18:23:34 2009 +0000 summary: Added an extra line of output Y el comando “hg push” se encarga de empujar dichos cambios. Cada uno de ellos funciona exactamente de la misma manera a trav´ s de una conexi´ n de red.3 4 5 6 7 8 9 10 comparing with ../hello-push pushing to . el comando “hg push” no actualiza el directorio de trabajo del repositorio en el que estamos empujando los cambios. el e ı ´ repositorio remoto est´ configurado para no permitir a usuarios an´ nimos empujar cambios a el.com> date: Tue Feb 10 18:23:34 2009 +0000 summary: Added an extra line of output En este ejemplo. aunque.com/tutorial/hello comparing with http://hg. a o 1 2 3 4 $ hg push http://hg./hello-push pushing to .

como se ilustra en la figura 3.h> int main(int argc.c con contenidos diferentes.Cap´tulo 3 ı Una gira de Mercurial: fusionar trabajo Hasta ahora hemos cubierto c´ mo clonar un repositorio. 1 2 3 4 5 6 7 $ cd .’ hello. 0 files merged. Empezaremos o u ´ clonando (otro) repositorio (ve lo seguido que aparecen?) y haciendo un cambio en el. Mercurial la facilita. char **argv) 26 . hello. 0 files removed.1.’ Ahora deber´amos tener dos copias de hello. 3. Fusionar es una parte fundamental de trabajar con una herramienta de control distribuido de versiones. cada una aislada convenientemente de las otras en su propio repositorio. Como fusionar es una operaci´ n tan necesaria y com´ n. Ambos desean que n ı el repositorio compartido contenga el arreglo del fallo y la nueva caracter´stica. Roberto a˜ ade una nueva caracter´stica en el suyo.c $ hg commit -m ’A new hello for a new day. ı Frecuentemente trabajo en varias tareas diferentes en un mismo proyecto al mismo tiempo. a Alicia arregla un fallo en su repositorio. */ #include <stdio. Nuestro siguiente paso es fusionar cambios de repositorios separados.1. hacer cambios. 1 2 3 4 5 6 7 8 9 $ cat hello. Revisemos el proceso. $ hg clone hello my-new-hello updating working directory 2 files updated. y jalar o empujar dichos cambios de un o repositorio a otro..\\n"). This program is * not covered by patents in the United States or other countries. El historial de los dos repositorios diverge ı ahora. Fusionar l´neas de trabajo ı Alicia y Roberto tienen cada uno una copia personal del repositorio de un proyecto en el que est´ n trabajando. Trabajar de esta manera significa que a menudo debo fusionar una parte de mi propio trabajo con otra. 0 files unresolved $ cd my-new-hello $ sed -i ’/printf/i\\tprintf("once more.c /* * Placed in the public domain by Bryan O’Sullivan.

This program is * not covered by patents in the United States or other countries. a 1 2 3 4 5 6 7 $ hg pull ./my-hello/hello.c /* * Placed in the public domain by Bryan O’Sullivan.. char **argv) { printf("hello../my-hello pulling from ./my-hello searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) 27 .1: Historial reciente divergente de los repositorios my-hello y my-new-hello Ya sabemos que jalar los cambios desde nuestro repositorio my-hello no tendr´ efecto en el directorio de trabajo. world!\"). world!\"). */ #include <stdio. hello. } $ cat . printf("hello again!\n"). return 0..h> int main(int argc.\n"). } my−hello 5: fccf my−new−hello Los cambios más recientes difieren 5: 05b9 revisión principal (sin hijos) 4: 2278 4: 2278 3: 0272 3: 0272 2: fef8 historia común 2: fef8 1: 82e5 1: 82e5 0: 0a04 0: 0a04 Figura 3. return 0.10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 { printf("once more. printf("hello.

1 N. 6:fccff93807a3 tip 4:2278160e78d4 Bryan O’Sullivan <bos@serpentine.1. un frente. este es un buen ejemplo de porqu´ no es seguro usar n´ meros de revisi´ n cuando se e u o habla de conjuntos de cambios). El autor se refiere a heads aqu´. pero fue a˜ adida una nueva revisi´ n. La revisi´ n de punta es. ı del T. Conjuntos de cambios de frentes Un frente es un cambio que no tiene descendientes. 28 .com> del T. ı n o e podemos ver que el ID del conjunto de cambios se mantiene igual en el nuevo repositorio.1. 3. Refiri´ ndonos a la figura 3. un repositorio o a u puede contener m´ s de un frente. Frentes. Podemos ver los frentes en un repositorio usando el comando “hg heads”2 . el comando “hg pull” dice algo acerca de “frentes”1 .8 (run ’hg heads’ to see heads.1. pero el n´ mero de revisi´ n u o ´ ha cambiado. Sin embargo.2 usted puede ver el efecto que tiene jalar los cambios de my-hello a my-new-hello. o hijos. porque la revisi´ n m´ s reciente en un repositorio no tiene ning´ n hijo. ’hg merge’ to merge) Sin embargo. como tambi´ n se les conoce. El historial que ya exist´a en my-new-hello se mantiene intacto. e o por tanto. 1 2 3 4 5 6 7 8 9 10 $ hg heads changeset: tag: parent: user: date: summary: changeset: user: 2 N.com> Tue Feb 10 18:23:34 2009 +0000 Added an extra line of output 5:05b9c1e50b3c Bryan O’Sullivan <bos@serpentine. a 6: fccf tip (y principal) principal 5: 05b9 4: 2278 3: 0272 2: fef8 1: 82e5 0: 0a04 Figura 3.2: Contenidos del repositorio despu´ s de jalar my-hello a my-new-hello e En la figura 3. (Incidentalmente.

“hg update”.3: Directorio de trabajo y repositorio durante la fusi´ n. Hacer la fusi´ n o Qu´ pasa si tratamos de usar el comando usual. 1 files merged. lo que se ve reflejado tanto en la salida de “hg parents” como en los contenidos de hello.2. 3. 0 files unresolved (branch merge. don’t forget to commit) Directorio de trabajo durante la fusión Repositorio después de consignar la fusión fusión directorio de trabajo durante la fusión 6: fccf punta 7: 22a5 punta (y frente) 6: fccf frente 5: 05b9 5: 05b9 4: 2278 4: 2278 Figura 3.c 0 files updated. o 1 2 3 4 $ hg merge merging hello. changeset: tag: parent: 6:fccff93807a3 tip 4:2278160e78d4 29 . a menos que lo obliguemos a hacerlo.11 12 13 date: summary: Tue Feb 10 18:23:36 2009 +0000 A new hello for a new day. para actualizar el nuevo frente? e 1 2 $ hg update abort: crosses branches (use ’hg merge’ or ’hg update -C’) Mercurial nos indica que el comando “hg update” no har´ la fusi´ n. o usamos el comando “hg merge” para hacer la fusi´ n entre los dos frentes.c. y consignaci´ n consecuente o o Esto actualiza el directorio de trabajo. En vez de “hg update”. 1 2 3 4 5 6 7 8 9 $ hg parents changeset: 5:05b9c1e50b3c user: Bryan O’Sullivan <bos@serpentine. 0 files removed.1. de tal forma que contenga los cambios de ambos frentes. no actualizar´ el directorio de trabajo cuando a o a considera que lo que deseamos hacer es una fusi´ n.com> date: Tue Feb 10 18:23:36 2009 +0000 summary: A new hello for a new day.

3 usted puede apreciar una representaci´ n de lo que pasa en el directorio de trabajo durante la fusi´ n o o cuando se hace la consignaci´ n. o 1 $ hg commit -m ’Merged changes’ Ahora tenemos una nueva revisi´ n de punta. note que tiene los dos frentes anteriores como sus padres. pero a veces usted se encontrar´ fusionando cambios donde m´ s de ı a a uno de ellos afecta las mismas secciones de los mismos ficheros. Estos son las o mismas revisiones que mostr´ previamente el comando “hg parents”. “hg parents” mostrar´ dos padres hasta que consignemos (“hg commit”) los o a resultados de la fusi´ n. } 3. world!\"). Consignar los resultados de la fusi´ n o Siempre que hacemos una fusi´ n. This program is * not covered by patents in the United States or other countries. char **argv) { printf("once more. return 0. printf("hello.com> Tue Feb 10 18:23:34 2009 +0000 Added an extra line of output $ cat hello. en donde usted debe decidir c´ mo reconciliar ambos cambios y producir un resultado o coherente. */ #include <stdio. y estos se vuelven los padres del nuevo conjunto de cambios. o 1 2 3 4 5 6 7 8 9 $ hg tip changeset: tag: parent: parent: user: date: summary: 7:22a572779faf tip 5:05b9c1e50b3c 6:fccff93807a3 Bryan O’Sullivan <bos@serpentine.h> int main(int argc. Durante la fusi´ n. A menos que ambas modificaciones sean id´ nticas. printf("hello again!\n").10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 user: date: summary: Bryan O’Sullivan <bos@serpentine.2.3.c /* * Placed in the public domain by Bryan O’Sullivan.com> Tue Feb 10 18:23:36 2009 +0000 Merged changes En la figura 3.1. 3. el directorio de trabajo tiene dos conjuntos de cambios como sus o o ´ padres. 30 . hello. e el resultado es un conflicto.\n"). Fusionar cambios con conflictos La mayor´a de las fusiones son algo simple.

ej.4: Cambios con conflictos a un documento La figura 3. 31 . con las modificaciones que hemos hecho. Mercurial no tiene ninguna utilidad integrada para manejar conflictos. el gui´ n intenta con herramientas gr´ ficas para fusionar. p. A la izquierda est´ la revisi´ n base del fichero. sobrina del anterior dictador de Nigeria Sani Abacha. Debido a esto la herramienta divide la parte superior de la ventana en tres paneles. a o a Tambi´ n es posible hacer que Mercurial ejecute otro programa o gui´ n en vez de hgmerge. la que forma parte del conjunto de cambios que estamos a o tratando de fusionar. con una fusi´ n adecuada de “nuestra” versi´ n del fichero y la de “ellos”. Le contacto en secreto. Lo que debemos hacer para resolver el conflicto causado por ambos cambios es decidir c´ mo debe quedar o finalmente el fichero. hijo del anterior dictador de Nigeria Sani Abacha. En la mitad est´ “nuestra” versi´ n del fichero.1. Es un gui´ n de l´nea de comandos que es instalado junto con Mercurial. porque hay tres versiones diferentes del o o ı fichero en que estamos interesados. o o Los cuatro paneles est´ n enlazados. lo que hace es tratar de encontrar una de varias herramientas para fusionar que es probable que est´ n instaladas en su sistema. y la usar´ para describir las caracter´sticas comunes de las e ı herramientas gr´ ficas para hacer fusiones. En el panel inferior se encuentra el resultado actual de la fusi´ n. a a El tipo de fusi´ n que la herramienta hace se conoce como fusi´ n de tres v´as. definiendo la variable e o de entorno HGMERGE con el nombre del programa de su preferencia.4 ilustra un ejemplo con dos cambios generando conflictos en un documento. en la figura 3. mientras tanto. ejecuta un programa externo llamado hgmerge. Le contacto en secreto.5. a o A la derecha est´ la versi´ n del fichero de “ellos”. Por defecto. Usar una herramienta gr´ fica para fusi´ n a o Mi herramienta favorita para hacer fusiones es kdiff3. Primero se intenta con unas herramientas para fusionar e ´ cambios autom´ ticamente. usted puede modificarlo o ı para que se comporte como usted lo desee. si esto no tiene exito (porque la fusi´ n demanda una gu´a humana) o dichas herramientas a o ı no est´ n presentes. buscando los medios para desarrollar Nuestros cambios Sus cambios Saludos! Soy Mariam Abacha. alguien m´ s hizo cambios diferentes en el mismo o a texto. buscando los medios para desarrollar Saludos! Soy Alhaji Abba Abacha.Saludos! Soy Shehu Musa Abacha. Nuestra tarea es reemplazar todo el texto rojo. que o muestra los conflictos sin resolver. Le contacto en secreto. la versi´ n m´ s reciente de la que descienden las dos a o o a versiones que estamos tratando de fusionar. buscando los medios para desarrollar Versión inicial Figura 3. los otros son a actualizados para mostrar las secciones correspondientes del fichero que tengan asociado. la esposa del anterior dictador de Nigeria Sani Abacha. luego hicimos algunos cambios. si avanzamos vertical o horizontalmente en cualquiera de ellos.2. Puede ver una captura de pantalla de kdiff3 ejecut´ ndose. En vez de eso. 3. Empezamos con una sola versi´ n del fichero.

Se diferencian en las plataformas para las que est´ n a disponibles.4 mostrada anteriormente. la nuestra. Tambi´ n podemos editar manualmente el fichero en que queda la fusi´ n. Un ejemplo real En este ejemplo. si es necesario e o hacer cambios adicionales. mienı a tras que otras est´ n pensadas para formatos de ficheros especializados (generalmente XML).txt hg commit -m ’419 scam. reproduciremos el historial de modificaciones al fichero de la figura 3. La mayor´a est´ n afinadas para fusionar texto plano. first draft’ Clonaremos el repositorio y haremos un cambio al fichero.2. 1 2 3 4 $ cd . a 3. y en sus fortalezas y debilidades particulares. EOF hg add letter. 0 files unresolved 32 . o 1 2 3 4 5 6 7 $ > > > > $ $ cat > letter. Empecemos creando un repositorio con la versi´ n base de nuestro documento. $ hg clone scam scam-cousin updating working directory 1 files updated. the wife of former Nigerian dictator Sani Abacha.Figura 3.txt <<EOF Greetings! I am Mariam Abacha. 0 files removed. 0 files merged.2. o la de ellos. Hay muchas herramientas para fusionar ficheros disponibles..5: Usando kdiff3 para fusionar versiones de un fichero En cada conflicto del fichero podemos escoger resolverlo usando cualquier combinaci´ n del texto de la revisi´ n o o base.

(Esto introduce la idea de a que no es tan inusual hacer fusiones consigo mismo. $ hg clone scam-cousin scam-merge updating working directory 1 files updated. 0 files unresolved $ cd scam-merge $ hg pull -u . 1 2 3 4 5 $ export HGMERGE=merge $ hg merge merging letter. no se o a moleste en definir HGMERGE. no usar´ el comando normal de Mercurial para hacer la fusi´ n (hgmerge). porque lanzar´a mi linda e o ı herramienta automatizada para correr ejemplos dentro de una interfaz gr´ fica de usuario..) 1 2 3 4 5 6 7 8 9 10 11 $ cd .. with son’ Ahora que tenemos dos versiones diferentes de nuestro fichero./scam-son searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) not updating.txt merge: warning: conflicts during merge merging letter. En vez de eso.txt <<EOF > Greetings! > I am Alhaji Abba Abacha. 0 files merged. definir´ la a e variable de entorno HGMERGE para indicarle a Mercurial que use el comando merge. son of the former > Nigerian dictator Sani Abacha.txt failed! 33 . > EOF $ hg commit -m ’419 scam. cousin to the former Nigerian dictator Sani Abacha. para simular a alguien m´ s haciendo un cambio al mismo fichero.5 6 7 8 9 10 11 $ $ > > > > $ cd scam-cousin cat > letter. cuando usted a´sla tareas en repositorios separados./scam-son pulling from . o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ cd . ’hg merge’ to merge) En este ejemplo.. 0 files removed. 0 files removed. crearemos un entorno adecuado para hacer la fusi´ n.. $ hg clone scam scam-son updating working directory 1 files updated. Este comando forma parte de la instalaci´ n base de muchos sistemas Unix y similares. y de hecho ı encuentra conflictos al hacerlo. since new heads added (run ’hg heads’ to see heads. with cousin’ Y haremos otro clon. Si usted est´ ejecutando este ejemplo en su computador. 0 files merged. EOF hg commit -m ’419 scam. 0 files unresolved $ cd scam-son $ cat > letter.txt <<EOF Greetings! I am Shehu Musa Abacha.

Si la fusi´ n —autom´ tica o manual— falla.txt Greetings! <<<<<<< /tmp/tour-merge-conflictsNZwSt/scam-merge/letter. y consignar los resultados de nuestra fusi´ n: o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 $ cat > letter. 0 files removed. ´ Debido a que merge no puede resolver los conflictos que aparecen. no relation of the former > Nigerian dictator Sani Abacha. you can redo the full merge using: hg update -C 1 hg merge 2 $ cat letter.6 7 8 9 10 11 12 13 14 15 16 17 0 files updated. son of the former >>>>>>> /tmp/letter. > EOF $ hg resolve -m letter. o Mercurial puede saber —por el c´ digo de salida del comando merge— que no fue posible hacer la fusi´ n exitosao o ´ mente. cousin to the former ======= I am Alhaji Abba Abacha.txt I am Shehu Musa Abacha.txt <<EOF > Greetings! > I am Bryan O’Sullivan. por ı e o ejemplo. no hay nada que nos impida “arreglar” los ficheros afectados por o a nosotros mismos.749P-k Nigerian dictator Sani Abacha. 1 files unresolved There are unresolved merges.txt hg: unknown command ’resolve’ Mercurial Distributed SCM basic commands: add annotate clone commit diff export init log merge parents pull push remove serve status update add the specified files on the next commit show changeset information per file line make a copy of an existing repository commit the specified files or all outstanding changes diff repository (or selected files) dump the header and diffs for one or more changesets create a new repository in the given directory show revision history of entire repository or files merge working directory with another revision show the parents of the working dir or revision pull changes from the specified source push changes to the specified destination remove the specified files on the next commit export the repository via HTTP show changed files in the working directory update working directory use "hg help" for the full list of commands or "hg -v" for details $ hg commit -m ’Send me your money’ 34 . Esto puede ser util si. as´ que nos indica qu´ comandos debemos ejecutar si queremos rehacer la fusi´ n.txt˜other. indicando si provienen de nuestra versi´ n o de la de ellos. 0 files merged. el deja marcadores de fusi´ n en el fichero con o conflictos. estamos ejecutando una herramienta gr´ fica de fusi´ n y salimos de ella porque nos confundimos o cometimos a o un error.

Mercurial sabe d´ nde buscarla. “hg fetch”. a la derecha del “=” deber´a aparecer la ubicaci´ n de la extensi´ n. y luego consigna n o el resultado de la misma con un mensaje generado autom´ ticamente. ı 1 2 [extensions] fetch = (Normalmente. Si encuentra que los cambios a˜ aden un nuevo frente en el repositorio actual.3.com> Tue Feb 10 18:23:37 2009 +0000 Send me your money 3. por ejemplo. Activar la extensi´ n fetch es f´ cil. mientras que otros funcionan “tras bambalinas”. Edite su . o 1 2 3 hg pull hg merge hg commit -m ’Fusionados cambios remotos’ En la consignaci´ n final usted debe proveer un mensaje adecuado. La extensi´ n fetch a˜ ade un comando llamado. pero como el comando fetch es ı o o parte de la distribuci´ n est´ ndar. traer. Luego a˜ ada una o a o n l´nea que diga simplemente “fetch ”. del T.) o a o 3 N. Empieza jalando cambios de otro repositorio al repositorio o actual. o Mercurial cuenta con un mecanismo de extensi´ n flexible que le permite a sus usuarios extender su funcionalidad. “hg update” y “hg merge”. 35 . Si no se a˜ adieron nuevos frentes. Descargar. y vaya a (o cree) la secci´ n [extensions]. inicia una fusi´ n. De hecho. Esta extensi´ n act´ a como una o n o u combinaci´ n de “hg pull”. no sorpresivamente. Simplificar el ciclo jalar-fusionar-consignar El proceso de fusionar cambios delineado anteriomente es directo. que casi siempre es un fragmento de texto “de o relleno” carente de valor particular. a˜ adiendo ı n funcionalidad al servidor. actualiza el a n directorio de trabajo con el nuevo conjunto de cambios de punta.hgrc. Ser´a agradable reducir la cantidad de pasos necesarios.31 32 33 34 35 36 37 38 39 $ hg tip changeset: tag: parent: parent: user: date: summary: 3:e29827f5cf51 tip 1:eac603d73208 2:78b0a9e9cf1b Bryan O’Sullivan <bos@serpentine. si fuera posible. pero requiere la ejecuci´ n de tres comandos en o sucesi´ n. Mercurial es distribuido junto ı con una extensi´ n llamada fetch3 que hace precisamente esto. Algunas extensiones a˜ aden nuevos comandos que u n a n usted puede usar desde la l´nea de comandos. o manteniendo el n´ cleo de Mercurial peque˜ o y f´ cil de manejar.

es menos probable que me sosprenda su comportamiento. o 1 N.3. pero a o ´ considero util tener un “modelo mental” de qu´ es lo que sucede. Y tal vez con la misma importancia. cubriremos inicialmente los conceptos centrales del dise˜ o de Mercurial. del T.1. 4.1. la revisi´ n de cada e a o fichero.1. Administraci´ n de ficheros monitoreados o Mercurial usa una estructura llamada manifiesto para centralizar la informaci´ n que maneja acerca de los ficheros o ´ que monitorea. En este cap´tulo. Saber esto no es necesario. Una entrada registra qu´ ficheros est´ n presentes en el conjunto de cambios. los conceptos en los que se fundamenta Mercurial son lo suficientemente simples como para entender f´ cilmente c´ mo funciona el software. o 4.i”. o con un historial muy largo. 4.1. El fichero de registro de un fichero grande.i”). los datos de ı n n ´ revisiones y el ´ndice son combinados en un unico fichero “. y luego discutiremos ı n algunos detalles interesantes de su implementaci´ n. 4. Para ficheros peque˜ os con un historial peque˜ o.2. y otros cuantos metadatos del mismo. Los ficheros de registro son almacenados como ficheros el el directorio o a . otros datos relacionados con el conjunto de cambios. Un fichero de registro contiene dos tipos de informaci´ n: datos de revisiones. Cada entrada en el manifiesto contiene informaci´ n acerca de los ficheros involucrados en un unico o conjunto de cambios.d”) y para el ´ndice (sufijo “.1. y un ´ndice para o ı ayudar a Mercurial a buscar revisiones eficientemente.hg/store/data. Cada revisi´ n indica qui´ n a o o e consign´ un cambio. o y la revisi´ n del manifiesto a usar.1. guarda el historial de dicho fichero en un objeto de metadatos llamado filelog1 . e Comprender esto me da la confianza de que Mercurial ha sido cuidadosamente dise˜ ado para ser tanto seguro como n eficiente. Registro del historial de Mercurial ´ Seguir el historial de un unico fichero Cuando Mercurial sigue las modificaciones a un fichero. Cada entrada en el fichero de registro contiene suficiente informaci´ n para reconstruir una o revisi´ n del fichero que se est´ siguiendo. el comentario para el conjunto de cambios. si es f´ cil para m´ hacerme a una idea adecuada de qu´ est´ haciendo el a ı e a software cuando llevo a cabo una tarea relacionada con control de revisiones.Cap´tulo 4 ı Tras bambalinas A diferencia de varios sistemas de control de revisiones. es guardado como ficheros separados para datos (sufijo “. Fichero de registro 36 . Registro de informaci´ n del conjunto de cambios o La bit´ cora de cambios contiene informaci´ n acerca de cada conjunto de cambios. La correspondencia entre un fichero en el directorio ı de trabajo y el fichero de registro que hace seguimiento a su historial en el repositorio se ilustra en la figura 4.

las entradas en la bit´ cora de cambios para esos conjuntos de cambios apuntar´ n a la misma revisi´ n del manifiesto.2: Relaciones entre metadatos Como lo muestra la figura. Bitácora de cambios Manifiesto Bitácora de archivos Figura 4.hg/store/data/src/hello. o un fichero de registro.c .Directorio de trabajo Repositorio . hay exactamente una revisi´ n almacenada en la bit´ cora de o a ´ cambios.i Figura 4.1. el o manifiesto. si es la revisi´ n de una fusi´ n).c. Una o a o ´ revisi´ n del manifiesto almacena un apuntador a una unica revisi´ n de cada fichero de registro al que se le hac´a o o ı seguimiento cuando fue creado el conjunto de cambios. cada revisi´ n conserva un apuntador a o a su padre inmediato (o sus dos padres. a o 37 . e a Por cada conjunto de cambios en un repositorio. Estas relaciones se ilustran en la figura 4. o el fichero de registro. Cada revisi´ n de la bit´ cora de cambios contiene un apuntador a una unica revisi´ n del manifiesto.c.d .hg/store/data/src/hello.1: Relaci´ n entre ficheros en el directorio de trabajo y ficheros de registro en el repositorio o 4.i README src/hello. y tienen naturaleza jer´ rquica.2. Si a a o un fichero monitoreado por Mercurial no sufre ning´ n cambio de un conjunto de cambios a otro.4. Relaciones entre revisiones Dentro de una bit´ cora de cambios. Como mencio´ e anteriormente. no hay una relaci´ n “uno a uno” entre las revisiones en el conjunto de cambios.hg/store/data/README. Si el manifiesto no ha sido modificado de un conjunto de cambios a otro. tambi´ n hay o o n e relaciones entre revisiones a trav´ s de estas estructuras. un manifiesto. la entrada para dicho u fichero en las dos revisiones del manifiesto apuntar´ a la misma revisi´ n de su fichero de registro.

Este enfoque funciona tan bien que desde entonces ha sido copiado por otros sistemas de control de a revisiones.3. Almacenamiento eficiente El revlog provee almacenamiento eficiente de revisiones por medio del mecanismo de deltas3 . y los ficheros de registros es provista por una unica u a estructura llamada el revlog2 . o Nota al margen: la influencia de la compresi´ n de v´deo o ı Si le es familiar la compresi´ n de v´deo. A o a a ı ´ medida que sea m´ s f´ cil hacer operaciones como esta. donde una de ellas est´ leyendo datos y la otra los est´ escribiendo. 4 N. o sino a la operaci´ n normal del sistema.4. Mercurial puede manejar deltas de ficheros con contenido binario arbitrario. Recuperaci´ n r´ pida de datos o a Mercurial evita ingeniosamente un problema com´ n a todos los sistemas de control de revisiones anteriores¿ u el problema de la recuperaci´ n4 ineficiente de datos. registro de revisi´ n.2. m´ s confianza tendr´ usted en que sean hechas correctamente. que puede cubrir varios ficheros. Una vez la cantidad de informaci´ n de o o ´ deltas acumulada desde la ultima instant´ nea excede un umbral fijado de antemano. o ´ Una transacci´ n es at´ mica: o bien la transacci´ n tiene exito y entonces todos sus efectos son visibles para todos o o o los lectores. y por tanto toma m´ s tiempo a a ı a reconstruir una versi´ n particular. Entre m´ s largo sea el historial de un fichero.2. Para muchos tipos de fichero. o codificados en alguna representaci´ n de texto a o plano adecuada. 4. se almacena una nueva instant´ nea a a (comprimida.2. en lugar de otro delta. Almacenamiento seguro y eficiente ´ La base com´ n de las bit´ coras de cambios. almacena los cambios necesarios para transformar una revisi´ n o o anterior en la nueva revisi´ n. Nunca modifica ninguna secci´ n de un fichero una o n o vez ha sido escrita. Recuperaci´ n en el sentido de traer los datos. o La innovaci´ n que aplica Mercurial a este problema es simple pero efectiva. ı El hecho de que Mercurial s´ lo hace adiciones a los ficheros hace m´ s f´ cil proveer esta garant´a transaccional. 2 N. Mercurial almacena el rango de ı entradas (deltas) del fichero de datos que se deben leer para reconstruir una revisi´ n en particular. La figura 4. o 3 N. y luego cada una de las revisiones entre la instant´ nea y su versi´ n a a o objetivo. Esta garant´a de atomicidad implica que. por supuesto). m´ s revisiones deben ser le´das. Diferencias. En una entrada en el fichero ´ndice de un revlog. pero no debido a una falla o calamidad. 38 . no necesita tratar el texto plano como un caso especial. y ambas alternativas son enfoques que desperdician bastantes recursos. Muchos sistemas de control de revisiones almacenan los cono tenidos de una revisi´ n como una serie incremental de modificaciones a una “instant´ nea”.2.3 ilustra la idea. primero usted debe leer la instant´ nea. 4. Para reconstruir una versi´ n o a o cualquiera.1. o o del T. los manifiestos. a a a a 4. n Algunos sistemas de control de revisiones obsoletos s´ lo pueden manipular deltas de ficheros de texto plano. puede que sepa que la mayor parte de los esquemas de compresi´ n de v´deo almacenan e o ı del T. Contracci´ n de revision log. Mercurial trata cada escritura como parte de una transacci´ n. o reconstruirlos a partir de otros datos.2. si usted est´ ejecutando o ı a dos copias de Mercurial. Esto hace posible reconstruir cualquier versi´ n de un fichero o r´ pidamente. Ellos o o bien almacenan los ficheros binarios como instant´ neas completas. o ha mirado alguna vez una emisi´ n de TV a trav´ s de cable digital o ı o e o un servicio de sat´ lite. Esto es m´ s robusto y eficiente que otros esquemas que requieren modificar o reescribir datos. del T. o la operaci´ n completa es cancelada. Operaci´ n segura o Mercurial s´ lo a˜ ade datos al final de los ficheros de revlog. a Adicionalmente. estos deltas son t´picamente de una fracci´ n porcentual del o ı o tama˜ o de una copia completa del fichero. Retrieval. el lector nunca ver´ un a a a resultado escrito parcialmente que podr´a confundirlo. En vez de almacenar una copia completa del fichero por cada revisi´ n.

e Adem´ s del efecto que tiene en la eficiencia en la recuperaci´ n. a o o 4. estos esquemas usan t´ cnicas de e compresi´ n “con p´ rdida” para aumentar la tasa de compresi´ n. Mercurial verifica que los hashes sean correctos cuando recupera revisiones de ficheros y cuando jala cambios desde otro repositorio. tanto antes como despu´ s de la secci´ n corrompida. rev 6 a 7 Figura 4.d) Delta. Si un fichero de registro se corrompe parcialmente debido a a o un error de hardware o del sistema. Mercurial s´ lo los usa a e o tras bambalinas.3: Instant´ nea de un revlog.Índice de bitácora de revisiones (archivo . Si se encuentra un problema de integridad. Esto no ser´a e o ı ´ posible con un sistema de almacenamiento basado unicamente en deltas. a menudo es posible reconstruir algunas o la mayor´a de las revisiones a partir de ı las secciones no corrompidas del fichero de registro. una entrada en un revlog contiene un hash criptogr´ fico de a o a a los datos que representa. con deltas incrementales a cada cuadro del mismo como un delta contra el cuadro predecesor. rev 2 a 3 Índice. Los hashes de identificaci´ n de conjuntos de cambios que usted ve como usuario final son de las revisiones o de la bit´ cora de cambios. Esto quiere decir que si la se˜ al de v´deo se interrumpe. Esto hace dif´cil falsificar el contenido de una revisi´ n. y hace f´ cil detectar una corrupci´ n ı o a o accidental. 39 . rev 5 a 6 Delta. se reanudar´ una vez se n ı a reciba el siguiente cuadro clave.2. Adicionalmente. por lo que los errores visuales se acumulan a lo largo o e o de una cantidad de deltas inter-cuadros. rev 7 Snapshot. Identificaci´ n e integridad fuerte o Adem´ s de la informaci´ n de deltas e instant´ neas. Aunque los ficheros de registro y el manifiesto tambi´ n usan hashes. la acumulaci´ n de errores de codificaci´ n se reinicia con cada cuadro clave. y ı n para limitar la acumulaci´ n de errores introducida por la compresi´ n con p´ rdidas. el uso peri´ dico de instant´ neas de Mercurial lo a o o a hace m´ s robusto frente a la corrupci´ n parcial de datos. Ya que existe la posibilidad de que un flujo de v´deo se “pierda” ocasionalmente debido a fallas en la se˜ al.i) Datos de Bitacora de revisiones (archivo . rev 4 Delta. Adem´ s. Los hashes proveen m´ s que una simple revisi´ n de corrupci´ n: son usados como los identificadores para las a o o revisiones. los codificadores de v´deo insertan o o e ı peri´ dicamente un cuadro completo (tambi´ n llamado “cuadro clave”) en el flujo de v´deo.4. Mercurial se quejar´ y detendr´ cualquier operaci´ n a a o que est´ haciendo. rev 4 a 5 Delta. el siguiente delta es geno e ı erado con respecto a dicho cuadro.

4 usted puede ver un ejemplo de la estructura conceptual de un revlog. se ver´ reflejado en ese conjunto n a de cambios. la primera ranura para padres contiene el ID de la revisi´ n padre. la casilla para el primer padre permanece sin cambios.3. Los ficheros de registro. Tal como la revisi´ n de un revlog tiene espacio para dos padres.4. sino para dos. con los mismos contenidos que ten´an cuando fue consignado el conjunto de cambios. All´ se detalla a ı qu´ conjunto de cambios es actualizado el directorio de trabajo. para que pueda representar tanto una revisi´ n o o normal (con un solo padre) o una fusi´ n de dos revisiones anteriores. del T. y el segundo sea el ID nulo. El directorio de trabajo En el directorio de trabajo. el conjunto de cambios m´ s reciente en el repositorio que no tiene a hijos. en ingl´ s en el original. Un par de revisiones que tenga el mismo ID n ı o o padre son ramas. Una revisi´ n que representa una fusi´ n entre ramas tiene dos IDs de revisi´ n normales en sus ranuras o o o para padres. Qu´ pasa en una consignaci´ n e o El estado de directorio almacena informaci´ n sobre los padres para algo m´ s que mero registro.5 muestra el estado normal del directorio de trabajo. como tambi´ n se ver´ n las modificaciones a cualquiera de los ficheros que Mercurial ya est´ monitoreane a e do. una revisi´ n contiene sitio no s´ lo para un padre. el nuevo conjunto de cambios dentr´ los padres del directorio de trabajo como propios. e 40 . Cuando usted actualiza el directorio de trabae jo para que contenga un conjunto de cambios particular. En una revisi´ n normal. Cuando usted usa el comando “hg update”. borrado. Historial de revisiones. El directorio de trabajo “sabe” qu´ conjunto de cambios contiene. Mercurial no toca ninguno de los ficheros del directorio de trabajo cuando usted hace la consignaci´ n. El comando “hg o parents” le indica cu´ les son los padres del estado de directorio. 5 N. a 4. y bit´ coras de cambios comparten la misma estructura. a La primera revisi´ n en un revlog (al final de la imagen) tiene como padre al ID nulo.6. y la casilla para el segundo es actualizada con el conjunto de cambios con el que usted acaba de hacer la fusi´ n. de tal manera que el primer o a padre sea el ID del nuevo conjunto de cambios. ´ Es util pensar en el directorio de trabajo como en “el conjunto de cambios que estoy a punto de enviar”.4. Mercurial usa los o a padres del estado de directorio como los padres de un nuevo conjunto de cambios cuando usted hace una consignaci´ n. ı El estado de directorio5 contiene el conocimiento de Mercurial acerca del directorio de trabajo. Mercurial usa o o un hash especial. Esto puede verse en la figura 4. y un ID nulo es almacenado en la segunda. y todos los ficheros que Mercurial est´ monitoreando e a en este directorio. el estado de directorio tiene espacio para dos o padres. a Luego de una consignaci´ n. Mercurial busca la revisi´ n adecuada del manifiesto para o averiguar qu´ ficheros estaba monitoreando cuando se hizo la consignaci´ n del conjunto de cambios. ramas y fusiones Cada entrada en el revlog de Mercurial conoce la identidad de la revisi´ n de su ancestro inmediato. en las dos ranuras disponibles o para padres. y la segunda o o contiene el ID nulo. s´ lo difieren en el tipo de datos almacenados en a o cada delta o instant´ nea. o ´ La figura 4. Cualquier fichero que usted le diga a Mercurial que fue a˜ adido.4. Dicho conjunto de cambios es la punta. recrea una copia de cada uno de esos ficheros. Cuando usted hace una fusi´ n o (“hg merge”) con otro conjunto de cambios. manifiestos. para representar la idea de “no hay padre aqu´”. al que se conoce o usualmente como su padre. Luego de eso. que tiene un unico conjunto de cambios como padre. se˜ alando as´ que la revisi´ n s´ lo tiene un padre real. En la figura 4. De hecho. s´ lo modifica el estado de o o directorio para anotar sus nuevos padres. Mercurial actualizar´ los padres del directorio de trabajo. 4. renombrado o copiado. dirstate. Este hash es simplemente una ı cadena de ceros. Mercurial almacena una instant´ nea de los ficheros del repositorio como si fueran los a de un conjunto de cambios particular. llamado el “ID nulo”. el conjunto de cambios al que usted se actualiza es almacenado en la casilla destinada al “primer padre”.1. y qu´ revisi´ n e o e o de cada fichero era la actual en ese momento.

se invoca el programa externo de fusi´ n para definir o el nuevo contenido del fichero fusionado. En otras palabras.4. la acci´ n natural a o es actualizar el directorio de trabajo al conjunto de cambios de su inter´ s.8. deber´a tener en mente un “error” com´ n.9. Discutir´ otras formas de evitar este comportamiento. el proceso es el siguiente.2. Con algunas simplificaciones. Este nuevo conjunto de cambios no tiene hijos. estar´ creando un nuevo frente. m´ s e a adelante. inicialmente sorprendente. usted podr´a desear saber en qu´ estado se encontraba su proyecto el martes pasado.4. Por ejemplo. qu´ pasa si se hacen cambios.7. En casos como estos. Los padres o ı del directorio de trabajo se convierten en los padres del nuevo conjunto de cambios. as´ que usted termina trayendo ı nuevos conjuntos de cambios a su repositorio. ı u que es usar el comando “hg pull” sin ninguna opci´ n. para fusionar los ficheros que el monitorea en los dos e conjuntos de cambios. esto casi nunca tiene consecuencias negativas. o borrarlo? e Si ambos conjuntos de cambios han modificado un fichero. y el otro no lo ha hecho (o tambi´ n lo borr´ ). Usted puede apreciar la estructura que esto crea en la figura 4. u Si un conjunto de cambios ha modificado un fichero. Y el repositorio tiene ahora dos conjuntos de cambios que no ı ´ tienen hijos. Si usted hace alı gunos cambios. y el otro no lo ha hecho. por cada fichero en los manifiestos de ambos conjuntos de cambios. Mercurial deja el primer padre del directorio de trabajo intacto. o e y porqu´ Mercurial se comporta de esta forma. y luego una consignaci´ n o o o (“hg commit”). o a porque su directorio de trabajo no es sincronizado a cualquiera que sea la nueva punta. no se hace nada con el mismo. y luego hace una consignaci´ n. Una vez se ha actualizado el directorio de trabajo a un conjunto de cambios anterior. s´ lo sorprende a la gente. Si ning´ n conjunto de cambios ha modificado un fichero. y escribe como segundo padre el conjunto de cambios contra el cual usted est´ haciendo la fusi´ n. o Si un conjunto de cambios ha modificado un fichero. Nota: Si usted es nuevo en Mercurial. Creaci´ n de un nuevo frente o Es perfectamente normal actualizar el directorio de trabajo a un conjunto de cambios diferente a la punta actual. ´ Mercurial tambi´ n debe modificar el directorio de trabajo. el comando o “hg pull” no actualiza el directorio de trabajo. Por defecto. 41 . 4.3. Esto puede requerir interacci´ n directa de parte del usuario. asegurarse de que los cambios sigan al nuevo nombre de fichero. pero el directorio de trabajo sigue usando el mismo conjunto de cambios que ten´a antes de jalar.4. se borra dicho fichero e o del directorio de trabajo. El efecto que o tiene esto se muestra en la figura 4. se le pregunta al usuario qu´ hacer: conservar el fichero modificado. Pongo la palabra “error” en comillas porque todo lo que usted debe hacer para rectificar la situaci´ n es hacer una fusi´ n (“hg merge”). e y luego se hace una consignaci´ n? Mercurial se comporta en la misma forma que describ´ anteriormente. se crea una copia del fichero con las modificaciones pertinentes en el directorio de trabajo. y el otro ha renombrado o copiado el mismo. como se muestra en a o la figura 4. Si un conjunto de cambios ha borrado un fichero. y examinar directamente los ficheros en el e directorio de trabajo para ver sus contenidos tal como estaban en el momento de hacer la consignaci´ n. as´ que se convierte en la nueva punta. Fusi´ n de frentes o Cuando usted ejecuta el comando “hg merge”. o podr´a estar buscando ı e ı ´ en todos los conjuntos de cambios para saber cu´ ndo se introdujo un fallo. pero el otro lo ha modificado. Si un conjunto de cambios borra un fichero. a estos los llamamos frentes.

Detallar´ unos cuantos de ellos aqu´. que provee una buena velocidad con una tasa de compresi´ n respetable. (Si la conexi´ n se hace sobre ssh. estos se convertir´ n en los padres del nuevo conjunto de cambios. he tratado de resaltar algunos de los aspectos m´ s importantes del dise˜ o de Mercurial. para que.5.5. la atenci´ n a o n o los detalles no para ah´. las revisiones en la bit´ cora de cambios apuntan a revisiones en el manifiesto. Sin embargo. sin requerir la interacci´ n del usuario a ı a o para resolver ning´ n conflicto. muchos de los casos son completamente o autom´ ticos.´ Hay m´ s detalles—hacer una fusi´ n tiene una gran cantidad de casos especiales—pero estas son las elecciones m´ s a o a comunes que se ven involucradas en una fusi´ n. o o Esto implica que Mercurial hace “lo correcto” cuando almacena un fichero cuyo formato original est´ comprimido. Esta combinaci´ n de algoritmo y compresi´ n del flujo completo de datos (en vez de una o o o revisi´ n a la vez) reduce sustancialmente la cantidad de bytes a transferir. Esto es necesario porque Mercurial s´ lo monitorea dos padres. Mercurial no recomprmime el flujo. Mercurial usa el algoritmo de compresi´ n “deflaci´ n” (el mismo usado o o en el popular formato de fichero zip). Mercurial recomprime el flujo completo de datos usando un algoritmo de o e compresi´ n que brinda una mejor tasa de compresi´ n (el algoritmo Burrows-Wheeler del ampliamente usado paquete o o de compresi´ n bzip2).) o ı 4. o 4. de nuevo el directorio e o e o de trabajo es “el conjunto de cambios que estoy a punto de consignar”. porque ssh puede hacer esto por s´ mismo. Si recuerda la figura 4.1. pueda obetener una idea mejor de la cantidad de esfuerzo mental invertido en el dise˜ o de un a n sistema bien dise˜ ado. a n para mostrar que se presta gran cuidado y atenci´ n a la confiabilidad y el desempe˜ o. u Cuando considere qu´ pasa cuando usted hace una consignaci´ n despu´ s de una fusi´ n. y las a 42 .5. Hay una cantidad de aspectos de la construcci´ n de Mercurial que encuentro interesantes ı o personalmente.2. El encuentra que dicho delta excede el umbral respecto al cual se deber´a almacenar una instant´ nea completa del fichero. Cuando estos tipos de ficheros son comprimidos por segunda vez. Lo hace a a tratando siempre de comprimir una instant´ nea o delta. Recompresi´ n de red o Cuando almacena las revisiones en disco. la e o posibilidad de confundir al usuario y crear un desorden terrible en la fusi´ n se hace incontenible de inmediato. si e ı usted est´ interesado. cuando se transmiten datos de revisiones a trav´ s de una conexi´ n de red. pero usted debe consignar los resultados de cada fusi´ n sucesiu o vamente. a Mercurial le permite hacer m´ ltiples fusiones. ˜ Otras caracter´sticas de diseno interesantes ı En las secciones anteriores. aparte de los elementos “importantes” de arriba. Sin o embargo. Aunque t´ cnicamente es posible fusionar varios conjuntos de trabajo en una sola operaci´ n. Compresi´ n ingeniosa o Cuando es adecuado. por lo que Mercurial almacenar´ el a o a fichero zip o JPEG original. as´ que almacena la instant´ nea. tanto para las revisiones como para los o directorios de trabajo. ahorrando espacio ı a ı a ´ de nuevo respecto al enfoque simplista de usar unicamente deltas. Una vez termina su trabajo el comando “hg ´ merge”. y conservando la versi´ n comprimida s´ lo si es m´ s peque˜ a a o o a n que la versi´ n sin compresi´ n. n 4. Como usted puede ver. Mercurial descomprime los datos e o comprimidos de las revisiones. y Mercurial de nuevo hace “lo correcto” en estos casos. Mercurial almacenar´ tanto las instant´ neas como los deltas en formato comprimido. a como un fichero zip o una imagen JPEG. el fichero resultante usualmente es m´ s grande que la versi´ n comprimida una sola vez. el directorio de trabajo tiene dos padre. y de hecho la mayor´a de las fusiones terminan autom´ ticamente. Si la conexi´ n es hecha a trav´ s de HTTP. Reordenado de lectura/escritura y atomicidad A˜ adir datos al final de un fichero no es todo lo que hace falta para garantizar que un lector no ver´ una escritura n a parcial.2. brindando as´ un mejor desempe˜ o de red o ı n sobre casi todo tipo de redes. Los deltas entre revisiones de un fichero comprimido usualmente son m´ s grandes que las instant´ neas del mismo a a ´ fichero.

Un lector empieza leyendo datos a de la bit´ cora de cambios. Esto significa que sus guiones autom´ ticos diarios no se quedar´ n esperando para siempre. 6 N. Si hubiera un estado de directorio por cada directorio que Mercurial monitorea. y nunca leer´ un apuntador a una revisi´ n parcialmente escrita del fichero de a a o registro desde el manifiesto. se crea un “enlace duro”. y luego renombra at´ micamente este fichero temporal a dirstate6 . por ejemplo. Para evitar la posibilidad de leer una copia parcialmente escrita del fichero de ı ´ estado de directorio. lo que por supuesto se convierte en una fuente de todo tipo de problemas administrativos y de seguridad bastante molestos. por ejemplo. s´ lo necesitan permisos de lectura. as´ que no la d´ por hecha! Muchos de ellos requieren que los lectores sean capaces ı e de bloquear el repositorio antes de poder leerlo. Mercurial no requiere un bloqueo para leer el fichero de estado de directorio. Esta jerarqu´a es deliberada. y no parcialmente escrito. Si lo a es. revisa si la cantidad de nombres apuntando al fichero es de m´ s de uno. un lector nunca ver´ un apuntador a una versi´ n parcialmente escrita de revisiones del a a o manifiesto desde la bit´ cora de cambios.5. luego del manifiesto. el proceso que intenta escribir fallar´ por tiempo de a espera m´ ximo. y finalmente del fichero de registro. 4. ya ı n que cualquier movimiento de brazo es mucho m´ s costoso que incluso una operaci´ n de lectura relativamente grande. apil´ ndose a a a a si el sistema se cay´ sin que nadie se diera cuenta. Evitar movimientos de brazo Un aspecto cr´tico para el desempe˜ o de Mercurial es evitar los movimientos del brazo de lectura del disco duro. As´ se garantiza que el fichero o ı llamado dirstate est´ completo. Esto tiene un gran a u a efecto en la escalabilidad. Si un repositorio est´ bloqueado. a La naturaleza carente de bloqueos de la lectura significa que si usted est´ compartiendo un repositorio en un a sistema multiusuario. del T. a Como el escritor siempre termina de escribir los datos en el fichero de registro y en el manifiesto antes de escribir a la bit´ cora de cambios. Mercurial tambi´ n usa un esquema de “copiar al escribir” cuando clona un repositorio en un mismo medio de e almacenamiento local.revisiones en el manifiesto apuntan a revisiones en ficheros de registro. a´ n si se est´ escribiendo al repositorio mientras se hace la lectura. as´ que Mercurial hace una nueva copia del fichero. que es una manera sucinta de decir “estos dos nombres apuntan al mismo fichero”. (S´. En vez de copiar cada fichero de revlog del repositorio viejo al nuevo. a o Es por esto que. e 4. Mercurial escribe a un fichero con un nombre unico en el mismo directorio del fichero de estado de directorio. el estado de directorio es almacenado como un solo fichero. usted puede tener cualquier cantidad de procesos Mercurial leyendo datos de un repositorio de manera segura al mismo tiempo. no necesita dar a los usuarios locales permisos de escritura a su repositorio para que ellos puedan clonarlo o jalar cambios.3. Estado de directorio. Acceso concurrente El reordenado de lectura/escritura y la atomicidad garantizan que Mercurial nunca necesita bloquear un repositorio cuando est´ leyendo datos. o ´ s´ se usa un bloqueo para escribir a el. ı Un escritor inicia una transacci´ n al escribir los datos del ficheros del fichero de registro y el manifiesto. y esto requiere acceso de escritura en al menos un directorio. y no o escribe nada en la bit´ cora de cambios hasta que dichas escrituras hayan terminado. En ı cambio. Cuando Mercurial est´ a punto de a escribir a uno de los ficheros de revlog.4. privada para este a a ı repositorio. el disco har´a un movimiento de brazo por cada directorio.5. como NFS). (Esta no es una caracter´stica com´ n entre los o ı u sistemas de control de revisiones. los escritores esperar´ n un buen rato para revisar si el repositorio ya ha sido desbloa a queado.) Mercurial usar bloqueos para asegurarse de que s´ lo un proceso pueda escribir a un repositorio al mismo tiempo o (el mecanismo de bloqueo es seguro incluso sobre sistemas de ficheros notoriamente hostiles al bloqueo. de o ı a cero a infinito). 43 . Acceso seguro al estado de directorio Al igual que con los datos de revisi´ n. m´ s de un repositorio est´ usando el fichero. pero si el repositorio sique bloqueado por mucho tiempo. Mercurial lee el estado de directorio completo en un solo paso. el tiempo de espera m´ ximo es configurable. sin importar si se est´ escribiendo al mismo o no.

5. el fichero no ha sido modificado. se usa el estado de directorio a para almacenar informaci´ n extra para poder determinar efecientemente si usted ha modificado un fichero. n Mercurial actualiza el estado de directorio para saber qu´ hacer con dichos ficheros cuando usted haga la consignaci´ n. Si el tama˜ o del fichero ha cambiado. revisa primero la fecha de a modificaci´ n del fichero. 44 . Otros contenidos del estado de directorio Debido a que Mercurial no lo fuerza a indicar si usted est´ modificando un fichero. se almacena el momento en que Mercurial modific´ por ultima vez el fichero. pero el tama˜ o no.Algunos desarrolladores de control de revisiones han indicado que la idea de hacer una copia privada completa de un fichero no es eficiente desde el punto de vista de almacenamiento. renombra (“hg rename”) o copia (“hg copy”) ficheros. o n el fichero ha sido modificado. cada uno de los cuales es mucho m´ s importante para la “sensaci´ n” que se tiene del software en el trabajo a o d´a a d´a. Si no ha cambiado. es o o n necesario leer el contenido del fichero para revisar si ha cambiado. lo que brinda una mejora en el rendimiento grande. comparado con otros sistemas de control de revisiones. y este m´ todo brinda el m´ ximo rendimiento al tiempo que delega la mayor parte del trabajo de manejo de e a ficheros al sistema operativo.5. Almacenar estos pocos datos reduce dram´ ticaa mente la cantidad de datos que Mercurial debe leer. remueve (“hg remove”). S´ lo en el caso en que el tiempo de modificaci´ n ha cambiado. y el o tama˜ o del fichero en ese momento. n Cuando usted a˜ ade (“hg add”). Por cada o ´ fichero en el directorio de trabajo. el almacenamiento es barato. e o Cuando Mercurial est´ revisando el estado de los ficheros en el directorio de trabajo. Aunque esto es cierto. ı ı 4. Un esquema alternativo seguramente reducir´a el desempe˜ o y aumentar´a la complejidad ı n ı del software.

.. Primer padre 000000000000 Segundo padre 000000000000 Figura 4.. Primer padre ff9dc8bc2a8b Segundo padre 000000000000 Primer padre ecacb6b4c9fd Segundo padre 000000000000 Hash de revisión ecacb6b4c9fd Datos de revisión (delta o snapshot) .. Primer padre 34b8b7a15ea1 Segundo padre 000000000000 Hash de revisión 34b8b7a15ea1 Revisión de fusión (dos padres) Datos de Revisión (delta o snapshot) .Hash de revisión 1b67dc96f27a Revisión principal (sin hijos) Datos de revisión (delta o snapshot) ...... Hash de revisión 32bf9a5f22c0 Datos de revisión (delta o snapshot) . Ramas (dos revisiones.4: 45 .. mismo padre) Hash de revisión ff9dc8bc2a8b Primer padre ff9dc8bc2a8b Segundo padre 000000000000 Primera revisión (ambos padres nulos) Datos de revisión (delta o snapshot) .. Primer padre 5b80c922ebdd Segundo padre 32bf9a5f22c0 Hash de revisión 5b80c922ebdd Datos de revisión (delta o snapshot) ..

Historia en el repositorio Padres del directorio de trabajo Primer padre e7639888bb2f e7639888bb2f 7b064d8bac5e Segundo padre 000000000000 000000000000 Figura 4.5: El directorio de trabajo puede tener dos padres Historia en el repositorio Padres del directorio de trabajo Primer padre Nuevo conjunto de cambios dfbbb33f3fa3 dfbbb33f3fa3 e7639888bb2f Segundo padre 7b064d8bac5e 000000000000 000000000000 Figura 4.6: El directorio de trabajo obtiene nuevos padres luego de una consignaci´ n o 46 .

7: El directorio de trabajo. actualizado a un conjunto de cambios anterior Cabeza Pre−existente Cabeza recién creada (y tip) Padres del directorio de trabajo Primer padre e7639888bb2f ffb20e1701ea ffb20e1701ea 7b064d8bac5e Segundo padre 000000000000 000000000000 Figura 4.Historia en el repositorio Padres del directorio de trabajo Primer padre e7639888bb2f 7b064d8bac5e 7b064d8bac5e Segundo padre 000000000000 000000000000 Figura 4.8: Despu´ s de una consignaci´ n hecha mientras se usaba un conjunto de cambios anterior e o 47 .

Cabeza pre−existente Cabeza recién creada(y tip) Padres del directorio de trabajo Primer padre (sin cambio) e7639888bb2f ffb20e1701ea ffb20e1701ea 7b064d8bac5e Segundo padre e7639888bb2f 000000000000 Figura 4.9: Fusi´ n de dos frentes o 48 .

Nombramiento expl´cito e impl´cito de ficheros ı ı ´ Mercurial tiene un comportamiento util en el cual si a una orden. Continuar´ haciendo seguimiento a los cambios que haga o a sobre el fichero cada vez que consigne. pero que no han cambiado. los ficheros que haya adicionado antes de consignar no se listar´ n en la salida e a de “hg status”. Una vez que haya adicionado el fichero.Cap´tulo 5 ı Mercurial d´a a d´a ı ı 5. a a Para indicarle a Mercurial que tenga en cuenta un fichero. m´ s o a adelante hablaremos de ello. Mercurial no hace nada con el inmediatamente. se emplea un “?” para mostrar tales ficheros. la l´nea referente al fichero al aplicar la orden “hg status” para tal fichero cambia de “?” a “A”. a 1 2 3 4 $ $ $ $ mkdir b echo b > b/b echo c > b/c mkdir b/d 49 . todas las ´ ordenes lo interpretar´ n como “Deseo operar en cada fichero de este directorio y sus subdirectorios”. tomar´ una instant´ nea n a a del estado del fichero la pr´ xima vez que usted consigne. (De todas maneras. ı 1 2 3 4 5 6 7 8 9 10 $ $ $ $ ? $ $ A $ $ hg init add-example cd add-example echo a > a hg status a hg add a hg status a hg commit -m ’Added one file’ hg status Despu´ s de invocar “hg commit”.1. En cambio. La orden “hg ı status” le mostrar´ cu´ les ficheros son desconocidos para Mercurial. C´ mo indicarle a Mercurial qu´ ficheros seguir o e Mercurial no trabaja con ficheros en su repositorio a menos que usted se lo indique expl´citamente. puede obtener tal informaci´ n.1. le pasa el nombre de un directorio. Si tiene un repositorio que contiene miles de ficheros. La raz´ n para esto es que “hg status” solamente le muestra aquellos ficheros “interesantes” — o los que usted haya modificado o a aquellos sobre los que usted haya indicado a Mercurial hacer algo— de forma predeterminada. emplee la orden “hg add”.1.) ´ Cuando usted a˜ ade un fichero. 5. hasta que usted lo elimine. rara vez desear´ saber cu´ les de ellos est´ n a a a siendo seguidos por Mercurial.

hidden $ hg add empty/. ı ´ Los directorios vac´os rara vez son utiles. y hay soluciones alternativas no intrusivas que usted puede emplear para ı obtener el efecto apropiado. no directorios Mercurial no da seguimiento a la informaci´ n de los directorios. Una es crear un directorio. 0 files removed. a ´ y reducir en lo posible una sorpresa silenciosa pero fatal. a o Cuando hacemos impl´citos los nombres de los ficheros dando el nombre de un directorio.. pero tiene una consecuencia pr´ ctica menor: no es posible representar un directorio a completamente vac´o en Mercurial. 5. Los desarrolladores de Mercurial pensaron que la complejidad necesaria para administrar directorios vac´os no val´a la pena frente al beneficio limitado que esta caracter´stica podr´a traer. e ı Suena como una diferencia trivial. borra todos los directorios vac´os que estuvieran en la ruta del fichero borrado. Despu´ s de borrar un fichero. mientras que o no lo hizo en el ejemplo anterior cuando adicionamos el fichero con nombre a. En lugar de eso tiene en cuenta las rutas de o los ficheros.2. Antes de crear un fichero.”) es tratado como oculto por la mayor´a de comandos y herramientas GUI. 0 files merged. 50 . ı ı ı ı Si necesita un directorio vac´o en su repositorio. y ı a ı Mercurial asume en tales casos que usted sabe lo que est´ haciendo y no imprime informaci´ n alguna. Esta ı aproximaci´ n se ilustra en la figura 5. primero crea todos los directorios que hagan falta para completar la ruta del mismo. Esto para aclarar lo que est´ sucediendo. cualquier fichero cuyo e nombre comience con un punto (“. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ hg init hidden-example $ cd hidden-example $ mkdir empty $ touch empty/. 0 files unresolved $ ls tmp empty $ ls tmp/empty Figura 5. ´ ´ En el ultimo caso hicimos expl´cito el nombre del fichero que dese´ bamos adicionar en la l´nea de ordenes. ı despu´ s hacer “hg add” a un fichero “oculto” dentro de ese directorio. Nota al margen: Mercurial trata ficheros.1. hay algunas formas de lograrlo. Mercurial efect´ a el ı u paso extra de imprimir el nombre de cada fichero con el que va a hacer algo.hidden $ hg commit -m ’Manage an empty-looking directory’ $ ls empty $ cd . $ hg clone hidden-example tmp updating working directory 1 files updated. En sistemas tipo Unix.1: Simular un directorio vac´o con un fichero oculto ı Otra forma de abordar la necesidad de un directorio vac´o es simplemente crear uno en sus guiones de construcci´ n ı o antes de que lo necesiten.5 6 7 8 9 10 $ echo d > b/d/d $ hg add b adding b/b adding b/c adding b/d/d $ hg commit -m ’Added all files in subdirectory’ Tenga en cuenta que en este ejemplo Mercurial imprimi´ los nombres de los ficheros que se adicionaron. Este comportamiento es com´ n a la mayor´a de ordenes en u ı Mercurial.1.

Si actualiza su directorio de trabajo a un conjunto de cambios en el cual el fichero que elimin´ a´ n era tenido en o u ´ cuenta. Ficheros perdidos Mercurial considera como perdido un fichero que usted borr´ . o o Al eliminar un fichero no se altera de ninguna manera el historial del mismo. este reaparecer´ en el directorio de trabajo. con los contenidos que este ten´a cuando se consign´ tal conjunto a ı o de cambios. Al eliminar un fichero no se afecta su historial Es preciso tener en cuenta que eliminar un fichero tiene s´ lo dos efectos. pero para el que no se us´ “hg remove”. Si decide recrear un fichero con el mismo nombre y desea que Mercurial le haga seguimiento.1. a 5. use la orden “hg remove”.2. o Mercurial deja de hacer seguimiento a los cambios del fichero desde la pr´ xima consignaci´ n. Mercurial lo eliminar´ de nuevo del directorio de trabajo. 1 2 3 4 5 6 7 8 9 10 11 12 13 $ hg init remove-example $ cd remove-example $ echo a > a $ mkdir b $ echo b > b/b $ hg add a b adding b/b $ hg commit -m ’Small example for file removal’ $ hg remove a $ hg status R a $ hg remove b removing b/b Despu´ s de hacer “hg remove” a un fichero. se borrar´ el fichero y le a indicar´ a Mercurial que deje de hacerle seguimiento.2. Si usted actualiza el directorio de trabajo a un conjunto de cambios posterior en el cual el fichero hab´a ı sido eliminado. C´ mo dejar de hacer seguimiento a un fichero o Si decide que un fichero no pertenece a su repositorio. Mercurial sabr´ que el fichero recientemente adicionado a no est´ relacionado con el fichero anterior que ten´a el mismo nombre.2. 1 2 3 4 5 6 7 8 $ $ $ $ $ $ $ ! hg init missing-example cd missing-example echo a > a hg add a hg commit -m ’File about to be missing’ rm a hg status a 51 .5. basta con hacerle “hg add”. incluso si recrea el e a fichero con el mismo nombre en su directorio de trabajo. Los o o ´ ficheros perdidos se representan con “!” al visualizar “hg status”. Mercurial dejar´ de hacer seguimiento al mismo. Las ordenes de Mercurial generalmente no har´ n a nada con los ficheros perdidos. Los ficheros eliminados se representan con “R” al usar “hg a status”.2. o Se elimina la versi´ n actual del fichero del directorio de trabajo. a ı 5.

1 2 3 $ hg remove --after a $ hg status R a Por otro lado. si borr´ un fichero perdido por accidente. Reaparecer´ . Al principio del desarrollo de Mercurial.3. seguido inmediatamente o de una consignaci´ n.2. puede usar “hg revert nombre de fichero” para o recuperar el fichero. a 5. En la pr´ ctica.Si su repositorio contiene un fichero que “hg status” reporta como perdido. o a 52 . o 1 2 3 $ echo c > c $ hg commit -A -m ’Commit with addremove’ adding c 5. 1 2 3 4 5 6 7 $ hg init addremove-example $ cd addremove-example $ echo a > a $ echo b > b $ hg addremove adding a adding b La orden “hg commit” se puede usar con la opci´ n -A que aplica el mismo agregar-eliminar.4. ´ Atajo util—agregar y eliminar ficheros en un solo paso Mercurial ofrece una orden combinada. Los ficheros copiados se tratan de forma especial cuando usted hace una fusi´ n con el trabajo de alguien m´ s.3. Cuando se copia un fichero con esta orden. resultaba muy sencillo borrar un fichero accidentalmente sin darse cuenta. Nota al margen: ¿Por qu´ decirle expl´citamente a Mercurial que elimine un fichero? e ı Es posible que se haya preguntado por qu´ Mercurial exige que usted le indique expl´citamente que est´ borrando e ı a un fichero. Copiar ficheros Mercurial ofrece la orden “hg copy” para hacer una copia nueva de un fichero. que agrega los ficheros que no tienen seguimiento y marca los ficheros faltantes como eliminados. sin modificaciones. Mercurial lleva un registro indicando que el nuevo fichero es una copia del fichero original. Mercurial se ı a dar´a cuenta de la ausencia del fichero autom´ ticamente despu´ s de la ejecuci´ n de “hg commit”. y desea que el mismo se vaya.2. este permit´a que usted borrara el fichero sin m´ s. a 1 2 3 4 $ hg revert a $ cat a a $ hg status 5. se puede usar “hg remove --after” posteriormente para indicarle a Mercurial que usted deseaba borrar tal fichero. y dejar´a de hacer ı a e o ı seguimiento al fichero. “hg addremove”.

a 1 2 3 4 5 6 $ hg pull ./my-copy pulling from . 1 2 $ hg status A new-file Pero si usamos la opci´ n -C de la orden “hg status”. hagamos un cambio en paralelo.. Cuando jalemos los cambios del primer repositorio y fusionemos las dos cabezas. Comeno zaremos con el mini repositorio usual que contiene un solo fichero 1 2 3 4 5 $ $ $ $ $ hg init my-copy cd my-copy echo line > file hg add file hg commit -m ’Added a file’ Debemos hacer algo de trabajo en paralelo. Para ilustrar lo que esto significa... 0 files removed.5. 0 files unresolved De vuelta en el repositorio inicial. se imprimir´ otra l´nea: el fichero desde el cual fue copiado o a ı nuestro fichero reci´ n a˜ adido. Adicionaremos una l´nea de contenido al ı fichero original que creamos. e n 1 2 3 4 $ hg status -C A new-file file $ hg commit -m ’Copied file’ Ahora. usemos la orden “hg copy” para hacer una copia del primer fichero que creamos. $ hg clone my-copy your-copy updating working directory 1 files updated. haremos un ejemplo. de forma que tengamos algo para fusionar. ı 1 2 3 4 $ cd . Aqu´ clonamos el repositorio.. 1 2 $ cd my-copy $ hg copy file new-file Si vemos la salida de la orden “hg status”. en el repositorio que clonamos. 0 files merged.1.3. Mercurial propagar´ los cambios que hemos hecho localmente en file a su copia. el fichero copiado luce tal como un fichero que se ha a˜ adido n normalmente./your-copy $ echo ’new contents’ >> file $ hg commit -m ’Changed file’ Hemos modificado el fichero file en este repositorio./my-copy searching for changes adding changesets adding manifests adding file changes 53 . Resultados de copiar un fichero durante una fusi´ n o Durante una fusi´ n los cambios “siguen” una copia. new-file. 1 2 3 $ cd .

3. 1 files merged. C´ mo hacer que los cambios no sigan a la copia? o Si por alg´ n motivo usted decide que esta caracter´stica de propagaci´ n autom´ tica de cambios en las copias u ı o a no es para usted. y se modifica el fichero original durante el curso normal de su trabajo. Antes de hacerlo. y ha comenzado a trabajar sobre su copia del fichero. y por esta raz´ n Mercurial propaga unicamente los o cambios en las copias hasta este punto y no m´ s all´ . 1 2 $ mkdir k $ hg copy a k 54 . y todos los argumentos previos son las fuentes. Esto significa que si usted hace modificaciones a un fichero. a menos que usted haya recordado propagar el arreglo del fallo a mano. gracias a la propagaci´ n autom´ tica del cambio que arregl´ el fallo o a o del fichero original.) La orden “hg copy” act´ a de forma parecida a la orden cp de Unix (puede usar el alias “hg cp” si le es m´ s u a ´ c´ modo). Mercurial hace una copia de cada fichero fuente tal como se encuentra en el directorio actual. y tome una decisi´ n asegur´ ndose que este comportamiento no es el apropiado para su caso espec´fico. y le aplica “hg copy” sin haber consignado primero los cambios. Digamos que yo he aplicado un o o arreglo de un fallo importante a un fichero fuente y consign´ los cambios. a a 5.3. Comportamiento de la orden “hg copy” Cuando usa la orden “hg copy”. de todas maneras. o o a ı 5. el mismo permanecer´a en su copia ı del fichero. (Este a e comportamiento me parece poco intuitivo. Por otro lado.7 8 9 10 11 12 13 14 15 added 1 changesets with 1 changes to 1 files (+1 heads) (run ’hg heads’ to see heads. y posteriormente use “hg add” sobre la nueva copia hecha a mano. 0 files removed. es cp). don’t forget to commit) $ cat new-file line new contents 5. Mercurial previene esta clase de problemas. usualmente no es necesario o ´ propagar los cambios el fichero original a las copias del mismo. y por tal motivo lo menciono. a Explicaremos a continuaci´ n la raz´ n de este comportamiento de Mercurial.3. usted decidi´ hacer “hg e o copy” sobre el fichero en su repositorio. relea la secci´ n 5.4.2. su fichero fuente tendr´a ı el fallo. se crea un fichero nuevo con ese nombre. Si jala y fusiona mis cambios y Mercurial no hubiera propagado los cambios en las copias. ’hg merge’ to merge) $ hg merge merging file and new-file 0 files updated. pero ı e en la mayor´a de casos es absolutamente deseable. El ultimo argumento es el destino. Hasta donde s´ .3. sin saber acerca del fallo o sin ver el arreglo. Por lo tanto si sobre un fichero se usa “hg copy”. a ´ Lo segundo a tener en cuenta es que las modificaciones solamente se propagar´ n en las copias unicamente si los a repositorios de los cuales est´ jalando los cambios no saben de la copia. y el destino no existe. 0 files unresolved (branch merge. simplemente use la orden usual de su sistema para copiar ficheros (en sistemas tipo Unix. nada pasar´ .3.2. Cuando su historial de cambios tiene un registro de la copia y la subsecuente fusi´ n. Si solamente indica un o fichero como la fuente. la nueva copia contendr´ tambi´ n las modificaciones que haya hecho hasta ese punto. Mercurial es el unico sistema de control de revisiones que propaga los cambios e ´ en las copias de esta forma. Es indispensable recordar que esta propagaci´ n solamente sucede ı o cuando fusionamos. ¿Por qu´ los cambios se reflejan en las copias? e Este comportamiento de cambios en ficheros que se propagan a las copias de los ficheros parecer´a esot´ rico.

si copia un fichero manualmente y desea que Mercurial sepa que ha copiado un fichero. La raz´ n por la cual discut´ la a u o ı orden “hg copy” antes de hablar acerca de cambiar el nombre de los ficheros. e Cuando usa la orden “hg rename”. Mercurial hace una copia de cada fichero fuente. 1 2 $ hg copy c e copying c/a/c to e/a/c Si tanto la fuente como el destino son directorios. Mercurial copia las fuentes en este. 1 2 3 4 $ mkdir d $ hg copy a b d $ ls d a b La copia de un directorio es recursiva. lo borra y lo marca como fichero eliminado. 1 2 3 4 $ hg status -C A b a R a 55 . es que Mercurial trata el renombrar un fichero de la misma forma que una copia. 1 2 3 $ hg status A b R a De la misma forma en que se usa la orden “hg copy”. la estructura de la fuente se recrea en el directorio destino. basta con aplicar la opci´ n --after a la orden “hg copy”. o 1 2 $ cp a z $ hg copy --after a z 5.3 4 $ ls k a ´ Si el destino es un directorio. Renombrar ficheros La necesidad de renombrar un fichero es m´ s com´ n que hacer una copia del mismo. y preserva la estructura del directorio fuente. n ahora eliminado. debemos usar la opci´ n -C de la orden “hg status” para o verificar que el fichero a˜ adido realmente comienza a ser seguido por Mercurial como una copia del fichero original. 1 $ hg rename a b La orden “hg status” muestra la nueva copia del fichero como a˜ adida y el fichero inicial de la copia. 1 2 $ hg copy c d copying c/a/c to d/c/a/c De la misma forma que la orden “hg rename”.4. como elimin nado. Por lo tanto. saber lo que hace Mercurial cuando usted copia un fichero le indica qu´ esperar cuando renombra un fichero.

5. e e Si yo modifico un fichero y usted lo renombra a un nuevo fichero./orig $ hg pull -u . 1 2 3 4 5 6 7 # See http://www./anne searching for changes adding changesets adding manifests 56 .” deber´a ser claro que el seguimiento de cambios de un renombramiento es ı definitivamente importante.1... 0 files removed. y posteriormente fusionamos nuestros respectivos cambios. Renombrar ficheros y fusionar cambios Dado que el renombrado de Mercurial se implementa como un copiar-y-eliminar. e 1 2 3 4 5 6 $ hg clone orig anne updating working directory 1 files updated. Cambios de nombre divergentes y fusi´ n o El caso de renombramiento con nombres divergentes ocurre cuando dos desarrolladores comienzan con un fichero— llam´ moslo foo—en sus repositorios respectivos. 0 files merged.” pero.. 1 2 3 $ cd anne $ hg mv foo bar $ hg ci -m ’Rename foo to bar’ Mientras que Bob lo renombra como quux. 5. Sin esto.4.2. puede indic´ rsele a Mercurial acerca de un renombramiento inmediato a con la opci´ n --after.4. (Es lo o a que se esperar´a que “simplemente funcione. 0 files unresolved Anne renombra el fichero a bar./anne pulling from . mi modificaci´ n al fichero bajo su nombre original se propagar´ en el fichero con el nuevo nombre.. son similares a la o orden “hg copy” en casi todo.selenic. 1 2 3 $ cd . no todos los sistemas de control de revisiones hacen esto. puede ser util. 0 files unresolved $ hg clone orig bob updating working directory 1 files updated. ı ¿Qu´ cree que deber´a pasar cuando fusionen su trabajo? El comportamiento de Mercurial es que siempre preserva e ı ambos nombres cuando fusiona los conjuntos de cambios que contienen nombres divergentes.com/mercurial/bts/issue455 $ cd .) ı Aunque el hecho de que los cambios sigan la copia es una caracter´stica respecto a la cual usted puede estar ı ´ de acuerdo y decir “si. la misma propagaci´ n de cambios o ocurre cuando usted fusiona despu´ s de renombrar como despu´ s de hacer una copia. 0 files removed.Igual que con “hg remove” y “hg copy”. El comportamiento de la orden “hg rename” y las opciones que acepta./bob $ hg mv foo quux $ hg ci -m ’Rename foo to quux’ Veo esto como un conflicto porque cada desarrollador ha expresado intenciones diferentes acerca de c´ mo consido era deber´a haberse nombrado el fichero. 0 files merged. ser´a muy sencillo que los cambios se quedaran atr´ s cuando los ficheros se ı a renombran.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ hg init issue29 $ cd issue29 $ echo a > a $ hg ci -Ama adding a $ echo b > b $ hg ci -Amb adding b $ hg up 0 0 files updated. 0 files merged. ’hg merge’ to merge) $ hg merge warning: detected divergent renames of foo to: bar quux 1 files updated. y le permite a usted o guiar la situaci´ n a una resoluci´ n adecuada.3./bob searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run ’hg heads’ to see heads.. 0 files unresolved $ hg pull . Cambios de nombre convergentes y fusi´ n o Otra clase de conflicto al cambiar el nombre de ficheros ocurre cuando dos personas eligen renombrar diferentes ficheros fuente al mismo destino. 29. Esto est´ documentado como Fallo de a Mercurial No..4. 0 files removed. En este caso Mercurial aplica su maquinaria de fusi´ n usual. don’t forget to commit) $ ls bar quux Tenga en cuenta que Mercurial le advierte acerca de nombres divergentes. mientras que en otro hay un directorio con el mismo nombre. 0 files merged. 1 files removed. Otros casos l´mite relacionados con renombramientos ı Mercurial tiene un fallo de mucho tiempo en el cual no es capaz de fusionar cuando por un lado hay un fichero con un nombre dado. o o 5. e o 5. 0 files unresolved (branch merge.4./bob pulling from . 0 files merged. 0 files unresolved $ mkdir b $ echo b > b/b $ hg ci -Amc adding b/b created new head $ hg merge abort: Is a directory: /tmp/issue29HYiaCx/issue29/b 57 . 1 files removed.8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 adding file changes added 1 changesets with 1 changes to 1 files 1 files updated. pero deja que usted decida qu´ hacer e con la divergencia despu´ s de la fusi´ n.4.

5. ni seguido por Mercurial. Recuperarse de equivocaciones ´ Mercurial tiene unas ordenes poderosas que le ayudar´ n a recuperarse de equivocaciones comunes. pero sus opciones pueden estar m´ s ı a limitadas. Por ejemplo. Cuando haya consignado un cambio. no ser´ adicionado. puede hacer algo todav´a. ejecute “hg revert” con el nombre del fichero que a˜ adi´ .5. ı 58 . si aplic´ “hg add” a un fichero por accidente. si decide que era un error. Tambi´ n puede usar a e “hg revert” para deshacerse de cambios err´ neos a un fichero. a La orden “hg revert” le permite deshacer cambios que haya hecho a su directorio de trabajo. y en tanto o n o que el fichero no haya sido tocado de forma alguna. vea o o el cap´tulo 9. o Tenga en cuenta que la orden “hg revert” se usa para cambios que no han sido consignados. Para obtener informaci´ n acerca de la orden “hg revert” y detalles de c´ mo tratar con cambios consignados.

6. 59 . Esto le permite “subscribirse”a un repositorio usando su herramienta de lectura de notificaciones favorita. Para uso interactivo. Vea la secci´ n 6. Mercurial ofrece dos formas de hacerlo. a La primera es usando la orden “hg serve”. Modelos de colaboraci´ n o Con una herramienta adecuadamente flexible.com/repo/hg?style= gitweb. El protocolo de entunelamiento HTTP de Mercurial a comprime datos agresivamente.2. es bueno tener herramientas y ejemplos a la mano al pensar en posibles modelos de flujo de trabajo. Si est´ interesado en proveer una interfaz web a sus propios repositorios. La interfaz web de Mercurial ´ Mercurial tiene una poderosa interfaz web que provee bastantes capacidades utiles. y (cuando el servidor e est´ configurado para permitirlo) empujar cambios al mismo. examinar cada cambio (comentarios y diferencias). Me gusta mucho m´ s este modelo que el estar suscrito a una lista de a correo a la cual se env´an las notificaciones. dado que no requiere configuraci´ n adicional de parte de quien sea que ı o est´ administrando el repositorio. 6. si el control distribuido de versiones es nuevo para usted. tomar decisiones acerca del flujo de trabajo es mucho m´ s un reto a de ingenier´a social que un problema t´ cnico. que es a manejado por todos los servidores web comunes.selenic. Mercurial impone pocas limitaciones sobre c´ mo puede estructurar el ı e o flujo de trabajo en un proyecto. jalar cambios.4 m´ s adelante. Adicionalmente la interfaz provee notificaciones RSS de los cambios del repositorio. Si tiene un repositorio que desea hacer disponible a o o a de forma permanente. Sin embargo.Cap´tulo 6 ı Colaborar con otros Debido a su naturaleza descentralizada. la interfaz le permite visualizar uno o varios repositorios. Puede ver el historial de un repositorio. como por ejemplo el repositorio principal de Mercurial en http://www. as´ que depende de usted y de su grupo definir y trabajar con un modelo que se ajuste ı a sus necesidades particulares. Mercurial no impone pol´tica alguna de c´ mo deben trabajar los grupos ı o de personas. y ver los contenidos de cada directorio y fichero. Para a m´ s detalles de c´ mo usar esta orden vea la secci´ n 6. a La interfaz web tambi´ n permite a los usuarios remotos clonar repositorios. La forma m´ s sencilla de empezar a trabajar con la interfaz web es usar su navegador para visitar un repositorio a existente. Mercurial tiene soporte embebido para el est´ ndar CGI (Common Gategay Interface).6 para los detalles de la configuraci´ n a trav´ s de o o e CGI.1. y ser notificado autom´ ticamente de la aca tividad en el repositorio tan pronto como sucede. que est´ enfocada a servir “de forma liviana” y por intervalos cortos. de forma que trabaja eficientemente incluso en conexiones de red con poco ancho de banda.

6.2.1.

Factores a tener en cuenta

El aspecto m´ s importante que usted debe considerar de cualquier modelo es qu´ tan bien se ajusta a las necesidades a e y capacidades de la gente que lo usar´ . Esto puede parecer auto-evidente; a´ n as´, usted no puede permitirse olvidarlo a u ı ni por un momento. Una vez defin´ un modelo de flujo de trabajo que parec´a ser perfectamente adecuado para m´, pero que caus´ una ı ı ı o cantidad considerable de consternaci´ n y fricci´ n dentro de mi equipo de desarrollo. A pesar de mis intentos de exo o plicar porqu´ necesit´ bamos un conjunto complejo de ramas, y de c´ mo deb´an fluir los cambios entre ellas, algunos e a o ı miembros del equipo se molestaron. Aunque ellos eran personas inteligentes, no quer´an prestar atenci´ n a las limı o itaciones bajo las cuales est´ bamos operando, o comparar las consecuencias de esas limitaciones con los detalles del a modelo que yo estaba proponiendo. No esconda bajo la alfombra los problemas sociales o t´ cnicos que usted pueda preveer. Sin importar el esquema e que usted use, debe hacer planes para enfrentar posibles errores o problemas. Considere a˜ adir procedimientos automn atizados para prevenir, o recuperarse r´ pidamente de, los problemas que usted pueda anticipar. A manera de ejemplo, a si usted planea tener una rama en la vayan los cambios que no est´ n listos para producci´ n, har´a bien en pensar en la e o ı posibilidad de que alguien fusione accidentalmente dichos cambios en una rama para publicaci´ n. Usted podr´a evitar o ı este problema en particular escribiendo un gancho que evite que se fusionen cambios desde ramas inapropiadas.

6.2.2.

Anarqu´a informal ı

No sugerir´a un enfoque de “todo vale” como algo sostenible, pero es un modelo que es f´ cil de entender, y que ı a funciona perfectamente bien en unas cuantas situaciones inusuales. Como un ejemplo, muchos proyectos tienen un grupo informal de colaboradores que rara vez se re´ nen f´sicau ı mente. A algunos grupos les gusta evitar el aislamiento de trabajar a distancia organizando “sprints” ocasionales. En un sprint, una cantidad de gente se re´ ne en un mismo sitio (el cuarto de conferencias de una empresa, el cuarto de u ´ reuniones de un hotel, ese tipo de lugares) y pasar varios d´as m´ s o menos encerrados all´, trabajando intensamente ı a ı en un pu˜ ado de proyectos. n Un sprint es el lugar perfecto para usar el comando “hg serve”, ya que “hg serve” no requiere una infraestructura especial de servidores. Usted puede empezar a trabajar con “hg serve” en momentos, leyendo la secci´ n 6.4 m´ s o a abajo. Luego simplemente d´gale a las personas cerca suyo que usted est´ ejecutando un servidor, env´eles la URL a ı a ı trav´ s de un mensaje instant´ neo, y tendr´ de inmediato una forma r´ pida de trabajar juntos. Ellos pueden escribir su e a a a URL en un navegador web y revisar sus cambios r´ pidamente; o ellos pueden jalar un arreglo de fallo que usted haya a hecho y verificarlo; o pueden clonar una rama que contiene una nueva caracter´stica y probarla. ı Lo bueno, y lo malo, de hacer cosas de manera ad hoc como aqu´, es que s´ lo las personas que saben de sus ı o cambios, y d´ nde est´ n, pueden verlos. Un enfoque tan informal sencillamente no puede escalarse m´ s all´ de un o a a a pu˜ ado de personas, porque cada individuo tiene que saber de n repositorios diferentes de los cuales jalar. n

6.2.3.

´ Un repositorio central unico

Para proyectos peque˜ os migrando desde una herramienta centralizada de control de revisiones, tal vez la forma n ´ m´ s f´ cil de empezar es hacer que los cambios vayan a trav´ s de un repositorio central compartido. Este es tambi´ n el a a e e “bloque base” para esquemas m´ s ambiciosos de flujo de trabajo. a ´ Los colaboradores empiezan clonando una copia de este repositorio. Ellos pueden jalar cambios de el siempre que lo necesiten, y algunos (o tal vez todos los) desarrolladores tienen permiso para empujar cambios de vuelta cuando est´ n listos para que los dem´ s los vean. e a Bajo este modelo, para los usuarios tiene sentido jalar cambios directamente entre ellos, sin ir a trav´ s del reposie torio central. Considere un caso en el que yo tengo un arreglo tentativo de fallo, pero me preocupa que al publicarlo en ´ el repositorio central rompa los arboles de todos los dem´ s cuando lo jalen. Para reducir el potencial de da˜ o, puedo a n pedirle a usted que clone mi repositorio en un repositorio personal suyo y lo pruebe. Esto nos permite aplazar este cambio potencialmente inseguro hasta que haya tenido algo de pruebas. En este tipo de escenario, la gente usualmente utiliza el protocolo ssh para empujar cambios de manera segura al repositorio central, como se documenta en la secci´ n 6.5. Tambi´ n es usual publicar una copia de s´ lo lectura del o e o 60

repositorio sobre HTTP usando CGI, como en la secci´ n 6.6. Publicar a trav´ s de HTTP satisface las necesidades de o e aquellos que no tienen permiso para empujar, y de aquellos que desean usar navegadores web para explorar el historial del repositorio.

6.2.4.

Trabajo con muchas ramas

Los proyectos de cierta talla tienden de manera natural a progresar de forma simult´ nea en varios frentes. En el a caso del software, es com´ n que un proyecto tenga versiones peri´ dicas oficiales. Una versi´ n puede entrar a “modo u o o mantenimiento” por un tiempo despu´ s de su primera publicaci´ n; las versiones de mantenimiento tienden a contener e o solamente arreglos de fallos, no nuevas caracter´sticas. En paralelo con las versiones de mantenimiento, puede haber ı una o varias versiones futuras en desarrollo. La gente usa normalmente la palabra “rama” para referirse a una de las direcciones ligeramente distintas en las cuales avanza el desarrollo. Mercurial est´ especialmente preparado para administrar un buen n´ mero de ramas simult´ neas pero no id´ nticas. a u a e Cada “direcci´ n de desarrollo” puede vivir en su propio repositorio central, y usted puede mezclar los cambios de una o a otra cuando sea necesario. Dado que los repositorios son independientes entre s´, los cambios inestables de una rama ı de desarrollo nunca afectar´ n una rama estable a menos que alguien mezcle expl´citamente los cambios. a ı A continuaci´ n hay un ejemplo de c´ mo podr´a hacerse esto en la pr´ ctica. Digamos que tiene una “rama principal” o o ı a en un servidor central.
1 2 3 4 5

$ hg init main $ cd main $ echo ’This is a boring feature.’ > myfile $ hg commit -A -m ’We have reached an important milestone!’ adding myfile Alguien lo clona, hace cambios locales, los prueba, y los empuja de vuelta. Una vez que la rama principal alcanza un hito de proyecto se puede usar la orden “hg tag” para dar un nombre permanente a la revisi´ n del hito. o

1 2 3 4 5 6 7 8 9 10 11

$ hg tag v1.0 $ hg tip changeset: 1:471e84684405 tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:16 2009 +0000 summary: Added tag v1.0 for changeset a1e37e7a184f $ hg tags tip v1.0

1:471e84684405 0:a1e37e7a184f

Digamos que en la rama principal ocurre m´ s desarrollo. a
1 2 3 4 5 6

$ cd ../main $ echo ’This is exciting and new!’ >> myfile $ hg commit -m ’Add a new feature’ $ cat myfile This is a boring feature. This is exciting and new! Cuando se usa la etiqueta con que se identific´ la versi´ n, la gente que clone el repositorio en el futuro puede usar o o “hg update” para obtener una copia del directorio de trabajo igual a cuando se cre´ la etiqueta de la revisi´ n que se o o consign´ . o 61

1 2 3 4 5 6 7

$ cd .. $ hg clone -U main main-old $ cd main-old $ hg update v1.0 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cat myfile This is a boring feature. Adicionalmente, justo despu´ s de que la rama principal se etiquete, alguien puede clonarla en el servidor a una e nueva rama “estable”, tambi´ n en el servidor. e

1 2 3 4 5 6 7 8 9

$ cd .. $ hg clone -rv1.0 main stable requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files updating working directory 1 files updated, 0 files merged, 0 files removed, 0 files unresolved Alguien que requiera hacer un cambio en la rama estable puede clonar ese repositorio, hacer sus cambios, consignarlos, y empujarlos de vuelta.

1 2 3 4 5 6 7 8 9 10 11 12 13

$ hg clone stable stable-fix updating working directory 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd stable-fix $ echo ’This is a fix to a boring feature.’ > myfile $ hg commit -m ’Fix a bug’ $ hg push pushing to /tmp/branchingOpMbpu/stable searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files Puesto que los repositorios de Mercurial son independientes, y que Mercurial no mueve los cambios de un lado a otro autom´ ticamente, las ramas estable y principal est´ n aisladas la una de la otra. Los cambios que haga en la rama a a principal no se “filtran” a la rama estable y viceversa. Es usual que los arreglos de fallos de la rama estable deban hacerse en la rama principal tambi´ n. En lugar de e reescribir el arreglo del fallo en la rama principal, usted puede jalar y mezclar los cambios de la rama estable a la principal, y Mercurial traer´ tales arreglos por usted. a

1 2 3 4 5 6

$ cd ../main $ hg pull ../stable pulling from ../stable searching for changes adding changesets adding manifests 62

7 8 9 10 11 12 13 14 15 16 17

adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run ’hg heads’ to see heads, ’hg merge’ to merge) $ hg merge merging myfile 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don’t forget to commit) $ hg commit -m ’Bring in bugfix from stable branch’ $ cat myfile This is a fix to a boring feature. This is exciting and new! La rama principal a´ n contendr´ los cambios que no est´ n en la estable y contendr´ adem´ s todos los arreglos de fallos u a a a a de la rama estable. La rama estable permanece inc´ lume a tales cambios. o

6.2.5.

Ramas de caracter´sticas ı

En proyectos grandes, una forma efectiva de administrar los cambios es dividir el equipo en grupos m´ s peque˜ os. a n Cada grupo tiene una rama compartida, clonada de una rama “principal” que conforma el proyecto completo. Aquellos que trabajan en ramas individuales usualmente est´ n aislados de los desarrollos de otras ramas. a

maestro

cripto

sistemadearchivos

ipc

memoria

red

seguridad

Figura 6.1: Ramas de Caracter´sticas ı ´ Cuando se considera que una caracter´stica particular est´ en buena forma, alguien de ese equipo de caracter´sticas ı a ı jala y fusiona de la rama principal a la rama de caracter´sticas y empuja de vuelta a la rama principal. ı

6.2.6.

El tren de publicaci´ n o

Algunos proyectos se organizan al estilo“tren”: una versi´ n se planifica para ser liberada cada cierto tiempo, y las o caracter´sticas que est´ n listas cuando ha llegado el “tren”, se incorporan. ı e Este modelo tiene cierta similitud a las ramas de caracter´sticas. La diferencia es que cuando una caracter´stica ı ı pierde el tren, alguien en el equipo de caracter´sticas jala y fusiona los cambios que se fueron en la versi´ n liberada ı o hacia la rama de caracter´stica, y el trabajo contin´ a sobre lo fusionado para que la caracter´stica logre estar en la ı u ı pr´ xima versi´ n. o o

6.2.7.

El modelo del kernel Linux

El desarrollo del kernel Linux tiene una estructura jer´ rquica bastante horizontal, rodeada de una nube de caos a aparente. Dado que la mayor´a de los desarrolladores de Linux usan git, una herramienta de control de versiones ı distribuida con capacidades similares a Mercurial, resulta de utilidad describir la forma en que el trabajo fluye en tal ´ ambiente; si le gustan estas ideas, la aproximaci´ n se traduce bien de Git a Mercurial. o ´ ´ En el centro de la comunidad est´ Linus Torvalds, el creador de Linux. El publica un unico repositorio que es a ´ ´ considerado el arbol “oficial” actual por la comunidad completa de desarrolladores. Cualquiera puede clonar el arbol ´ ´ de Linus, pero el es muy selectivo respecto a los arboles de los cuales jala. 63

´ Linus tiene varios “lugartenientes de confianza”. 6. algunas personas mantienen repositorios “estables” de versiones anteriores del kernel. el jala todos los cambios que ellos publican. La primera es que es de “jalar exclusivamente”. Es objeto de los caprichos individuales. en el o u cap´tulo 8. A pesar de que est´ ´ntimamente ligado acerca aı de c´ mo interact´ a su equipo. Algunos mantenedores publican varios arboles: uno para cambios ı experimentales. y as´ sucesivamente. o Una buena herramienta de control de versiones distribuida. ı ´ convencer o incluso rogar a otro desarrollador para que tome sus cambios. Pero el mantenedor de un subsistema probablemente los revisara.9. uno para cambios que van a ofrecer al mantenedor principal. sienten que el proceso comparativamente ca´ tico o del Kernel Linux es completamente lun´ tico. ı 64 . y el ritmo de desarrollo es alucinante. no hay forma de elegir qu´ modelo va a e usar: la herramienta le ofrece publicaci´ n compartida. sin siquiera responderle. Cuando la colaboraci´ n encuentra la administraci´ n ramificada o o Una vez que usted y su equipo configuren algunos repositorios compartidos y comiencen a propagar cambios entre sus repositorios locales y compartidos. Si o usted es un hacker respetado pero especializado en almacenamiento. Adicionalmente existen varias ramas conocidas que mucha gente usa para prop´ sitos distintos. usted comenzar´ a encarar un reto relacionado. n Personas que vienen de proyectos con un ordenamiento distinto. la gente desecha cambios cuando a lo desea. y trata de arreglar un fallo de redes. Si usted ı usa una herramienta centralizada de control de versiones como Subversion. y para decidir cuando presentarlos a Linus. tal cambio puede recibir un nivel de escrutinio de un mantenedor de redes comparable con el que se le har´a a un completo ı extra˜ o. soportar´ los dos modelos. A medida que usted ofrezca “mejores” cambios a a un mantenedor. pero un poco distinto: a administrar las direcciones en las cuales su equipo puede moverse. Otros publican solo ı ´ un arbol. habr´ m´ s posibilidad de que se conf´e en su juicio y se acepten los cambios. aceptar y publicar los cambios. ı La reputaci´ n y meritocracia no necesariamente son transversales entre “personas” de diferentes subsistemas. debe encontrar qui´ n es el mantenedor del subsistema y solicie ´ ´ tarle que tome su cambio. Algunos de sus lugartenientes generalmente aceptan ser los “manteneı dores”. personas con intereses similares pueden jalar sus cambios regularmente para estar al d´a con su trabajo.8.2.2. estos pasar´ n al arbol de a a Linus a su debido tiempo. Si usted es un desconocido. Usted debe solicitar. Cada lugarteniente tiene su forma particular de revisar. Solamente jalar frente a colaboraci´ n publica o ´ Una fuente perpetua de discusiones en la comunidad de c´ digo abierto yace en la afirmaci´ n de que el modelo de o o desarrollo en el cual la gente solamente jala cambios de otros “es mejor que” uno en el cual muchas personas pueden publicar cambios a un repositorio compartido. y no hay forma de publicar cambios en un arbol que alguien m´ s controla. a los cuales aplican ´ arreglos de fallos cr´ticos cuando es necesario. Si el mantenedor revisa los cambios y est´ de acuerdo en tomarlos. Linus probablemente a o ignorar´ sus cambios. y a los acoger´ en caso de que aprueben su criterio de aplicabilidad. T´picamente los partidarios del modelo de publicar usan las herramientas que se apegan a este modelo. o Por ejemplo. Usted a y sus colaboradores pueden estructurar c´ mo trabajar´ n juntos basados en sus propias necesidades y preferencias. A pesar de eso Linux es una pieza de software exitosa y bien reconocida. Este modelo tiene dos caracter´sticas notables. porque casi no hay arboles en los cuales ´ m´ s de una persona pueda publicar. va a tener que tomar una o aproximaci´ n artificial (tal como aplicar parches a mano). sin o a tener que llevar a cabo las peripecias que la herramienta les obligue a hacer. en la mayor´a de los casos sin siquiera revisarlos. Como regla. a a La segunda es que est´ basado en reputaci´ n y meritocracia. responsables de subsistemas espec´ficos dentro del kernel. 6. Si un hacker cualquiera desea hacer un cambio a un ı ´ subsistema y busca que termine en el arbol de Linus. este es un tema lo suficientemente denso para ameritar un tratamiento aparte. Si usted es reconocido a a ı y mantiene una rama durante bastante tiempo para algo que Linus no ha aceptado. tal como Mercurial. y si desea hacer cualquier otra cosa.

“hg serve” no permitir´ que los usuarios remotos modifiquen su repositorio. para que la gente pueda hacer “hg clone” o “hg pull” (jalar) o cambios desde tal repositorio. Si otro proceso est´ esa cuchando en tal puerto. in´cielo con la opci´ n -v. y averiguar qu´ URL deber´a enviar a sus colaboa a e ı radores. “hg incoming”. probablemente encontrar´ elemental una porci´ n del material a continuaci´ n. Tambi´ n sirve como una demostraci´ n de c´ mo se siente usar los comandos usando la red. deber´ crear una o m´ s cuentas de usuario en un servidor de forma tal que los a a ´ usuarios remotos puedan entrar y ejecutar ordenes. Uso del protocolo Secure Shell (ssh) Usted puede publicar y jalar cambios en la red de forma segura usando el protocolo Secure Shell (ssh). ı o 6. es un protocolo de red que le permite comunicarse de manera segura con otro a computador. lo siguiente que deber´a hacer (despu´ s de asegurarse que tienen el URL correcto) es verificar su ı e configuraci´ n de cortafuegos. Para usarlo exitosamente. o a Hablar el protocolo de conexi´ n de Mercurial. a o Si no est´ familiarizado con ssh.6.1.4. Si otras personas no pueden acceder a su instancia de “hg serve”.) a o o 65 . No puede detectar o controlar sus cortafuegos. desde un navegador web. acoplado n ´ y agil. deber´a usar “hg serve” exclusivamente en amo ı bientes en los cu´ les esto no sea importante. a aceptar´ conexiones desde cualquier cliente y servir´ datos de este repositorio mientras lo mantenga funcionando. o Normalmente. 6. (Si ssh le es familiar. lo cual puede ser algo desconcertante. Es de tipo s´ lo lectura. y en pocos segundos se iniciar´ un servidor HTTP especializado.3. Un URL para una instancia de “hg serve” ejecut´ ndose en un port´ til deber´a lucir similar a http://my-laptop. En particular. e o o Ejecute “hg serve” dentro de un repositorio. Solamente puede hacer dos cosas: o Permitir la visualizaci´ n del historial del repositorio que est´ sirviendo. no muestra ning´ n mensaje. para comunicarse con el servidor como si el repositorio estuviera alojado remotamente. “hg serve” escucha conexiones entrantes en el puerto 8000. Compartir informalmente con “hg serve” La orden “hg serve” de Mercurial satisface de forma espectacular las necesidades de un grupo peque˜ o. tendr´ que hacer algo de configuraci´ n a nivel de cliente o de servidor. no hay nada que le impida usar “hg serve” para servir un repositorio en a a ´ su propio computador. a a Todo el que conozca la URL del servidor que usted ha iniciado. Para usarlo con Mercurial. Aspectos t´ cnicos de la colaboraci´ n e o Lo que resta del cap´tulo lo dedicamos a las cuestiones de servir datos a sus colaboradores. o en los cuales tenga control completo acerca de qui´ n puede acceder a a e su red y jalar cambios de su repositorio.5. La orden “hg serve” no tiene conocimiento acerca de programas cortafuegos que puedan estar instalados en su sistema o en su red. a a ı La orden “hg serve” no es un servidor web de prop´ sito general. usted puede especificar un puerto distinto para escuchar con la opci´ n -p. u Si desea confirmar que en efecto est´ ejecut´ ndose correctamente. y posteriormente usar ordenes como “hg clone”. Cuestiones adicionales para tener en cuenta Dado que permite lectura sin autenticaci´ n a todos sus clientes. o De forma predeterminada. y que pueda comunicarse con su computador a trav´ s e de la red. a o Si est´ familiariz´ ndose con Mercurial. ı 6. Esto puede ayudarle a adecuarse r´ pidamente a usar a comandos en repositorios alojados en la red. puede usar un navegador web o Mercurial para leer datos del repositorio.local:8000/.4. cuando se inicia “hg serve”.

o ı Mercurial no podr´ encontrarlo correctamente (por lo tanto. El predeterminado es el 22. No es la situaci´ n ideal. del T. Por ejemplo.5.ini para indicarle a Mercurial d´ nde encontrar la orden a o real del cliente. “hg. 2. puesto que no hay una forma est´ ndar o a para que las herramientas puedan interpretarlo. tendr´ que editar su fichero Mercurial.2.serpentine. Por ejemplo. o El componente de la ruta del URL para ssh es una fuente de confusi´ n.exe -ssh -i "C:/ruta/a/mi/llave/privada" Nota: La ruta a plink no deber´a contener espacios o caracteres en blanco. pero es muy poco probable que vaya a cambiar.com:22/hg/hgbook 1. a Mercurial trata la ruta al repositorio en el servidor como relativa al directorio personal del usuario remoto. a o o En Windows. Algunos programas se comportan de manera distinta a otros cuando manipulan estas rutas. tendr´ que usar la orden plink como un cliente de l´nea de a a ı comandos para ssh. La parte “ssh://” le indica a Mercurial que use el protocolo ssh. como en el siguiente ejemplo: 1 ssh://server//absolute/path 6. 4. 1 C´ mo leer y escribir URLs de ssh o Los URLs de ssh tienden a lucir de la siguiente forma: ssh://bos@hg. probablemente no ser´a a ı buena idea colocarlo en C:\Program Filesa a N. Si tiene alta tolerancia al dolor.serpentine.1. La ultima porci´ n del URL es la ruta local del repositorio en el servidor. 3. Si usted est´ usando un sistema de estos. Por favor lea los o p´ rrafos siguientes cuidadosamente. entonces un URL ssh que tenga como ruta a bar realmente se refiere al directorio /home/foo/bar. Si por casualidad o a a no est´ presente. que ofrece un conjunto completo de ordenes de cliente ssh. 1 2 [ui] ssh = C:/ruta/a/plink. puede usar el porte de Cygwin para OpenSSH. Hay dos alternativas: a ´ El excelente paquete PuTTY [Tat] de Simon Tatham. puede usar una ruta que comience con una virgulilla. Si desea especificar una ruta relativa a otro directorio de usuario. comience con el componente de la ruta con dos barras.6.5. ı 66 . vea la documentaci´ n de sus sistema para averiguar c´ mo instalarlo. as´ que u a ı solamente necesitar´ especificar esa porci´ n si no est´ usando el puerto 22. El “:22” identifica el n´ mero del puerto en el servidor al cual se conectar´ . si el usuario foo en el servidor tiene el directorio personal /home/foo. Puede omitirlo si el usuario a remoto coincide con el usuario local. as´ e ı 1 ssh://server/˜otheruser/hg/repo Y si realmente desea especifica una ruta absoluta en el servidor. si est´ usando PuTTY. En cualquier caso. El componente “bos@” indica el nombre del usuario que est´ entrando al servidor. Encontrar un cliente ssh para su sistema Casi todos los sistemas tipo Unix vienen con OpenSSH preinstalado. seguida del nombre del usuario (llam´ mosle otrousuario).com” es el nombre del servidor al cual se desea entrar. primero tendr´ que descargar un cliente adecuado. a o a ´ 5. ejea cute which ssh para identificar d´ nde est´ instalada la orden ssh (usualmente estar´ en /usr/bin). Ubicarlo en C:\Archivos de Programa tampoco lo ser´a.

recomiendo generar un par de llaves. Generar un par de llaves Para evitar la necesidad de teclear una clave de forma repetitiva cada vez que necesita usar el cliente. Si o a a a no hay un agente de autenticaci´ n corriendo. en algunos casos incluso si su sistema ya ha sido reiniciado. Pero a´ n. (La unica oportunidad en la cual usted no querr´a hacerlo. usualmente o ´ esta continuar´ trabajando indefinidamente. tendr´ que teclear su o a frase clave cada vez que Mercurial intente comunicarse con un servidor para usted (p. El problema de almacenar frases claves en un agente es que es posible para un atacante bien preparado recuperar el texto plano de su frase clave. la orden ssh-keygen se encargar´ de la tarea. Configurar el lado del servidor apropiadamente Dado que puede ser dispendioso configurar ssh si es algo nuevo para usted. Si usa puttygen en Windows. es mejor asegurarse de que puede usar la orden normal ´ ssh o putty para comunicarse primero con el servidor. hay una variedad de cosas que podr´an ir ı mal. o el agente no almacena la frase clave necesaria.5. o que haya tecleado incorrectamente la frase clave de su llave o la clave del usuario remoto. Los problemas m´ s e a comunes son los siguientes: Si obtiene un error de “conexi´ n rehusada”. Lo primero para asegurar en el lado del servidor es que usted pueda iniciar sesi´ n desde otra m´ quina.5. esto esconder´ el problema subyacente. En Windows. es cuando est´ usando el protocolo ssh para tareas automatizadas en una red segura.ssh. necesitar´ la orden puttygen.3. Se requiere adicionar la llave p´ blica al conjunto de llaves autorizadas u del usuario que usted usa para acceder a la m´ quina remota. o pegarla desde la ventana en la cual se despliega directamente en el fichero u o authorized keys. ı En sistemas tipo Unix. 6. Si tiene problemas usando estas ordenes directamente. Es su decisi´ n si es un o riesgo aceptable. si est´ usando PuTTY. Lo que s´ es seguro es que evita reteclear. cada vez que jale o publique cambios).5. el agente se llama ssh-agent. puede guardar la u a o llave p´ blica en un fichero de su elecci´ n.pub. En Windows. significar´ a˜ adir la llave p´ blica a la lista en el fichero llamado authorized keys en su directorio . el mensaje de error que obtenga le puede dar pistas de qu´ ha ido mal. a Antes de intentar que Mercurial hable con un servidor ssh.e. no en el cliente. Si no puede o a entrar usando ssh o putty. Un cliente ssh notar´ si el agente est´ corriendo. si a est´ usando PuTTY. El a˜ ade un icono a su barra del sistema que le permitir´ administrar las frases u a clave almacenadas. es posible que no haya un demonio SSH corriendo en el servidor o o ´ que no pueda accederse a el debido a la configuraci´ n de cortafuegos. a a ´ Cuando genera un par de llaves.6.5. deber´a asegurarse primero que las ordenes de ssh en el lado del cliente funcionan ı primero. antes de preocuparse por si existe un problema con Mercurial. o Si obtiene un error de “no hay ruta hasta el servidor”. puede tener una direcci´ n incorrecta para el servidor o un o cortafuegos con bloqueo agresivo que negar´ la existencia del servidor. A˜ ada a eso Mercurial y hay mucho m´ s en qu´ pensar.4. se aconseja comedidamente protegerlas con una frase clave. 6. y le solicitar´ una frase clave. Para aquellos servidores que usen OpenSSH (la gran a mayor´a).) ı a No basta con generar un par de llaves. En un sistema tipo Unix. puede que haya tecleado mal el usuario en el servidor. Cuando desee revisar un problema a u a ´ relacionado con ssh y Mercurial. Tendr´ que usar la orden ssh-add para a˜ adir frases claves al agente. Las buenas noticias es que una vez tiene una configuraci´ n funcional. de seguro Mercurial no funcionar´ . la o a n a ´ n orden pageant act´ a como el agente. y usualmente se ejecuta autom´ ticamente cuando usted inicia a sesi´ n. La mayor parte de estos problemas potenciales ocurren en n a e el lado del servidor. ı a n u En sistemas tipo Unix. su llave p´ blica tendr´ la extensi´ n . 67 . Uso de un agente de autenticaci´ n o Un agente de autenticaci´ n es un demonio que almacena frases clave en memoria (olvidar´ las frases clave si sale o a de su sesi´ n y vuelve a entrar). a Si obtiene un mensaje de “permiso denegado”.

pero deshabilitado de forma predeterminada. Por ejemplo. Si este es el caso. Si alguien distinto al usuario es due˜ o del n mismo o puede escribir en el fichero. incluso cuando se o ´ ejecutan ordenes no interactivas como esta. Pero deber´a revisar los posibles problemas: ı ¿Est´ instalado Mercurial en el servidor? ¡S´ que suena trivial pero es mejor revisar! a e ´ Tal vez la ruta de b´ squeda de la interfaz de ordenes (normalmente v´a la variable de entorno PATH) simplemente u ı est´ mal configurada. Esto puede suceder si establece la ruta en el gui´ n de l´nea de comandos de entrada o ı ´ incorrecto.ssh tiene permisos excesivamente abiertos.En resumen. ı 1 ssh miservidor date Si en su servidor tiene gui´ n que se ejecuta a la entrada e imprime letreros o cualquier otra cosa. no se preocupe. o e La variable de ambiente PYTHONPATH puede requerir contener la ruta a los m´ dulos de Mercurial en Python. Incluso podr´an a ı ´ causar problemas potenciales cuando se ejecuten ordenes de forma remota. no necesita hacerlo. Mercurial intenta detectar e ignorar los letreros en sesiones no interactivas de ssh. a continuaci´ n algunas posibilidades: o Puede haber olvidado usar ssh-add o pageant para guardar la frase clave. el demonio ssh no confiar´ en el y no lo leer´ . o puede ser que se establezca unicamente cuando a ı hay entradas interactivas. Ahora deber´a poder acceder a los repositorios de Mercurial que tiene el usuario en el servidor. el siguiente paso es asegurarse de que Mercurial corre en el servidor. la fecha y hora actual. (Si edita sus guiones de entrada en el servidor. ¡felicitaciones! Ha logrado la interacci´ n entre el cliente o o y el servidor. De otra forma estos letreros al menos llenar´ n la salida de Mercurial. En muchos sistemas estar´ instalado. Como resultado el demonio ssh no confiar´ ni leer´ su fichero authorized keys. a Puede ser que su variable de ambiente PATH solamente apunte al lugar en el cual est´ el ejecutable hg si la sesi´ n a o de entrada es interactiva. Consulte la documentaci´ n de su int´ rprete de ordenes. la forma usual de ver si un gui´ n de l´nea de comandos se ejecuta en un int´ rprete interactivo es verificar el o ı e c´ digo de retorno de la orden tty -s. Si est´ usando un agente de autenticaci´ n en el lado del cliente para almacenar las frase claves de sus contrase˜ as. Si se le solicita la clave del usuario remoto. un directorio personal o . si tiene problemas al comunicarse con el demonio ssh del servidor. Si tiene ı problemas con Mercurial y ssh en este punto. No trate de buscar otras posibilidades ex´ ticas o a o configuraciones erradas hasta que haya revisado primero estas dos. o ´ Puede que ni siquiera est´ establecida. a 68 . hay otras posibilidades que deben revisarse: O bien el directorio del usuario o su directorio . Si puede ejecutar “hg version” sobre una conexi´ n ssh. a o n deber´a poder entrar al servidor sin necesidad de que se le soliciten frases claves o contrase˜ as. Si se le pregunta ı n alguna. a ı El fichero authorized keys del usuario puede tener un problema. intente usar la opci´ n --debug para tener informaci´ n m´ s clara de lo o o a que est´ sucediendo. Una vez que haya hecho a esto tendr´ que revisar si el cortafuegos del servidor est´ configurado para recibir conexiones entrantes en el puerto a a en el cual est´ escuchando el demonio de ssh (usualmente el 22). ser´ porque Mercurial no fue instalado en a /usr/bin. podr´a estar incorrecta. Puede haber almacenado una frase clave para una llave distinta. a ´ a En un mundo ideal.) o Cuando verifique que el venerado ssh funciona en su servidor. primero aseg´ rese de que se est´ ejeu e cutando. pero no es a prueba de tontos. deber´a arreglarlo antes de continuar. La siguiente orden deber´a ejecutarse satisfactoriamente: ı 1 ssh miservidor hg version Si ve un mensaje de error en lugar de la salida usual de “hg version”. y deber´a imprimir exactamente una ı ı l´nea de salida. de forma que solamente imprima algo ı si se ejecuta interactivamente.ssh con a a permisos de escritura para grupo mostrar´ a veces este s´ntoma. deber´a poder ejecutar la siguiente orden exitosamente.

a a a o Nota: Configurar un servidor web es una actividad compleja. edite su fichero . har´ que a ssh se conecte a hg.com usando compresi´ n. Pero el comportamiento predeterminado del cliente ssh es no utilizar compresi´ n. alguien ha medido que la compresi´ n reduce la cantidad de tiempo requerido para clonar un repositorio particularmente grande o de 51 minutos a 17 minutos. Use su discreci´ n y juicio respecto o a las siguientes secciones. dado que el protocolo puede comprimir datos transparentemente. o 1 2 [ui] ssh = ssh -C Si usa ssh. Servir sobre HTTP usando CGI Dependiendo de qu´ tan ambicioso sea.6.1. 69 . t´ mese un tiempo para revisar ciertos aspectos de la configuraci´ n de su sistema: o o 1.5. de la siguiente forma: u 1 2 3 Host hg Compression yes HostName hg. hg.ssh/config (que puede no existir a´ n). 3. o 6. hacer uso de compresi´ n puede a a o mejorar el rendimiento de las operaciones de Mercurial que involucren la red. puede a a ı e no estar habilitado de forma predeterminada. engorrosa y altamente dependiente del sistema. 2.6. Prep´ rese para cometer muchas equivocaciones. ¿Est´ configurado su servidor para permitir ejecutar programas CGI en el directorio donde planea hacerlo? Casi a todos los servidores de forma predeterminada deshabilitan expl´citamente la habilidad de ejecutar programas ı CGI. De ninguna manera podremos cubrir todos los casos posibles con los cuales pueda encontrarse. Para o hacerlo.ejemplo. puede reconfigurarlo para que siempre use compresi´ n cuando se comunique con su servidor. Compresi´ n con ssh o Mercurial no comprime datos cuando usa el protocolo ssh. aunque est´ presente.ejemplo. los cuales por derecho propio son buenos. o Sobre cualquier red distinta a una LAN r´ pida (incluso con una red inal´ mbrica). Lista de chequeo de la configuraci´ n del servidor web o Antes de continuar.6. y nos dirigiremos hacia configuraciones m´ s complejas.com Que define un alias. Incluso para a a el caso m´ s b´ sico necesitar´ leer y modificar la configuraci´ n de su servidor web. Cuando lo usa con la orden ssh o con una URL de Mercurial con protocolo ssh. Tanto ssh como plink aceptan la opci´ n -C para activar la compresi´ n. sobre WAN. y ema plear bastante tiempo leyendo las bit´ coras de error de su servidor. Si tiene un servidor web instalado. Esto le brindar´ un nombre m´ s corto para teclear. ¿Est´ ejecut´ ndose? En la mayor´a de sistemas. Puede editar f´ cilmente su hgrc para o o a habilitar la compresi´ n para todos los usos de Mercurial con el protocolo ssh. configurar la interfaz CGI de Mercurial puede tomar desde unos minutos e hasta varias horas. ¿Tiene un servidor web? Mac OS X viene con Apache. junto con o a a compresi´ n. pero otros sistemas pueden no tener un servidor web instalado. Comenzaremos con el ejemplo m´ s sencillo. Por ejemplo. a 6.6.

y asegurarse que sea ejecutable. y una cuenta de usuario o que cre´ espec´ficamente para desarrollar este ejercicio.cgi ˜/public_html chmod 755 ˜/public_html/hgweb./hgweb.6.selenic.cgi El argumento 755 de la orden chmod es un poco m´ s general que hacerlo ejecutable: asegura que el gui´ n sea ejecutable a o por cualquiera. Si la hay. muchas de ellas no son ı relevantes para servir repositorios de Mercurial. A pesar de que lighttpd tiene menos caracter´sticas que Apache en ciertas areas. podr´a toparse con cada ı uno de los errores que describimos a continuaci´ n. Los permisos de sus ficheros pueden ser demasiado restrictivos. De hecho. Para comenzar. encuentre el gui´ n hgweb. Hay una alta probabilidad de que esta primera visita al URL sea fallida.com/˜username/foo.com/repo/hg/raw-file/tip/hgweb. puede descargarlo del repositorio principal de Mercurial a en http://www. desde el cual pueden servir p´ ginas web. y hay muchas razones posibles para este comportamiento... El subsistema suexec de o Apache no ejecutar´ un gui´ n que tenga permisos de escritura para el grupo o el planeta. as´ que no deje de leerlos cuidadosamente. o A continuaci´ n presento una configuraci´ n predeterminada por usuario en mi sistema Fedora. busque el fichero de configuraci´ n que contenga la directiva UserDir. Si dejara los permisos de escritura abiertos. deber´a considerar usar el ı servidor web lighttpd en lugar de Apache. por ejemplo public html.Si no tiene un servidor web instalado. Si no est´ presente en sitio alguno. y que el “grupo” y los “otros” no tengan permiso de escritura. los directorios por usuario estar´ n deshabilitados. o a e a 1 2 3 chmod 755 ˜ find ˜/public_html -type d -print0 | xargs -0r chmod 755 find ˜/public_html -type f -print0 | xargs -0r chmod 644 Otra posibilidad con los permisos es que obtenga una ventana completamente en blanco cuando trata de cargar el gui´ n. e a e A continuaci´ n una receta r´ pida para hacer que sus permisos est´ n acordes con las necesidades b´ sicas. Configuraci´ n b´ sica de CGI o a En sistemas tipo Unix es com´ n que los usuarios tengan un subdirectorio con un nombre como public html en u su directorio personal. a o Su servidor web puede estar configurado para evitar la ejecuci´ n de programas CGI en los directorios de usuario. En caso cona trario. y no tiene experiencia configurando Apache. con una instalaci´ n nueva de Apache. Un fichero llamado foo en este directorio ser´ visible a a en una URL de la forma http://www. la directiva UserDir tendr´ el nombre del subdirectorio bajo el cual Apache mirar´ en el directorio de cada a a usuario. o 1 chmod 755 ˜/public_html ¿Qu´ podr´a resultar mal? e ı Cuando haya ubicado el CGI en el sitio correspondiente.cgi que deber´a estar presente en su instalaci´ n de Mercurial. 6. el subsistema suexec de Apache probablemente se negar´a a ejecutar el gui´ n. Si usa Apache. pero su valor es disabled. o o 70 . e ı Su servidor web puede tener directorios por usuario deshabilitados. sin dejarse abatir por un error. los directorios por usuario est´ n o a a deshabilitados. De hecho.example. por ejemplo. adem´ s de tener permiso para leer aquellos que est´ n adentro. es posible que los permisos que tiene son demasiado permisivos.2. suexec tambi´ n ı o e insiste en que el directorio en el cual reside el gui´ n no tenga permiso de escritura para otros. Y definitivamente es mucho m´ s sencillo comenzar con lighttpd a que con Apache.cgi. Apache tiene una reputaci´ n bien ganada por su configuraci´ n barroca o o ´ y confusa. En este caso. Tendr´ que copiar este gui´ n en su directorio public html. a o 1 2 cp . A continuaci´ n presento o ı o los problemas que yo tuve en un sistema con Fedora 7. El servidor web debe poder recorrer su directorio personal y los directorios que est´ n bajo public html. abra un navegador e intente visitar el URL http:// myhostname/˜myuser/hgweb. Si no o ı o puede encontrar r´ pidamente una copia local en su sistema.cgi.

cgi tambi´ n lo era. edite su copia de hgweb. para hacer lo propio con los m´ dulos.allow Deny from all </LimitExcept> </Directory> Si encuentra un grupo de instrucciones de Directory similares en su configuraci´ n de Apache. Ya super´ los problemas que ı e mostr´ con Apache. puede que se encuentre con otra traza a todo color de Python al visitar el URL: esta seguramente se referir´ a que no puede encontrar /path/to/repository1 . lograr que lighttpd sirviera mi repositorio fue r´ pido (en o a otras palabras. a pesar de haber usado Apache por lo menos por a una d´ cada. Por lo tanto estaba seguro de que mis e a ı permisos para directorios y ficheros eran correctos y que mi gui´ n hgweb. muchos de los cu´ les no son espec´ficos del servidor. a a ¡Uff! Configuraci´ n de lighttpd o En mi intenci´ n de ser exhaustivo. 71 . si est´ tratando de usar lighttpd.cgi Otra posibilidad es que observe una traza de Python en colores informando que no puede importar un m´ dulo o relacionado con mercurial. Si este error le ocurre. necesitar´ o bien descomentar (si o a se encuentra presente) o adicionar una directiva como la siguiente: 1 AddHandler cgi-script . Ruta al repositorio. Recuerde que el servidor que ejecuta el programa CGI no cuenta con variables de entorno de las cuales usted s´ dispone en una sesi´ n interactiva.path = "public_html" cgi. o A˜ ad´ posteriormente unas l´neas al final del fichero de configuraci´ n. Este error o solamente ocurrir´ si est´ ejecutando una instalaci´ n privada de Mercurial en lugar de una instalaci´ n para todo el a a o o sistema. considero o que lighttpd es bastante m´ s sencillo de configurar que Apache. del T.cgi y siga las indicaciones dentro ı o del mismo para establecer de forma adecuada su variable de entorno PYTHONPATH. un servidor web con creciente aceptaci´ n. para o e o servir los repositorios de la misma forma en que lo describ´ anteriormente con Apache. Si hubiera configurado lighttpd antes que Apache. Primero tuve que editar la secci´ n a a o o mod access para habilitar mod cgi y mod userdir. lighttpd funcion´ inmediatamente para m´. y de que esta fue mi primera experiencia con lighttpd.1 2 3 4 5 6 7 8 9 10 11 12 <Directory /home/*/public_html> AllowOverride FileInfo AuthConfig Limit Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec <Limit GET POST OPTIONS> Order allow. o e Dado que ya Apache estaba en ejecuci´ n correctamente. habr´a o ı ı tenido casi los mismos problemas a nivel de configuraci´ n del sistema que con Apache. ¡Esto es un gran progreso! El servidor es capaz de ejecutar su gui´ n CGI. n ı ı o o 1 2 userdir. Si resulta que Apache le muestra el texto del gui´ n CGI en lugar de ejecutarlo. deber´ leer la secci´ n de Apache). Finalmente. deber´ tener una linda vista HTML del historial de su repositorio. la directiva a revisar o es Options. De todas maneras.cgi" => "" ) Hecho esto. cuando trate de recargar la p´ gina.cgi y reemplace la cadena a o /path/to/repository con la ruta completa al repositorio que desea servir. intent´ configurar lighttpd.deny Allow from all </Limit> <LimitExcept GET POST OPTIONS> Order deny. e 1 N. Adicione ExecCGI al final de esta lista en caso de que haga falta y reinicie su servidor web. En este punto.assign = ( ". Edite su gui´ n hgweb. los cuales estaban inhabilitados en mi instalaci´ n predeterminada.

cgi le permite publicar una lista espec´fica de reposia o ı torios. el URL completo al repositorio o ser´ http://myhostname/˜myuser/hgwebdir.cgi es mediante una secci´ n llamada collections. Si no tiene una a mano. una restricci´ n frustrante. Primero se debe obtener una copia del gui´ n. Deber´a o a ı mostrar una lista vac´a de repositorios.6.6. con los contenidos de la siguiente forma: o 1 2 3 [paths] repo1 = /mi/ruta/a/un/repo repo2 = /ruta/a/otro/repo 72 .cgi tiene una porci´ n adicional respecto al trabajo requerido con o hgweb. La forma m´ s sencilla de configurar hgwebdir. Si obtiene una ventana en blanco o un mensaje de error. cree una secci´ n paths.cgi. y permitir lectura de todo el a mundo. puede descargarla del ftp principal o del repositorio de Mercurial en http://www.3. El formato del fichero es similar a un fichero “ini” de Windows. Esta puba o licar´ autom´ ticamente todos los repositorios en los directorios que usted especifique. La secci´ n deber´a lucir as´: a a o ı ı 1 2 [collections] /mi/ruta = /mi/ruta Mercurial lo interpreta buscando el nombre del directorio que est´ a la derecha del s´mbolo “=”. o 1 2 cp . De forma predeterminada. Especificaci´ n expl´cita de los repositorios a publicar o ı Adem´ s del mecanismo collections.selenic.2. y debe asegurarse de que tenga permisos de ejecua o ci´ n. o El gui´ n hgwebdir.cgi que mirase.cgi eliminar´ solamente a /mi del nombre del repositorio./hgwebdir. o El procedimiento para configurar hgwebdir. si tenemos un repositorio cuya ruta local es /mi/ruta/este/repo. o a El mecanismo de collections permite publicar f´ cilmente repositorios de una forma “hacer y olvidar”..cgi/this/repo. y nos ofrecer´ la ruta virtual ruta/este/repo en lugar de este/repo.cgi permite publicar unicamente un repositorio.cgi.cgi. busca un o o fichero llamado hgweb.cgi Con la configuraci´ n b´ sica.com/repo/hg/raw-file/tip/hgwebdir. Si el a o a URL base de nuestro gui´ n CGI es http://myhostname/˜myuser/hgwebdir.cgi. intente visitar en su navegador http://myhostname/˜myuser/hgwebdir. que puede ser interpretado por el m´ dulo o ConfigParser [Pyt] de Python. Necesitar´ una copia del gui´ n en su directorio public html. El componente restante de la ruta despu´ s de esta eliminaci´ n usualmente se llama “ruta virtual”.cgi buscar´ recursivamente en cada directorio listado en la secci´ n collections de su fichero o a o de configuraci´ n. pero no har´ el recorrido recursivo dentro de los repositorios que encuentre. Para hacerlo. Despu´ s de eso puede publicar y sacar o o e de publicaci´ n un repositorio en cualquier momento incluy´ ndolo o excluy´ ndolo de la jerarqu´a de directorios en la o e e ı cual le haya indicado a hgwebdir.6. Solaa mente requiere configurar el gui´ n CGI y el fichero de configuraci´ n una vez. y usando el texto a la izquierda para eliminar el texto de los nombres que mostrar´ en la ı a interfaz web. resulta mucho mejor usar o el gui´ n hgwebdir.. cada una con un nombre distinto. Tendr´ que crear el fichero.config en el mismo directorio. Si desea publicar m´ s o o a de uno sin complicarse con varias copias del mismo gui´ n. ubicando repositorios e ı en la jerarqu´a de directorios. verifique la lista de ı problemas potenciales en la secci´ n 6. a El gui´ n hgwebdir. e o Dado el ejemplo de arriba. el gui´ n hgwebdir. el gui´ n CGI o eliminar´ la porci´ n inicial /mi/ruta del nombre y publicar´ el repositorio con una ruta virtual este/repo. hgwebdir.cgi. Compartir varios repositorios con un gui´ n CGI o ´ El gui´ n hgweb.cgi se apoya en un fichero externo de configuraci´ n.cgi ˜/public_html chmod 755 ˜/public_html ˜/public_html/hgwebdir. a Si reemplazamos /mi/ruta en el lado izquierdo de este ejemplo con /mi.

Note que no tiene que haber relaci´ n alguna entre la ruta virtual a o que elija y el lugar del repositorio en su sistema de ficheros. puede usar tanto collections como paths simult´ neamente en un solo fichero de configuraci´ n. hgwebdir.4. Descarga de ficheros fuente La interfaz web de Mercurial permite a los usuarios descargar un conjunto de cualquier revisi´ n. ı a ı bz2 Un fichero tar con el m´ todo de compresi´ n bzip2. el valor tendr´ una secuencia de palabras extra´das de la lista de abajo. a u a 6. Este formato posee la peor tasa de compresi´ n. Todas ellas van en la secci´ n [web]. Si habilita esta caracter´stica. Mercurial viene con dos plantillas web.hg/hgrc del repositorio. Para habilitarla adicione un allow archive a la ı a secci´ n [web] de su fichero hgrc.cgi no reportar´ ning´ n error. La cantidad m´ xima predeterminada de ficheros modificados a desplegar en una p´ gina. o 1 2 [web] allow_archive = bz2 gz zip allowpull Booleano. los usuarios de la interfaz web podr´ n descargar una copia de la revisi´ n del repositorio que est´ n viendo. este valor controla la cantidad de filas en cada franja. a a stripes Entero. a consulte el cap´tulo 11. Esta caracter´stica no est´ habilitada de forma predeterminada. style Controla la plantilla que Mercurial usa para desplegar la interfaz web. contact Cadena. o o e a ı allow archive Determina qu´ mecanismos de descarga soportar´ Mercurial. pero no contendr´ una copia de los datos del a e o o a repositorio. A continuaci´ n se ı ı a o presenta un ejemplo de c´ mo habilitar los tres formatos soportados. comprimido con gzip.cgi y hgwebdir. ı o o 73 . La cantidad m´ xima de conjuntos de cambios a mostrar de forma predeterminada en cada p´ gina. la ruta virtual (el componente que aparecer´ en el URL) est´ en el lado derecho de cada definici´ n. pero usa m´ s e o o a tiempo de procesamiento en el servidor. Si lo desea.cgi) tienen varias opciones de configuraci´ n disponibles.5. llamadas default y gitweb (La primera es m´ s atractiva visualmente). A veces tiene sentido colocar esta opci´ n en el fichero . esta caracter´stica se deshabilitar´ . zip Un fichero zip. Puede especificar una plantilla propia.6. y los guiones hgweb. pero en otras o ´ oportunidades es mejor hacerlo en el hgrc global si todos los repositorios tienen un unico mantenedor. a o Nota: Si varios repositorios tienen la misma ruta virtual. Una cadena en forma libre (pero preferiblemente corta) que identifica a la persona o grupo a cargo del repositorio. Si se coloca no o false. Si da una lista vac´a o no tiene la entrada allow archive. a a o mientras que la ruta al repositorio est´ a la derecha. Determina si la interfaz web permite a los usuarios remotos emplear “hg pull” y “hg clone” sobre el repositorio HTTP. comprimido con LZW. Para activar la a o e caracter´stica de descarga de conjunto. Si la interfaz web despliega “franjas” para facilitar la visualizaci´ n alineada de filas cuando se ve una o tabla. gz Un fichero tar. Usualmente contiene el nombre y la direcci´ n de correo electr´ nico de una persona o de una o o lista de correo. Pero se comportar´ de manera impredecible. Este conjunto o contendr´ una r´ plica del directorio de trabajo en la revisi´ n en cuesti´ n. Opciones de configuraci´ n en Web o Las interfaces web de Mercurial (la orden “hg serve”. solamente se habilita la porci´ n de los procesos “orientados-ao humanos” de la interfaz web. pero es muy usado o en el mundo Windows. a a maxfiles Entero.En este caso. Tiene la mejor tasa de compresi´ n. maxchanges Entero.6. A continuaci´ n mostramos c´ mo habilitar el estilo gitweb. o 6.

El nombre de un fichero en el cual escribir la bit´ cora de error.cgi. IPv6 no se usa de manera predeterminada. name Cadena. la orden “hg serve” escribe a esta informaci´ n en la salida de error est´ ndar. Sustituye el nombre predeterminado. En principio. Estas opciones son motd y style. El puerto predeterminado es u a a el 8000. El n´ mero del puerto TCP en el cu´ l el servidor esperar´ conexiones. o a ipv6 Booleano. a address Cadena. puede a˜ adir otras opciones de configuraci´ n en la secci´ n [web] del fichero hgweb.cgi. Tales configun a raciones solamente afectar´ n el comportamiento de la orden “hg serve” cuando usted la ejecuta. o el servidor escucha en todas las direcciones. n 74 . Opciones espec´ficas a la orden “hg serve” ı Algunas opciones en la secci´ n [web] de un fichero hgrc son de uso exclusivo de la orden “hg serve”. Directorio en el que se buscar´ n los ficheros plantilla. La direcci´ n local en la cual el servidor debe escuchar peticiones entrantes. errorlog Ruta. el ´ cual es el ultimo componente de la ruta del repositorio. Si se usa o no el protocolo IPv6.config n o o en lugar del fichero hgrc si lo considera m´ s conveniente. Elegir el fichero hgrc correcto para las configuraciones de [web] Es importante recordar que un servidor web como Apache o lighttpd se ejecutar´ bajo un ID de usuario que a generalmente no es el suyo Los guiones CGI ejecutados por su servidor. usado por casi todos los servidores web. no a un fichero. a Opciones espec´ficas para repositorios individuales ı Ciertas opciones de configuraci´ n de [web] deben estar ubicadas en el .1 2 [web] style = gitweb templates Ruta. Las l´neas de la bit´ cora se escriben en un formato o a ı a de fichero “combinado” est´ ndar. description Cadena. El nombre del fichero en el cual se escribe la bit´ cora de acceso. tales como hgweb. la orden “hg serve” a escribe esta informaci´ n a la salida est´ ndar. El nombre para visualizar en la interfaz web del repositorio. se ejecutar´ n tambi´ n a e ´ con ese ID de usuario. no a un fichero. De forma predeterminada.hg/hgrc de un repositorio en lugar del o fichero del usuario o el hgrc global. Una cadena de forma libre (preferiblemente corta) que describa los contenidos o el prop´ sito del reposo itorio. o accesslog Ruta. el gui´ n busca en el a o directorio en el cual fue instalado. Si usa hgwebdir. En principio. Si a˜ ade opciones [web] a su fichero personal hgrc los guiones CGI no leer´ n tal fichero hgrc. port Entero. De forma predeterminada. Para logar que los a guiones CGI vean sus configuraciones. o a˜ ada tales opciones al fichero global hgrc. o bien cree un fichero hgrc en el directorio personal del usuario bajo cuyo ID se ejecuta su servidor web.

´ Si usted especifica expl´citamente nombres reales de ficheros en la l´nea de comandos.py src/watcher/_watcher.c src/watcher/watcher. Mercurial opera unicamente ı ı sobre dichos ficheros. esto es lo que hace el comando a “hg add”. lo recorrer´ antes de continuar con el directorio actual.2.1. a 1 2 3 4 5 $ ? ? ? ? hg status src src/main. Nombrado de ficheros simple Mercurial usa un mecanismo unificado “bajo el cap´ ” para manejar nombres de ficheros. ı 1 $ hg add COPYING README examples/simple. a u Muchos comandos operar´ n sobre el directorio de trabajo completo. La manera en que los comandos operan con nombres de fichero es la siguiente.py Cuando usted provee el nombre de un directorio. Cada comando se como porta de manera uniforme con respecto a los nombres de fichero. ´ Ejecuci´ n de comandos sin ningun nombre de fichero o Los comandos de Mercurial que trabajan con nombres de fichero tienen comportamientos por defecto adecuados cuando son utilizados sin pasar ning´ n patr´ n o nombre de fichero. Mercurial va por todos los ficheros y subdirectorios de un directorio en orden alfab´ tico. Aqu´ presento unas cuantas reglas generales que usted puede usar para que es lo que probablemente ı har´ un comando si usted no le pasa ning´ n nombre de fichero con el cual trabajar.py src/xyzzy. e Cuando encuentra un subdirectorio. Por ejemplo.txt 7. Mercurial interpreta eso como “opere en cada fichero en este directorio y sus subdirectorios”. 75 . como usted esperar´a. El tipo de comportamiento depende de lo que u o haga el comando.Cap´tulo 7 ı Nombres de ficheros y asociaci´ n de o patrones Mercurial provee mecanismos que le permiten trabajar con nombres de ficheros en una manera consistente y expresiva. 7.

Vamos a ejecutar el comando “hg ı status” desde un subdirectorio.. a´ n si usted los llama dentro de un subdirectorio. pas´ ndole la salida del comando “hg root”..in adding . y a hacer que opere en el directorio de trabajo completo./COPYING .py adding watcher/_watcher.txt hg status ‘hg root‘ ..py src/main..py MANIFEST.py watcher/_watcher.py .py adding main../setup.py adding xyzzy..”./examples/performant. adding main.txt Siguiendo la misma l´nea.c src/watcher/watcher.c watcher/watcher.py adding .txt $ hg add -n . borrar ficheros o a accidentalmente al ejecutar “hg remove” sin ning´ n argumento..txt 76 .c adding watcher/watcher../examples/simple.py src/xyzzy. a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ cd src $ hg add -n adding . si no es el adecuado para usted./examples/performant. Esto lo proteje a usted de. a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ A A A ? ? ? ? ? ? ? $ A A A ? ? ? ? ? ? ? hg status COPYING README examples/simple. algunos comandos normalmente imprimen las rutas de ficheros con respecto a la ra´z del ı ı repositorio.py adding xyzzy. por ejemplo.Si el comando tiene efectos dif´ciles o incluso imposibles de revertir. se le obligar´ a usted a proveer expl´citaı a ı mente al menos un nombre o patr´ n (ver m´ s abajo)./setup.in . Si un comando opera normalmente a en todo el directorio de trabajo./README . Dichos comandos imprimir´ n las rutas de los ficheros u a respecto al directorio en que usted se encuentra si se les pasan nombres expl´citos.py src/watcher/_watcher.py xyzzy.py setup. a la vez que todas las rutas de ficheros se imprimen respecto a nuestro subdirectorio.py ./MANIFEST.in examples/performant.. usted puede llamarlo para que trabaje s´ lo en el directorio actual y sus subdirectorio o pas´ ndole el nombre “.py main. u Es f´ cil evitar este comportamiento por defecto./MANIFEST.c adding watcher/watcher.py adding watcher/_watcher.

el trabajo de asociar patrones con nombres de ficheros recae sobre el int´ rprete de comandos. Tambi´ n puede hacer o e que impriman el nombre de cada fichero. para que usted no sea sorprendido por lo que sucede. dentro de un unico directorio. ı ı ı no tiene mucho sentido repetir esto de vuelta a usted. 1 2 $ hg add ’glob:*.4. ni directorios. Si Mercurial est´ actuando en un fichero impl´citamente. MacOS.py La secuencia “**” se asocia con cualquier cadena. o ı Mercurial soporta dos tipos de sintaxis para patrones.py’ adding main. usualmente o ı ı se imprimir´ el nombre del fichero.7. u o ı o 7. No es una elemento ı ´ est´ ndar de los tokens de glob de Unix. del T. En sistemas tipo Unix (Linux. por favor note que yo tengo el cuidado de rodear todos mis patrones con o comillas sencillas. 2 N. o o del T. y tambi´ n deber´a ser familiar para los usuarios o e e ı de la l´nea de comandos de Windows. y es muy util. colecci´ n. o a a e a Usted puede silenciar a los comandos que se comportan de esta manera usando la opci´ n -q. $ hg status ’glob:**.1.3. e 7.py’ 1 N. 77 . y har´ la expansi´ n necesaria. tambi´ n conocidas a e como regexps. etc. pero es aceptado por varios int´ rpretes Unix populares. es el a mismo tipo de asociaci´ n de patrones usado por el int´ rprete de Unix. a Esto es el principio de m´nima sorpresa. e La sintaxis re2 es m´ s poderosa. ni patrones (ver m´ s abajo). o e o seguido por el patr´ n en s´. Grupo. A prop´ sito. a´ n aquellos que usted indic´ expl´citamente. a o Para pasar un patr´ n en vez de un nombre normal en la l´nea de comandos. ´ La secuencia “*” se asocia con cualquier cadena. La que se usa con m´ s frecuencia se denomina glob1 . Si un comando opera en un fichero que usted no pas´ expl´citamente en la l´nea de comandos. Mercurial le permite usar patrones para identificar a ficheros. Uso de patrones para identificar ficheros Adem´ s de trabajar con nombres de ficheros y directorios. usted debe indicarle expl´citamente a Mercurial que el nombre que se le e ı pasa es un patr´ n. el mecanismo es simple: o ı 1 syntax:patternbody Un patr´ n es identificado por una cadena de texto corta que indica qu´ tipo de patr´ n es. porque a ı usted no pas´ nombres. Si usted se ha referido expl´citamente a un fichero en la l´nea de comandos. Patrones glob estilo int´ rprete e Este es un vistazo general de los tipos de patrones que usted puede usar cuando est´ usando asociaci´ n con patrone a o glob. lo m´ s seguro es decirle a usted qu´ se est´ haciendo. El manejo de patrones de Mercurial es expresivo. Por esto.. para que no sean expandidos por el int´ rprete antes de que Mercurial pueda verlos.). le permite especificar patrones usando expresiones regulares. y cruza los l´mites de los directorios. as´ que Mercurial identificar´ autom´ ticamente o e ı a a los nombres que son patrones. Expresiones regulares. usted puede o a omitir el prefijo “glob:” en Windows. En estos sistemas. seguido por un dos puntos. a e 1 2 $ cd . pero tambi´ n es seguro usarlo. aglomeraci´ n. usando la opci´ n -v.4. en los ejemplos siguientes. ı Cuando Mercurial hace asociaci´ n autom´ tica de patrones en Windows. el int´ rprete no expande los patrones. En Windows. usa la sintaxis glob. Reportar que est´ pasando a ´ El ejemplo con el comando “hg add” en la secci´ n anterior ilustra algo m´ s que es util acerca de los comandos de o a Mercurial.

Esta sintaxis est´ basada en la misma del lenguaje Perl. En vez de eso. Las expresiones regulares al estilo Perl se encuentran documentadas exhaustivamente en una multitud de sitios web. que es el a dialecto m´ s popular en uso (por ejemplo.py setup.py src/main.py}’ ? MANIFEST. haciendo que se e asocie con cualquier caracter sencillo que no se encuentre en la clase. se niega la clase. en donde todo el grupo es asociado si cualquier subpatr´ n en o el grupo puede ser asociado.py 7.{in. Ella se asocia con cualquier caracter sencillo dentro de la clase.py src/watcher/watcher. ya que las mismas no son usadas e ı frecuentemente. La clase se finaliza con un caracter “]”. o 1 2 3 $ hg status ’glob:**[nr-t]’ ? MANIFEST.py Cuidado! No olvide que si usted desea asocia un patr´ n con cualquier directorio. y en muchos libros.4. 1 2 $ hg status ’glob:**.?’ ? src/watcher/_watcher. tambi´ n se usa en Java).in ? setup. Un “{” marca el inicio de un grupo de subpatrones. n 1 2 3 4 5 6 7 8 $ ? $ A A ? ? ? hg status ’glob:*. Asociaci´ n con patrones de expresiones regulares re o Mercurial acepta la misma sintaxis para expresiones regulares del lenguaje de programaci´ n Python (internamente o se usa el motor de expresiones regulares de Python). me enfocar´ en unas cuantas cosas que usted deber´a conocer si tiene e ı la necesidad de usar expresiones regulares en Mercurial.py La secuencia “?” se asocia con cualquier caracter sencillo. Una clase puede contener m´ ltiples rangos de la forma “a-f”. no deber´a usar el elemento para asociar o ı ´ con cualquier cadena “*”. ya que este s´ lo generar´ asociaciones dentro de un solo directorio.py setup.py examples/performant.” separa los subpatrones. a e No discutir´ el dialecto de expresiones regulares de Mercurial en detalle aqu´. Este peque˜ o ejemplo ilustra la diferencia entre los dos.c El caracter “[” marca el inicio de una clase de caracteres. 78 .py examples/performant.2. use el o a caracter para asociar con cualquier cadena “**”. El caracter “.py src/main.py’ setup.py hg status ’glob:**.txt Si el primer caracter en aparecer despu´ s de “[” en la clase de caracteres es un “!”.in ? src/xyzzy. En vez de eso.py src/watcher/watcher. y el “}” finaliza el grupo. 1 2 3 $ hg status ’glob:*.py’ examples/simple. que u en este caso es una abreviaci´ n para “abcdef”.3 4 5 6 7 A A ? ? ? examples/simple.

o 7. En o ı otras palabras. This treatment of uppercase and lowercase letters as interchangeable is also referred to as case folding. Para buscar coincidencias en cualquier sitio dentro de una cadena. e intercalarlos como desee. This is not very likely to affect you. o --exclude. que la asociaci´ n de una expresi´ n se hace desde el inicio de la cadena. o -X. Los comandos que operan con nombres de fichero aceptan dos opciones de filtrado. When a file or directory is created.7. There are three common ways to handle case in names. Un detalle a tener en cuenta es que. las de Mercurial est´ n enra´zadas. si desea asociar ficheros en este directorio. but it could surprise you if you don’t know about it. a´ n si usted se encuentra en un subdirectorio foo. This is the standard arrangement on Windows and MacOS. El filtro -I puede verse como un “procese todos los ficheros que coincidan con este filtro”. empiece su patr´ n con un “. Ignorar ficheros y directorios no deseados XXX. The names foo and FoO identify the same file. le permite especificar un patr´ n con el que deben coincidir los ficheros para ser procesados. its case is ignored. o 1 2 3 $ hg status -X ’**. le permite limitar a´ n m´ s dichos o u a ficheros mediante el uso de filtros. no se buscan a ı o o coincidencias dentro de la cadena. When an existing file is being looked up. Case preserving. o --include. 1 2 $ hg status -I ’*. Uppercase and lowercase versions of a letter are treated as identical.txt 7. 7. 79 .py’ src ? src/watcher/_watcher. o Usted puede pasar m´ ltiples veces las opciones -I y -X en la l´nea de comandos. su patr´ n u o debe empezar con “foo/”. si le son familiares las expresiones regulares al estilo Perl. relativo a la ra´z del repositorio. le brinda una manera de evitar procesar ficheros.Una expresi´ n regular es comparada contra un nombre de fichero completo. and can be retrieved and displayed by the operating system.*”. Completely case insensitive.in’ ? MANIFEST.5. Mercurial interpreta los patrones que usted pase usando la sintaxis glob (pero usted puede usar expresiones regulares si lo necesita). ´ Sensibilidad a mayusculas Si usted est´ trabajando en un ambiente de desarrollo mixto que contiene tanto sistemas Linux (u otro Unix) y a sistemas Mac o Windows. but insensitive.c ? src/xyzzy. deber´a tener en mente el hecho de que ellos tratan case (“N” versus “n”) of file names in ı incompatible ways. both when creating a file and during subsequent accesses. Filtrado de ficheros Mercurial no s´ lo le provee una variedad de formas para especificar ficheros. Por u ı defecto.6.in ´ El filtro -X puede verse como “procese unicamente los ficheros que no coincidan con este patr´ n”. -I. This is common on older DOS-based systems. Operating systems and filesystems differ in the way they handle the case of characters in file and directory names. Esto es. and it’s easy to deal with if it does. si coinciden con este patr´ n. the case of its name is stored.

y Mercurial reporta un conflicto de may´ sculas/min´ sculas cuando usted trata de actualizar (“hg update”) o u u fusionar (“hg merge”).9.7. but insensitive. y usted no podr´ actualizar (“hg update”) su directorio de trabajo a dicho conjunto de cambios en un a sistema Windows o MacOS. ambos ser´ n almacenados correctamente en a el repositorio. e 80 . Si el sistema de ficheros conserva las diferencias entre may´ sculas. Mercurial ver´ el conflicto entre los dos nombres de fichero que el sistema de a ficheros tratar´a como el mismo. Nota: Antes de la versi´ n 0. y j´ lelo (“hg pull”) o emp´ jelo (“hg push”) a su sistema Windows o MacOS. y use el comando “hg rename” o ı de Mercurial para cambiar los nombres de cualquiera de los ficheros o directorios problem´ ticos para que no causen a m´ s conflictos. ´ ´ Arreglar un conflicto de mayusculas/minusculas Si usted est´ usando Windows o Mac en un entorno mixto donde algunos de sus colaboradores est´ n usando Linux a a o Unix. Si un usuario de Windows o Mac jalan este cambio. On Unix-like systems. un PC ejecutando Windows. ı a o o 7. Linux will handle names on that filesystem in a case preserving. y trasladar de manera segura la memoria y el repositorio de ida y vuelta entre un Mac. a a u y actual´celo (“hg update”) a la revisi´ n con los nombres que ya no generan conflictos. Mercurial tratar´ los nombres que s´ lo difieren en may´ sculas como uno solo y el mismo. it is possible to have any or all of the above ways of handling case in action at once.Case sensitive. el procedimiento para arreglar el problema es simple.3.7. porque el mecanismo de a almacenamiento de Mercurial es seguro frente a sensibilidad/insensibilidad a may´ sculas. clone el repositorio problema all´. Sin embargo.3. Esto significa que usted puede usar herramientas normales de u copia de ficheros para transferir un repositorio Mercurial a. Si un usuario de Linux consigna cambios a dos u ficheros. if you use a USB thumb drive formatted with a FAT32 filesystem on a Linux system.7. y no detectaba los conu u flictos con nombres de ficheros. The case of a name is significant at all times. S´ lo busque un sistema Linux o Unix cercano. Si usted est´ usando una versi´ n m´ s antigua de a o a Mercurial en Windows o MacOS.1. ´ ´ Detecci´ n de conflictos de mayusculas/minusculas o Al operar en el directorio de trabajo. a o u Un aspecto importante de este enfoque es que es posible consignar un conjunto de cambios en un sistema de ficheros sensible a may´ sculas (t´picamente Linux o Unix) que terminar´ causando problemas para usuarios en sisu ı a temas insensibles a may´ sculas (usualmente en Windows o MacOS). por ejemplo. Consigne este cambio. For example. Los nombres de fichero son traducidos para que puedan ser almacenados de manera segura tanto en sistemas sensibles como insensibles a may´ sculas. ı o El conjunto de cambios con los nombres con conflictos de may´ sculas/min´ sculas permanecer´ en el historial de u u a su proyecto. The names foo and FoO identify different files.C. 7. Mercurial no usaba un mecanismos seguro frente o a sensibilidad/insensibilidad a may´ sculas o min´ sculas. This is the way Linux and Unix systems normally work. Mercurial respeta la pol´tica de nombrado del sistema de ficheros en que ı se encuentre el directorio de trabajo. way. Y ser´ n representados correctamente como ficheros separados. pero no es u sensible a ellas. Almacenamiento portable y seguro de repositorios El mecanismo de almacenamiento de los repositorios en Mercurial es robusto frente a sensibilidad/insensibilidad u a may´ sculas.c y el otro llamado MyFile.2. o hagan fusi´ n (“hg o merge”) con ese conjunto de cambios. no tendr´ n problemas inicialmente. una vez que u ellos traten de actualizar (“hg update”) el directorio de trabajo con ese conjunto de cambios. y un sistema Linux 7. e impedir´ que ocurra la actualizaci´ n o fusi´ n. una memoria USB. le recomiendo en´ rgicamente que se actualice. en los directorios de trabajo de otros a usuarios de Linux. pero puede continuar el desarrollo sin impedimentos. uno de ellos llamado myfile.

Mercurial tampoco impone restricci´ n alguna al nombre o de una etiqueta.0 ´ Una etiqueta no es m´ s que un “nombre simb´ lico” para una revisi´ n. El nombre a a u de una etiqueta no puede tener ninguno de los siguientes caracteres: Dos puntos (ASCII 58. a En este cap´tulo. En o ı ´ paralelo. portar a una nueva plataforma. Dar un nombre persistente a una revisi´ n o Cuando usted decide otorgar a una revisi´ n el nombre particular de una “versi´ n”. 1 2 3 4 5 $ hg init mytag $ cd mytag $ echo hello > myfile $ hg commit -A -m ’Initial commit’ adding myfile Mercurial le permite dar un nombre permanente a cualquier revisi´ n usando la orden “hg tag”. pueden liberar versiones “menores”. a Muchos proyectos de software liberan una versi´ n “mayor” que contiene nuevas caracter´sticas substanciales. “:”) Retorno de carro (return) (ASCII 13. para cualquiera que sea el prop´ sito o a o o que se tenga en ese momento (reproducir un fallo. m´ s all´ de lo necesario para asegurar que una etiqueta pueda procesarse sin ambig¨ edades. Esto le permitir´ reproducir dicha versi´ n en una fecha posterior. comenzaremos hablando de c´ mo mantener registro de etapas del proyecto como las liberaciones ı o de una versi´ n. brind´ ndole una forma permanente y sencilla de referirse a una revisi´ n.Cap´tulo 8 ı Administraci´ n de versiones y desarrollo o ramificado Mercurial ofrece varios mecanismos que le permiten administrar un proyecto que avanza en m´ ltiples frentes u simult´ neamente.1. Sin causa de o sorpresa. y c´ mo puede o o ayudar Mercurial a aislar y administrar tal trabajo. Las etiquetas existen unicamente para su a o o conveniencia. 8. demos un vistazo a la estructura usual de un proyecto de software. etc). es buena idea grabar la identidad o o de tal revisi´ n. 1 $ hg tag v1. pero con arreglos para algunos fallos. esos nombres se llaman “tags” (etiquetas). “\r”) 81 . Usualmente estas son id´ nticas a las versiones mayores en las cuales e est´ n basadas. Para entender estos mecanismos. Mercurial no interpreta de a o ninguna manera los nombres de las etiquetas que usted use. Continuaremos hablando del flujo de trabajo entre las diferentes fases de un proyecto.

com> Tue Feb 10 18:23:29 2009 +0000 Initial commit Siempre que requiera indicar un ID de revisi´ n a una orden de Mercurial. o la cantidad de etiquetas que una misma revisi´ n pueda ı o tener. y lo usar´ . “\n”) ı Puede usar la orden “hg tags” para ver las etiquetas presentes en su repositorio. por n´ mero de revisi´ n.0 for changeset 1d3fd3640aaa 0:1d3fd3640aaa v1. la facilidad de usarlas para identificar o revisiones disminuir´ r´ pidamente. despu´ s con el n´ mero de revisi´ n y finalmente con un hash unico de la e u o revisi´ n. es perfectamente razonable asigı narle una etiqueta a cada una de ellas.Nueva l´nea (ASCII 10. a Cuando usted ejecuta “hg log”. Tambi´ n significa que la etiqueta tip a a e siempre aparecer´ como primera etiqueta listada al desplegar la orden “hg tags”. que identifica siempre la revisi´ n m´ s reciente en el repositorio. si se muestra una revisi´ n que tenga etiquetas asociadas a ella. no es muy buena idea tener “demasiadas” (la cantidad variar´ de un proyecto a otro). o 1 2 3 $ hg tags tip v1. aceptar´ un nombre de etiqueta en su o a lugar. se imprimir´ n o a tales etiquetas. Internamente. cada revisi´ n o ´ marcada se identifica primero con su nombre. Lo que significa u o usualmente que las etiquetas m´ s recientes se listan antes que las m´ s antiguas. de pocos d´as. 1 2 3 4 5 6 7 8 9 10 11 12 13 $ hg log changeset: tag: user: date: summary: changeset: tag: user: date: summary: 1:515e5c86f496 tip Bryan O’Sullivan <bos@serpentine. Si tiene demasiadas etiquetas. o a Al desplegar la orden “hg tags”. debido a a a que la intenci´ n es ayudarle a encontrar revisiones. Pero si tiene un sistema de construcci´ n autom´ tica de binarios que asegura o a 82 .com> Tue Feb 10 18:23:29 2009 +0000 Added tag v1. Siendo pr´ cticos. La etiqueta tip es una etiqueta “flotante” especial.0 1:515e5c86f496 0:1d3fd3640aaa Note que tip aparece en en listado generado por “hg tags”. las etiquetas se listan en orden inverso.com> date: Tue Feb 10 18:23:29 2009 +0000 summary: Initial commit No hay l´mites en la cantidad de etiquetas por repositorio. Mercurial traducir´ su nombre de etiqueta en el ID de revisi´ n correspondiente. a o a 1 2 3 4 5 6 7 8 9 10 $ echo goodbye > myfile2 $ hg commit -A -m ’Second commit’ adding myfile2 $ hg log -r v1.0 Bryan O’Sullivan <bos@serpentine. si su proyecto tiene etapas (milestones) frecuentes. a a Por ejemplo.0 user: Bryan O’Sullivan <bos@serpentine. Al desplegarse.0 changeset: 0:1d3fd3640aaa tag: v1.

hgtags. la orden reportar´ el lugar del error. lo unico que debe hacer es mover la o etiqueta hacia la revisi´ n correcta tan pronto como localice el error. Si encuentra un error o u e en el fichero . a y hace la consignaci´ n del cambio al mismo autom´ ticamente. para que identifique una revisi´ n distinta.1 for changeset 55d99d62d333 8. seguido por un espacio.1 2:55d99d62d333 De todas maneras habr´ un registro permanente de la antigua identidad de la etiqueta. Posteriormente a a e ejecute de nuevo la orden “hg tags” para asegurarse de que su arreglo fue aplicado correctamente . 83 .hgtags: cuando Mercurial procesa las etiquetas en el repositorio. lee la versi´ n consignada m´ s reciente del fichero. aseg´ rese de ejecutar la orden “hg tags” despu´ s de consignar. estar´a introduciendo mucho ruido si se usara una etiqueta para cao ı da generaci´ n exitosa.hgtags durante una fusi´ n. Cada l´nea comienza con un hash de conjunto de ı ı cambios.hgtags.1’ already exists (use -f to force) $ hg tag -f -r 2 v1.0 $ hg tags tip 3:31eda97c4db9 Tambi´ n puede modificar una etiqueta en cualquier momento. Deber´ usar la opci´ n -f para indicarle a Mercurial que realmente desea actualizar a o la etiqueta.hgtags. 1 2 3 $ hg tag --remove v1.1 $ hg tags tip 5:b26c4daf4a9d v1. o a ver´ un conjunto de cambios correspondiente en la salida de “hg log”. use “hg tag --remove”. las encontrar´ en un fichero llamado .1. Mercurial modifica este fichero. Si ha creado etiquetas. M´ s bien. En cambio. Esto significa que cada vez que ejecuta “hg tag”.1 1:515e5c86f496 $ hg tag -r 2 v1.1. o o a ı simplemente evitar las etiquetas para llevar cuenta de la posibilidad de generaci´ n de binarios. o a Una consecuencia desafortunada de este dise˜ o es que usted no puede verificar que su fichero .hgtags.1 abort: tag ’v1.hgtags fusionn ado sea correcto hasta despu´ s de haber consignado un cambio. que podr´ arreglar y despu´ s consignar. a a ´ Por lo tanto no hay problema al marcar con una etiqueta una revisi´ n incorrecta. a 1 2 3 4 5 6 7 $ hg tip changeset: tag: user: date: summary: 5:b26c4daf4a9d tip Bryan O’Sullivan <bos@serpentine. pero a veces hace su aparici´ n durante una fusi´ n. podr´a usar tags para generaciones fallidas (¡en caso de que estas sean raras!). simplemente e o usando una nueva orden “hg tag”. Cuando invoca la orden “hg tag”. o Mercurial almacena las etiquetas en un fichero controlado por revisiones en su repositorio.com> Tue Feb 10 18:23:30 2009 +0000 Added tag v1. nunca lee la copia de trabajo del fichero . seguido por el nombre de una etiqueta. a o o El formato del fichero es sencillo: Consiste de una serie de l´neas. hay un detalle para tener en cuenta al a o modificar el fichero . Si est´ resolviendo un conflicto en el fichero . pero Mercurial no la usar´ . 1 2 3 4 5 6 7 8 9 10 $ hg tag -r 1 v1.que cada revisi´ n puede generarse limpiamente.1 $ hg tags tip 4:eb33d1c642f4 v1.hgtags durante una fusi´ n. o Si quiere eliminar una etiqueta que no desea. Manejo de conflictos entre etiquetas durante una fusi´ n o Usualmente no tendr´ que preocuparse por el fichero . As´ que si se encuentra resolviendo un conflicto en e ı .

lo que usted posiblemente desear´a ser´an etiquetas locales.0”. Si est´ tratando de a a o a encontrar un fallo sutil. ´ Puede haber prisa por una nueva versi´ n “principal”. ı e “El gran cuadro” Las ramas representan un barrido de la evoluci´ n del proyecto. Cuando las etiquetas permanentes son demasiado Dado que las etiquetas de Mercurial est´ n controladas por revisiones y se llevan en el historial del proyecto.8.hgtags. ya hemos visto que en varias ocasiones Mercurial trata a todo el historial como una serie de ramas y fusiones.2. una nueva versi´ n con un arreglo de fallo a la ultima versi´ n. el nuevo clon no contendr´ el a historial que creo la etiqueta que us´ para clonar el repositorio. Sin embargo. Administrar ramas en repositorios estilo gran cuadro En Mercurial la forma m´ s sencilla de aislar una rama del “gran cuadro” es a trav´ s de un repositorio dedicaa e do.0 Ahora puede clonar un repositorio compartido nuevo myproject-1.1. pero que en esencia comparten un nombre. . Etiquetas y clonado Puede haber notado que la orden “hg clone” tiene la opci´ n -r que le permite clonar una copia exacta del o repositorio hasta un conjunto de cambios espec´fico. puede e o comenzar a prepararse para versiones de mantenimiento futuras a partir de la versi´ n 1. n Exponen la narrativa de c´ mo se desarroll´ el c´ digo. la gente les da nombres y o hablan acerca de ellas en sus conversaciones. Cualquier etiqueta que usted cree usando -l se mantena dr´ local al repositorio en el que est´ trabajando en ese momento. o o o 8. el conjunto de cambios en el cual esta se almacena necesariamente se refiere a un conjunto de cambios anterior.0 marcando con una etiqueta o la revisi´ n con la cual prepar´ la versi´ n 1.0. Si cuenta con un repositorio compartido existente —llam´ moslo myproject—que alcanz´ la etapa “1. o o o y una versi´ n de “mantenimiento correctivo” a una versi´ n antigua que ha entrado en modo de mantenimiento. Esto tiene una interacci´ n con etiquetas que puede sorprender a los desprevenidos. Cuando ejecuta “hg clone -r foo” para clonar un repositorio hasta la etiqueta foo. a e 8. o o o 1 2 $ cd myproject $ hg tag v1.2. pensemos en el hecho de que un proyecto tiene muchas ı piezas concurrentes de trabajo en desarrollo al mismo tiempo. Realmente lo que tenemos aqu´ es dos ideas que se relacionan perif´ ricamente. ˜ El flujo de cambios—El gran cuadro vs. “El cuadro peque˜ o” Las ramas son artefactos de las actividades diarias de desarrollar y fusionar cambios. as´ que cuando usted crea una etio ı ´ queta. el pequeno Retomando lo mencionado en el comienzo de un cap´tulo.3.2. o Para estos casos. Esto guardar´ la etiqueta en un fichero llamado .1. El hecho de dar nombres a las revisiones tiene a usos m´ s all´ que simplemente hacer notar que la revisi´ n 4237e45506ee es realmente v2. El nuevo clon no tendr´ historial posterior a la revisi´ n que usted ı a o haya especificado.hg/localtags no est´ controlado por revisiones. o Recuerde que una etiqueta se almacena como una revisi´ n al fichero . A diferencia de o a . ı 8. El resultado es que tendr´ exactamente el subconjunto o a correcto del historial del proyecto en el nuevo repositorio. pero.hgtags. no la etiqueta que podr´a haber esperado.3.0. Puede crear una etiqueta local con ı ı la opci´ n -l de la orden “hg tag”. o o Usualmente la gente se refiere a esas direcciones concurrentes de desarrollo como “ramas”. 84 . posiblemente desear´a colocar una etiqueta record´ ndole algo como “Ana vio los s´ntomas en ı a ı esta revisi´ n”.1 con tal etiqueta.0. todas a las personas involucradas ver´ n las etiquetas que usted haya creado.hg/localtags.

1 2 3 4 $ cd . veremos varias alternativas con las que n ı Mercurial puede ayudarle a administrar tales arreglos de fallo sin duplicar su trabajo. $ hg clone myproject my-feature updating working directory 2 files updated. basta con jalar los cambios de la rama de mantenimiento a la rama objetivo en su clon a local.1 searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files Mientras tanto.. $ hg clone myproject myproject-1. 0 files unresolved Posteriormente.1 my-1.0.0. En el caso m´ s sencillo. 0 files unresolved $ cd my-1. el desarrollo para la siguiente versi´ n mayor puede continuar aislado e inc´ lume. 0 files merged.0. es muy probable que el fallo tambi´ n est´ en la rama principal (y posiblemente en otras ramas de mantenimiento tambi´ n). ellos clonar´an el repositorio myproject-1.0. si alguien necesita trabajar en la reparaci´ n de un fallo deber´a dirigirse a la liberaci´ n de vero ı o si´ n 1.4.1 updating working directory 2 files updated.0.0. 0 files removed. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ cd . 1 2 3 4 5 6 7 8 9 10 11 12 13 $ hg clone myproject-1. cuando tiene un fallo para arreglar en una rama de mantenimiento.1.0. No repita trabajo: fusi´ n entre ramas o En muchos casos. 85 . 0 files removed.. har´an sus cambios y los empujar´an o ı ı ı de vuelta.1’ $ hg push pushing to /tmp/branch-repo07QkL5/myproject-1. Solamente un e e e desarrollador extra˜ o desear´a corregir el mismo fallo muchas veces.0. 0 files removed.1-bugfix updating working directory 2 files updated. 0 files merged. por tanto. 0 files merged. 0 files unresolved $ cd my-feature $ echo ’This sure is an exciting new feature!’ > mynewfile $ hg commit -A -m ’New feature’ adding mynewfile $ hg push pushing to /tmp/branch-repo07QkL5/myproject searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files 8.1-bugfix $ echo ’I fixed a bug using only echo!’ >> myfile $ hg commit -m ’Important fix for 1. en el repositorio o o myproject.1 que viene en camino.

Por ejemplo. 0 files unresolved $ cd myproject-merge $ hg pull . Es f´ cil de entender o a gracias a su simplicidad. Le est´ indicando que su consignaci´ n ocurı a o rir´ en la rama llamada default. y es dif´cil cometer errores.0.5.1 pulling from . Si se encuentra m´ s en la categor´a “usuario diestro” (y sus colaboradores tambi´ n). o busque la l´nea que contiene el texto “HG: branch default” al final. 0 files merged. indic´ ndole qu´ conjunto de cambios es la punta de cada una.0.1 2 3 4 5 6 7 8 9 10 11 12 13 $ cd . puede considerar otra altera ı e nativa para administrar las ramas. 0 files unresolved (branch merge. Incluso antes de que empiece a nombrar ramas por su cuenta. Nombrar ramas dentro de un repositorio La aproximaci´ n correcta en casi todas las oportunidades es aislar las ramas en los repositorios. cuando invoca la orden “hg commit”./myproject-1. 0 files removed.1 branch’ $ hg push pushing to /tmp/branch-repo07QkL5/myproject searching for changes adding changesets adding manifests adding file changes added 2 changesets with 1 changes to 1 files 8. El truco para trabajar de esta forma en Mercurial se logra gracias a que puede asignar un nombre persistente a una rama. Hay una relaci´ n uno a uno entre las ramas y los directorios con ı o los que est´ trabajando en su sistema../myproject-1.1 searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run ’hg heads’ to see heads..0. Esta orden mostrar´ las ramas prea sentes en su repositorio. a e 1 2 $ hg tip changeset: 0:c54ce9a68981 86 . Esto le permite usar emplear herramientas usuales (que no son conscientes de a Mercurial) para trabajar con los ficheros dentro de una rama/repositorio. 0 files merged. puede encontrar indicios de la rama default si los busca. 0 files removed. y empujar de nuevo a la rama principal. He mencionado con anterioridad la distinci´ n a nivel humano entre las ramas estilo o “cuadro peque˜ o” y “gran cuadro”. a Use la orden “hg branches” para empezar a trabajar con ramas nombradas.. pero antes de fusionarlos). Siempre existe una rama llamada default. ’hg merge’ to merge) A continuaci´ n deber´ mezclar las cabezas de las dos ramas. $ hg clone myproject myproject-merge updating working directory 3 files updated. don’t forget to commit) $ hg commit -m ’Merge bugfix from 1. o a 1 2 3 4 5 6 7 8 9 10 11 $ hg merge 1 files updated. Mientras que Mercurial trabaja con muchas ramas del estilo “cuadro peque˜ o” n n en el repositorio todo el tiempo (por ejemplo cuando usted jala cambios. tambi´ n puede e trabajar con varias ramas del “cuadro grande”. y se lanza su editor para introducir el mensaje de la consignaci´ n.

3 4 5 6 7 8 9

tag: user: date: summary:

tip Bryan O’Sullivan <bos@serpentine.com> Tue Feb 10 18:23:16 2009 +0000 Initial commit

$ hg branches default

0:c54ce9a68981

´ Dado que todav´a no ha creado ramas nombradas, la unica que ver´ ser´ default. ı a a Para hallar cu´ l es la rama “actual”, invoque la orden “hg branch”, sin argumento alguno. Le informar´ en qu´ raa a e ma se encuentra el padre del conjunto de cambios actual.
1 2

$ hg branch default Para crear una nueva rama, invoque la orden “hg branch” de nuevo. En esta oportunidad, ofrezca un argumento: el nombre de la rama que desea crear.

1 2 3 4

$ hg branch foo marked working directory as branch foo $ hg branch foo Despu´ s de crear la rama, usted podr´a desear ver el efecto que tuvo la orden “hg branch”. ¿Qu´ reportan las e ı e ordenes “hg status” y “hg tip”?

1 2 3 4 5 6 7 8

$ hg status $ hg tip changeset: 0:c54ce9a68981 tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:16 2009 +0000 summary: Initial commit

Nada cambia en el directorio actual, y no se ha a˜ adido nada al historial. Esto sugiere que al ejecutar la orden “hg n branch” no hay un efecto permanente; solamente le indica a que nombre de rama usar´ la pr´ xima vez que consigne a o un conjunto de cambios. Cuando consigna un cambio, Mercurial almacena el nombre de la rama en la cual consign´ . Una vez que haya o cambiado de la rama default y haya consignado, ver´ que el nombre de la nueva rama se mostrar´ cuando use la a a ´ orden “hg log”, “hg tip”, y otras ordenes que desplieguen la misma clase de informaci´ n. o
1 2 3 4 5 6 7 8 9 10

$ echo ’hello again’ >> myfile $ hg commit -m ’Second commit’ $ hg tip changeset: 1:b108bc883cbc branch: foo tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:17 2009 +0000 summary: Second commit

87

´ Las ordenes del tipo “hg log” imprimir´ n el nombre de la rama de cualquier conjunto de cambios que no est´ en la a e rama default. Como resultado, si nunca usa ramas nombradas, nunca ver´ esta informaci´ n. a o Una vez que haya nombrado una rama y consignado un cambio con ese nombre, todas las consignaciones subsecuentes que desciendan de ese cambio heredar´ n el mismo nombre de rama. Puede cambiar el nombre de una rama en a cualquier momento con la orden “hg branch”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

$ hg branch foo $ hg branch bar marked working directory as branch bar $ echo new file > newfile $ hg commit -A -m ’Third commit’ adding newfile $ hg tip changeset: 2:7f37f4b1f9a3 branch: bar tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:17 2009 +0000 summary: Third commit

Esto es algo que no har´ muy seguido en la pr´ ctica, debido que los nombres de las ramas tienden a tener vidas largas. a a (Esto no es una regla, solamente una observaci´ n.) o

8.6.

Tratamiento de varias ramas nombradas en un repositorio

Si tiene m´ s de una rama nombrada en un repositorio, Mercurial recordar´ la rama en la cual est´ su directorio de a a a trabajo cuando invoque una orden como “hg update” o “hg pull -u”. Se actualizar´ su directorio de trabajo actual a a la punta de esta rama, sin importar cu´ l sea la punta “a lo largo del repositorio”. Para actualizar a una revisi´ n que a o est´ en una rama con distinto nombre, puede necesitar la opci´ n -C de “hg update”. a o Este comportamiento puede ser sutil, as´ que ve´ moslo en acci´ n. Primero, recordemos en qu´ rama estamos ı a o e trabajando, y qu´ ramas est´ n en nuestro repositorio. e a
1 2 3 4 5 6 7 8 9 10 11 12

$ hg parents changeset: 2:7f37f4b1f9a3 branch: bar tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:17 2009 +0000 summary: Third commit $ hg branches bar foo default

2:7f37f4b1f9a3 1:b108bc883cbc (inactive) 0:c54ce9a68981 (inactive)

Estamos en la rama bar, pero existe otra rama m´ s antigua llamada “hg foo”. a Podemos hacer “hg update” entre los tipos de las ramas foo y bar sin necesidad de usar la opci´ n -C, puesto que o esto solamente implica ir linealmente hacia adelante y atr´ s en nuestro historial de cambios. a

88

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

$ hg update foo 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg parents changeset: 1:b108bc883cbc branch: foo user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:17 2009 +0000 summary: Second commit $ hg update bar 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg parents changeset: 2:7f37f4b1f9a3 branch: bar tag: tip user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:17 2009 +0000 summary: Third commit

Si volvemos a la rama foo e invocamos la orden “hg update”, nos mantendr´ en foo, sin movernos a la punta de a bar.
1 2 3 4

$ 0 $ 0

hg update foo files updated, 0 files merged, 1 files removed, 0 files unresolved hg update files updated, 0 files merged, 0 files removed, 0 files unresolved Al consignar un cambio a la rama foo se introducir´ una nueva cabeza. a

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

$ echo something > somefile $ hg commit -A -m ’New file’ adding somefile created new head $ hg heads changeset: 3:1ca81328634a branch: foo tag: tip parent: 1:b108bc883cbc user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:17 2009 +0000 summary: New file changeset: branch: user: date: summary: 2:7f37f4b1f9a3 bar Bryan O’Sullivan <bos@serpentine.com> Tue Feb 10 18:23:17 2009 +0000 Third commit

89

8.7.

Nombres de ramas y fusiones

Posiblemente ha notado que las fusiones en Mercurial no son sim´ tricas. Supongamos que su repositorio tiene dos e cabezas, 17 y 23. Si yo invoco “hg update” a 17 y aplico “hg merge” a 23, Mercurial almacena 17 como el primer padre de la fusi´ n, y 23 como el segundo. Mientras que si hago “hg update” a 23 y despu´ s aplico “hg merge” con o e 17, grabar´ a 23 como el primer padre, y 17 como el segundo. a Esto afecta el c´ mo elige Mercurial el nombre de la rama cuando usted hace la fusi´ n. Despu´ s de una fusi´ n, o o e o Mercurial mantendr´ el nombre de la rama del primer padre cuando consigne el resultado de la fusi´ n. Si el primer a o nombre de su padre es foo, y fusiona con bar, el nombre de la rama continuar´ siendo foo despu´ s de fusionar. a e No es inusual que un repositorio contenga varias cabezas, cada una con el mismo nombre de rama. Digamos que estoy trabajando en la rama foo, y usted tambi´ n. Consignamos cambios distintos; yo jalo sus cambios; Ahora tengo e ´ dos cabezas, cada una afirmando estar en la rama foo. El resultado de una fusi´ n ser´ una unica cabeza en la rama foo o a como usted esperar´a. ı Pero si estoy trabajando en la rama bar, y fusiono el trabajo de la rama foo, el resultado permanecer´ en la rama a bar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

$ hg branch bar $ hg merge foo 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don’t forget to commit) $ hg commit -m ’Merge’ $ hg tip changeset: 4:a6a8b6aebf33 branch: bar tag: tip parent: 2:7f37f4b1f9a3 parent: 3:1ca81328634a user: Bryan O’Sullivan <bos@serpentine.com> date: Tue Feb 10 18:23:17 2009 +0000 summary: Merge

En un ejemplo m´ s concreto, si yo estoy trabajando en la rama bleeding-edge, y deseo traer los arreglos m´ s a a recientes de la rama estable, Mercurial elegir´ el nombre de rama “correcto” (bleeding-edge) cuando yo jale una a fusi´ n desde estable. o

8.8.

´ Normalmente es util nombrar ramas

´ No deber´a considerar que las ramas nombradas son aplicables unicamente en situaciones con muchas ramas de ı ´ larga vida cohabitando en un mismo repositorio. Son muy utiles incluso en los casos de una rama por repositorio. En el caso m´ s sencillo, dar un nombre a cada rama ofrece un registro permanente acerca de en qu´ conjunto de a e cambios se gener´ la rama. Esto le ofrece m´ s contexto cuando est´ tratando de seguir el historial de un proyecto o a e ramificado de larga vida. Si est´ trabajando con repositorios compartidos, puede configurar el gancho pretxnchangegroup para que cada a uno bloquee los cambios con nombres de rama “incorrectos” que est´ n por adicionarse. Este provee una defensa a sencilla, pero efectiva, para evitar que la gente publique accidentalmente cambios de una rama “super nueva” a la rama “estable”. Tal gancho podr´a verse de la siguiente forma dentro de un repositorio compartido de hgrc. ı
1 2

[hooks] pretxnchangegroup.branch = hg heads --template ’branches ’ | grep mybranch

90

1. Un conjunto de cambios“simplemente e e malo” no es tan com´ n. e o 1 2 3 4 5 $ hg status ? b $ hg tip changeset: 1:be1cdd4c4fea tag: tip 1 N.1. y a dar cuenta de ellas apropiadamente. pero he olvidado hacerle “hg add”.1.Cap´tulo 9 ı Encontrar y arreglar sus equivocaciones Errar es humano. Hacer rollback una transacci´ n o En la secci´ n 4. el conjunto de cambios incompleto consiste en que cre´ un nuevo fichero fuente. pero tratar adecuadamente las consecuencias requiere un sistema de control de revisiones de primera categor´a. En este cap´tulo. Mercurial recuerda lo que hizo. Borrar el historial local La consignaci´ n accidental o Tengo el problema ocasional.) o A continuaci´ n una equivocaci´ n que me sucede frecuentemente: consignar un cambio en el cual he creado un o o nuevo fichero. discutiremos algunas t´ cnicas que puede usar cuando encuentra que hay un probı ı e lema enraizado en su proyecto. pero persistente de teclear m´ s r´ pido de lo que pienso. En mi caso. u ı 9. Cada vez o e o o que consigna un conjunto de cambios o lo jala de otro repositorio. 1 2 3 4 $ M $ $ hg status a echo b > b hg commit -m ’Add file b’ La salida de “hg status” despu´ s de la consignaci´ n confirma inmediatamente este error. Mercurial tiene unas caracter´sticas poderosas que le ayudar´ n a isolar las fuentes de ı a los problemas. Puede deshacer. (Ver en la secci´ n 9.4 una o anotaci´ n importante acerca del uso de esta orden. El significado igual que en los ambientes de sistemas manejadores de bases de datos se refiere a la atomicidad e integridad al devolver un conjunto de acciones que permitan dejar el repositorio en un estado consistente previo 91 .1.1. mencion´ que Mercurial trata modificaci´ n a un repositorio como una transacci´ n. 9.2. pero s´ resulta muy molesto.2. del T. 9. o hacer roll back1 .2. pero olvid´ hacerle “hg add”. exactamente una de tales acciones usando la orden “hg rollback”. que aveces resulta en a a consignar un conjunto de cambios incompleto o simplemente malo.

Su equipo de desarrollo puede tener un repositorio compartido para la versi´ n “0. volveremos a este terror´fico escenario posteriormente).4. Uso la orden “hg n e ´ rollback”. 1 2 3 4 5 6 7 8 9 10 11 12 $ hg rollback rolling back last transaction $ hg tip changeset: 0:c40e0a2ea41e tag: tip user: Bryan O’Sullivan <bos@serpentine. es o o ´ posible que publique tales cambios en el arbol compartido “0. Si yo publicara este conjunto de o o cambios a un repositorio compartido con un colega. La orden “hg rollback” excluir´ eficientemente los conjuntos de cambios que haya acabado de jalar. es bastante probable que algo en a se refiriera a b. Me convertir´a el sujeto de cierta indignaci´ n. o que vea jalando una sospechosa a a gran cantidad de cambios en el repositorio.com> date: Tue Feb 10 18:23:29 2009 +0000 summary: First commit $ hg status M a ? b El conjunto de cambios ya no est´ en el historial del repositorio.3. Ahora puedo hacer “hg add” al fichero b. no hay forma de que la desaparici´ n de un cambio se propague entre repositorios. Despu´ s de publicar.com> Tue Feb 10 18:23:29 2009 +0000 Add file b La consignaci´ n captur´ los cambios en el fichero a. En todo caso. pero solamente en el repositorio en el cual aplica “hg rollback”. Debido a que un roll back elimina el historial. y el directorio de trabajo cree que el fichero a ha a sido modificado. this time for real’ 9. En el peor de los casos.6 7 8 9 user: date: summary: Bryan O’Sullivan <bos@serpentine. o 9. el conjunto de cambios ha sido eliminado totlamente. confundiendo a todo su equipo de trabajo (pero no se preocupe.9”. La consignaci´ n y el roll back dejaron el directorio de trabajo exactamente como estaba antes de la o consignaci´ n.0”. ı o Como sea. la suerte me acompa˜ a—Encontr´ mi error antes de publicar el conjunto de cambios.9” y otra con cambios distintos o para la versi´ n “1. Mercurial a ´ agrupa todos los cambios de un “hg pull” a una unica transacci´ n y bastar´ con un “hg rollback” para deshacer o a esta equivocaci´ n. Erroneamente jalado Mantener ramas de desarrollo separadas de un proyecto en distintos repositorios es una pr´ ctica com´ n con Mercua u rial. el cual podr´a ı no estar presente cuando jalen mis cambios del repositorio.1. puede imaginar las consecuencias si tuviera un repositorio local “0. y Mercurial hace desaparecer el ultimo conjunto de cambios. por falta de atenci´ n. es muy probable que usted se de ı cuenta inmediatamente. un roll back es futil e El valor de “hg rollback” se anula cuando ha publicado sus cambios a otro repositorio. pero no el nuevo fichero b.1.0” en este. o Con este escenario. y hacer o de nuevo la consignaci´ n. dado que Mercurial mostrar´ el URL de donde est´ jalando. Un cambio desaparece totalmente al hacer roll back. o 1 2 $ hg add b $ hg commit -m ’Add file b. o 92 .9”. y jalara accidentalmente los cambios del repositorio compartido de la versi´ n “1.

a y volver´ a hostigarle. Si lo hace.1 +1.2 @@ original content +unwanted change Si no queremos ese cambio. es u e ı que el conjunto de cambios reaparecer´ en su repositorio.2. Revertir un cambio equivocado Si modifica un fichero y se da cuenta que no quer´a realmente cambiar tal fichero. puede hacer rollback del o a conjunto de cambios all´. usualmente deshace sus modificaciones.Si ha publicado un cambio en otro repositorio—particularmente si es un repositorio p´ blico—esencialmente u est´ “en terreno agreste. tal transacci´ n es la m´ s reciente o a o a de las que haya ocurrido en el repositorio. a (Si est´ absolutamente segruro de que el conjunto de cambios al que desea hacer rollback es el cambio m´ s reciente a a del repositorio en el cual public´ .” y tendr´ que reparar la equivocaci´ n de un modo distinto.5. y sabe que nadie m´ s pudo haber jalado de tal repositorio. observar´ que no es el comportamiento que o e a obtendr´ . o 9. Lo que pasar´ si publica un a a o a conjunto de cambios en alg´ n sitio. Si o espera poder hacer roll back a una transacci´ n despu´ s al antecesor. Comenzaremos modificando un fichero al u n cual Mercurial ya est´ siguiendo. pero es mejor no confiar en una soluci´ n de este estilo.) a 9. a 1 2 3 4 5 6 7 8 9 10 $ cat file original content $ echo unwanted change >> file $ hg diff file diff -r f8694d2c79ed file --. la orden necesaria es “hg revert”. Observa el conjunto de cambios padre del directorio y restaura los contenidos del fichero al estado de tal conjunto de cambios. (Es una forma larga de decirlo. y todav´a no ha consignado ı ı los cambios. Solamente hay un roll back Mercurial almacena exactamente una transacci´ n en su bit´ cora de transacciones. a 1 2 3 4 $ hg rollback rolling back last transaction $ hg rollback no rollback information available Una vez que haya aplicado un rollback en una transacci´ n a un repositorio.a/file Tue Feb 10 18:23:21 2009 +0000 +++ b/file Tue Feb 10 18:23:21 2009 +0000 @@ -1. podemos aplicar “hg revert” al fichero.) Ilustremos como act´ a la orden “hg revert” con un ejemplo peque˜ o. Esto significa que solamente puede hacer roll back a una transacci´ n. no podr´ volver a hacer rollback hasta que o a haga una consignaci´ n o haya jalado. 1 2 3 4 5 $ hg status M file $ hg revert file $ cat file original content 93 .1. hacer rollback y despu´ s volver a jalar del repositorio del cual hab´a publicado. tarde o temprano un ı o conjunto de cambios lograr´ colarse en un repositorio que usted no controle directamente (o del cual se ha olvidado).

deshar´ el estado “removido” del fichero. o 1 2 3 4 5 $ hg status ? file.orig $ cat file. Solamente lo “desmarcar´ ”. restaurar´ el fichero con sus contenidos sin modificaci´ n.1. a o Si usted hace “hg add” a un fichero. y no deseaba que Mercurial le diera seguimiento. revertir´ el estado de “adicionado” del fichero.2. y las dem´ s.orig original content unwanted change Este es un resumen de casos en los cuales la orden “hg revert” es de utilidad. o a Si usted hace “hg add” a un fichero. sin decirle a Mercurial (recuerde que en la terminolog´a de Mercurial esta clase de fichero se llama “faltante”). pero no lo tocar´ a a Si borra un fichero sin decirle a Mercurial. Si le solicita a Mercurial hacer “hg remove” a un fichero. Errores al administrar ficheros ´ La orden “hg revert” es util para m´ s que ficheros modificados. “hg remove”. No se preocupe. ı 1 2 3 4 $ $ ! $ rm file hg status file hg revert file 94 .La orden “hg revert” nos brinda un grado adicional de seguridad guardando nuestro fichero modificado con la extensi´ n . y lo restaua rar´ con sus contenidos sin modificaci´ n. lo restaurar´ a su estado sin modificaci´ n previo. a o Si usa la orden “hg remove” para eliminar un fichero. Le permite reversar los resultados de todas las a ´ ordenes de administraci´ n de ficheros que provee Mercurial—“hg add”. a o Si usted modifica un fichero. o a a 1 2 3 4 5 6 7 $ $ $ A $ $ ? echo oops > oops hg add oops hg status oops oops hg revert oops hg status oops De forma similar.orig. a o 9. puede usar “hg revert” para restarurarlo a los contenidos que ten´a la revisi´ n padre del directorio de trabajo. Mercurial no modificar´ de forma alguna el fichero. use “hg revert” para deshacer la adici´ n. ı o 1 2 3 4 5 6 7 $ hg remove file $ hg status R file $ hg revert file $ hg status $ ls file file Funciona de la misma manera para un fichero que usted haya eliminado manualmente. Describiremos cada uno de ellos con m´ s detalle en la secci´ n siguiente.

no olvide a copiarlas encima. como puede verlo en el siguiente ejemplo. Si necesita que las modificaciones en el fichero destino del renombramiento se muestren. esta orden no se deshace del conjunto de cambios que usted desea deshacer. Antes de leer esta secci´ n. (A prop´ sito. el fichero a donde se copi´ permanece en su directorio de trabajo. recuerde.5 6 $ ls file file Si usted revierte un “hg copy”. y a construir bloques que le permitan revertir parte de un conjunto de cambios a mano. pero sin o seguimiento. si elimina un fichero. u o o 9. sin modificar o borrar.3. Dado que una copia no afecta el fichero fuente de copiado de ninguna maner. hay algo para tener en cuenta: la orden “hg backout” deshace cambios adicionando o al historial.1. Para tratar con esos. Cuando aplica “hg revert” a un cambio de nombre.3. y modifica el fichero con el nuevo nombre. el fichero con el nuevo nombre no se identifica m´ s como agregado. pero por lo menos es ı f´ cil arreglarlo.) Estos aspectos engorrosos al revertir un renombramiento se constituyen discutiblemente en un fallo de Mercurial.4. 1 2 3 4 $ $ $ ? hg copy file new-file hg revert new-file hg status new-file Un caso ligeramente especial:revertir un renombramiento Si hace “hg rename” a un fichero. pero no si est´ tratando de a a deshacer alg´ n cambio que tiene consecuencias catastr´ ficas. no es suficiente proveer el nombre del fichero destino. Tratar cambios consignados Considere un caso en el que ha consignado el cambio a. cuando Mercurial restaure el fichero que fue eliminado como parte del renombramiento. al revertir ambos componentes o del renombramiento. se ha dado cuenta que el cambio a era incorrecto. Es la herramienta correcta si est´ arreglando fallos. Retroceder un conjunto de cambios La orden “hg backout” le permite “deshacer” los efectos de todo un conjunto de cambios de forma automatizada. En cambio. 9. debe proveer ambos nombres. Mercurial le permite “retroceder” un conjunto de cambios completo autom´ ticamente. para revertir un “hg rename”. crea un nuevo conjunto de cambios que reversa el conjunto de cambios que usted indique. vea la secci´ n 9. Mercurial no hace nada con este. no ser´ modificado. hay un detalle que debe tener en cuenta. y otro cambio b sobre este. Dado que el historial de Mercurial es inmutable. la fuente y el destino. 1 2 3 4 $ $ $ ? hg rename file new-file hg revert new-file hg status new-file Como puede ver en la salida de “hg status”. 95 . a pero el fichero con el nombre-inicial se elimna! Esto es contra-intuitivo (por lo menos para m´). a 1 2 3 4 $ hg revert file no changes needed to file $ hg status ? new-file Por lo tanto.

1.3. Normalmente “hg backout” le ofrecer´ un editor de texto para escribir el mensaje de la consignaci´ n.2. 9. $ hg clone -r1 myrepo non-tip-repo requesting all changes adding changesets 96 .3. 1 2 3 4 5 $ hg backout -m ’back out second change’ tip reverting myfile changeset 2:1d9ee76a7513 backs out changeset 1:cab6a78bf14b $ cat myfile first change Puede ver que la segunda l´nea de myfile ya no est´ presente. 1 2 3 4 5 6 7 8 9 10 $ hg log --style compact 2[tip] 1d9ee76a7513 2009-02-10 18:23 +0000 back out second change 1 cab6a78bf14b second change 60b8d10ede6c first change 2009-02-10 18:23 +0000 bos bos 0 2009-02-10 18:23 +0000 bos Vea que el nuevo conjunto de cambios que “hg backout” ha creado es un hijo del conjunto de cambios que retrocedimos. y lo ilustraremos con algunos ejemplos. que presenta una vista gr´ fica del historial de cambios. 1 2 3 4 5 6 7 $ $ $ $ $ $ $ hg init myrepo cd myrepo echo first change >> myfile hg add myfile hg commit -m ’first change’ echo second change >> myfile hg commit -m ’second change’ La orden “hg backout” toma un ID de conjunto de cambios como su argumento. La salida de “hg log” nos da una idea de lo que la ı a orden “hg backout” ha hecho.3. Es m´ s sencillo de ver en la figura 9. o 9. use la opci´ n --merge a la orden “hg backout”.La operaci´ n de la orden “hg backout” es un poco intrincada. Retroceder el conjunto de cambios punta ´ Comenzamos retrocediendo el ultimo conjunto de cambios que consignamos. a a el historial es bonito y lineal. Retroceso de un cambio que no es la punta ´ Si desea retrocede un cambio distinto al ultimo que ha consignado.. el conjunto de cambios a retroceder. o 1 2 3 4 $ cd . En este ejemplo. colocamos un mensaje en la consignaci´ n e a o usando la opci´ n -m. Como puede ver. a o para dejar un registro de por qu´ est´ retrocediendo. Primero o crearemos un repositorio con algunos cambios sencillos.

ver´ que el primer y el tercer cambio e a est´ n presentes. Posteriormente hace un a 97 . una operaci´ n que resulta normalmente o o r´ pida y sencilla.2. a 1 2 3 4 5 6 7 8 9 10 $ echo third change >> myfile $ hg commit -m ’third change’ $ hg backout --merge -m ’back out second change’ 1 reverting myfile created new head changeset 3:688f1a6067e5 backs out changeset 1:cab6a78bf14b merging with changeset 3:688f1a6067e5 merging myfile 0 files updated. 0 files merged. pero no el segundo. 0 files removed. Mercurial realmente consigna dos cambios en estas situaciones a (los nodos encerrados en una caja son aquellos que Mercurial consigna automaticamente). primero recuerda cu´ l es el padre del directorio de trabajo.primer cambio segundo cambio reversar segundo cambio Figura 9. a 1 2 3 $ cat myfile first change third change Como lo muestra el historial gr´ fico en la figura 9. don’t forget to commit) Si ve los contenidos del fichero myfile despu´ s de finalizar el retroceso. 0 files removed. Antes de que Mercurial comience el proceso de retroceso.1: Retroceso de un cambio con la orden “hg backout” 5 6 7 8 9 10 adding manifests adding file changes added 2 changesets with 2 changes to 1 files updating working directory 1 files updated. 1 files merged. 0 files unresolved $ cd non-tip-repo Que resulta en un retroceso de un conjunto de cambios “en un s´ lo tiro”. 0 files unresolved (branch merge.

e. M´ s control sobre el proceso de retroceso a A pesar de que recomiendo usar siempre la opci´ n --merge cuando est´ retrocediendo un cambio. $ hg clone -r1 myrepo newrepo requesting all changes adding changesets adding manifests adding file changes added 2 changesets with 2 changes to 1 files 98 . pero omitamos el a a retroceso que contiene. Es muy extra˜ o que usted necestite o n ´ tomar control del proceso de retroceso de forma manual. solamente con un poco de historial adicional que deshace el efecto de un conjunto de cambios que usted quer´a evitar. o 9. fusiona con el padre anterior del directorio de trabajo. no tratar´ de fusionar si est´ retrocediendo la punta. Para ilustrarlo. y consigna el resultado de la fusi´ n.3. 1 2 3 4 5 6 7 $ cd . la orden “hg o a backout” le permite decidir c´ mo mezclar un retroceso de un conjunto de cambios. Finalmente.retroceso al conjunto de cambios objetivo y lo consigna como un conjunto de cambios. dado que no es necesario). usted deber´a usar siempre a a ı esta opci´ n cuando ejecuta la orden “hg backout”. o primer cambio automatizar fusión segundo cambio tercer cambio reversar segundo cambio fusión Figura 9. pero puede ser util entender lo que la orden “hg backout” est´ haciendo autom´ ticamente para usted. ı Use siempre la opci´ n --merge o De hecho.. clonemos nuestro primer repositorio.2: Retroceso automatizado de un cambio a algo que no es la punta con la orden “hg backout” El resultado es que usted termina “donde estaba”.4. dado que la opci´ n --merge siempre hara lo “correcto” est´ o no retrocediendo el conjunto de cambios o e punta (p.

ı e 1 2 3 4 5 6 7 8 9 10 11 12 13 $ hg log --style compact 3[tip]:1 688f1a6067e5 2009-02-10 18:23 +0000 back out second change 2 72a18afb4ae5 third change cab6a78bf14b second change 60b8d10ede6c first change 2009-02-10 18:23 +0000 bos bos 1 2009-02-10 18:23 +0000 bos 0 2009-02-10 18:23 +0000 bos De nuevo.do not forget to merge (use "backout --merge" if you want to auto-merge) Nuestro nuevo conjunto de cambios es de nuevo un descendiente del conjunto de cambio que retrocedimos. no un descendiente del conjunto de cambios que era la punta. e 1 2 3 4 5 6 7 8 $ echo third change >> myfile $ hg commit -m ’third change’ $ hg backout -m ’back out second change’ 1 reverting myfile created new head changeset 3:688f1a6067e5 backs out changeset 1:cab6a78bf14b the backout changeset is a new head .com> date: Tue Feb 10 18:23:13 2009 +0000 summary: third change Ahora tenemos dos conjuntos de cambios aislados.8 9 10 updating working directory 1 files updated. Esto nos a o a aclara que cuando usamos “hg backout” para retroceder un cambio a algo que no sea la punta. consignaremos un tercer cambio. es m´ s sencillo lo que pas´ viendo una gr´ fica del historial de revisiones. es por lo tanto una nueva cabeza. Mercurial a˜ ade una n nueva cabeza al repositorio (el cambio que consign´ est´ encerrado en una caja). 0 files merged. 1 2 3 4 5 6 $ hg parents changeset: 2:72a18afb4ae5 user: Bryan O’Sullivan <bos@serpentine. en la figura 9. 0 files unresolved $ cd newrepo Como en el ejemplo anterior. o a Despu´ s de que la orden “hg backout” ha terminado.3. La orden “hg backout” fue muy expl´cita dici´ ndolo. 1 2 3 $ hg heads changeset: 3:688f1a6067e5 tag: tip 99 . 0 files removed. y veremos e qu´ pasa. despu´ s haremos retroceso de su padre. deja un nuevo conjunto de cambios de “retroceso” como el e padre del directorio de trabajo.

e a 100 . o Dado que la gr´ fica del historial muestra que el tercer camlio es una cabeza separada. 0 files unresolved (branch merge. El primer cambio deber´a estar preı sente. 0 files removed.3: Retroceso usando la orden “hg backout” 4 5 6 7 8 9 10 11 12 13 parent: user: date: summary: changeset: user: date: summary: 1:cab6a78bf14b Bryan O’Sullivan <bos@serpentine. porque nunca le hicimos retroceso.4. 1 files merged.com> Tue Feb 10 18:23:13 2009 +0000 third change Reflexionemos acerca de lo que esperamos ver como contenidos de myfile. el historial gr´ fica de nuestro repositorio luce como la figura 9. puesto que es el que retrocedimos. no esperamos ver el tercer a cambio presente en myfile.com> Tue Feb 10 18:23:13 2009 +0000 back out second change 2:72a18afb4ae5 Bryan O’Sullivan <bos@serpentine. don’t forget to commit) $ hg commit -m ’merged backout with previous tip’ $ cat myfile first change third change Despu´ s de eso. hacemos una fusi´ n usual de las dos cabezas. El segundo cambio debi´ desaparecer. e o 1 2 3 4 5 6 7 8 $ hg merge merging myfile 0 files updated. 1 2 3 4 $ cat myfile first change second change third change Para que el tercer cambio est´ en el fichero.primer cambio segundo cambio tercer cambio reversar segundo cambio Figura 9.

5. Hace el equivalente de un “hg update” para sincronizar el directorio de trabajo con el conjunto de cambios que usted quiere retroceder. 6. Lo llamaremos backout 4. o o 1. Si especifica --merge en la l´nea de comandos. Lo llamaremos parent.primer cambio segundo cambio tercer cambio reversar segundo cambio fusión manual Figura 9. Encuentra el padre del conjunto de cambios. Recuerda el padre actual del directorio de trabajo.3.5. una fusi´ n y otra consignaci´ n es o o o o o para dar a la maquinaria de fusi´ n la mayor oportunidad de hacer un buen trabajo cuando se trata con todos los cambios o entre el cambio que est´ retrocediendo y la punta actual. que la salida de “hg status” deber´a ser vac´a. Para cada fichero del conjunto de cambios que el retroceso afecte. Se asegura de que el directorio de trabajo es “limpio”. ı ı 2.4: Fusi´ n manual de un retroceso o 9. Por qu´ “hg backout” hace lo que hace e Esta es una descripci´ n corta de c´ mo trabaja la orden “hg backout”. har´ el equivalente a “hg revert -r a parent” sobre ese fichero. A este conjunto de cambio lo llamaremos orig 3. Suena mucho m´ s simple. y se consigna el resultado de la fusi´ n. esto es. 7. para restaurarlo a los contenidos que ten´a antes de que el conjunto de cambios fuera ı consignado. a ı La raz´ n por la cual “hg backout” hace una actualizaci´ n. una consignaci´ n. ı o Una v´a alternativa de implementar la orden “hg backout” ser´a usar “hg export” sobre el conjunto de cambios ı ı a retroceder como un diff y despu´ s usar laa opci´ n --reverse de la orden patch para reversar el efecto del cambio e o sin molestar el directorio de trabajo. Se consigna el resultado como un nuevo conjunto de cambios y tiene a backout como su padre. se fusiona con orig. a 101 . pero no funcionar´a bien ni de cerca.

cierta clase de o a o conjuntos de cambios malos tender´ n naturalmente a“morir” debido a que no pueden propagarse al repositorio central. puede o e intentar deshacerse del conjunto de cambios de todos los repositorios en los que se pueda encontrar. XXX This needs filling out. puede ı prevenir la publicaci´ n autom´ ticamente de cierta clase de cambios malos. el cambio o e a todav´a estar´ “all´ afuera”. o 9. y podr´a propagarse m´ s tarde. vea una discusi´ n de la orden patch en 12. no es una soluci´ n satisfactoria: si usted deja de hacerlo en un solo repositorio. no es necesariamente un desastre. y usted sabe en qu´ repositorios su mal cambio se ha propagado. un gancho de cambios de entrada que verifique que un conjunto de cambios compila.4. but doesn’t handle merge changesets. Mercurial brinda una orden invaluable. por lo tanto aumentan el tama˜ o del o ı n repositorio y la cantidad de tiempo que se emplea al clonar o jalar cambios. Al configurar algunos ganchos en el repositorio central para validar conjuntos de cambios (ver cap´tulo 10). Esto es particularmente sencillo si su equipo de trabajo jala cambios de un repositorio central. la orden “hg backout” es exactamente lo que necesita para deshacer los efectos de ı un cambio. la maquinaria de fusi´ n a o o de Mercurial manejar´ ficheros y directorios renombrados.1. En ocasiones particulares. llamada “hg bisect”. puede haber consignado un cambio que no deber´a estar de ninguna forma en el reposı itorio. a Esto suceder´ sin necesidad de intervenci´ n expl´cita. Cambios que nunca debieron ocurrir En la mayor´a de los casos. cuando se consign´ el conjunto de cambios o original y cuando se hizo la limpieza. a nada de lo cual la orden patch puede manejar. Esta por supuesto. Kind of an important omission. y modificaciones a ficheros binarios. Puede protegerse de antemano de ciertas clases de conjuntos de cambios malos.4. Mercurial no provee una forma de “cabar un hueco” en el historial. puede prevenir que la gente “rompa la compilaci´ n” inadvertidamente. Adicionalmente. Deja un registro permanente y exacto de lo que usted hizo. 9. La unica excepci´ n o es cuando usted ha acabado de consignar un cambio y este no ha sido publicado o jalado en otro repositorio. a o ı Por ejemplo.Si est´ retrocediendo un conjunto de cambios que est´ a unas 100 atr´ s en su historial del proyecto. se requiere que usted sepa o cual conjunto de cambios retroceder. Ah´ es ı cuando puede usar la orden “hg rollback” con seguridad. usted podr´a usar la orden “hg rollback” e ı para hacer que en su copia local desaparezca el cambio.5. e o Despu´ s de que usted haya publicado un cambio en otro repositorio. las posibilia a a dades de que una orden patch sea capaz de ser aplicada a un diff reverso. Antes de discutir las opciones que tiene si consign´ cambio del tipo “bolsa de papel deschable” (el tipo que es o tan malo que le gustar´a colocarse una bolsa de papel desechable en su cabeza). The hg-replay script in the examples directory works. que ayuda a 102 . porque los cambios que intervienen podr´an “no coincidir con el contexto” que patch usa para determinar si puede aplicar un parche (si ı esto suena como ch´ chara. dejando los conjuntos de cambios intactos. cambios de permisos. y reaparecer´ en su repositorio local la pr´ xima vez que jale a a o Si una situaci´ n como esta se presenta.2. 9.1. Los ficheros objeto no tienen valor intr´nseco y son grandes. y considerado como una equivocaci´ n. ı a ı ı a Si ha consignado uno o m´ s cambios despu´ s del cambio que desea desaparecer. Por ejemplo. consignar los ficheros objeto junto con ı o el c´ digo fuente. Al encuentro de la fuente de un fallo Aunque es muy bueno poder retroceder el conjunto de cambios que origin´ un fallo. pero no tendr´ las consecuencias que desea.4). Con tal configuraci´ n. El cambio a estar´ presente en un repositorio remoto. mientras est´ elimin´ ndolo. claramente no son altas. sus opciones son a´ n m´ s reducia e u a das. perm´tame discutir primero unas ı ı aproximaciones que probablemente no funcionen. Dado que Mercurial trata de forma acumulativa al historial—cada cambio se coloca encima de todos los cambios ´ que le preceden—usualmente usted no puede hacer que unos cambios desastrosos desaparezcan. ser´a muy inusual. C´ mo protegerse de cambios que han “escapado” o Si ha consignado cambios a su repositorio local y estos han sido publicados o jalados en cualquier otro sitio. como detall´ en la secci´ n 9.

000 conjuntos de cambios o en su repositorio. En este caso su prueba binaria mide e o n el desempe˜ o de su programa. esta aproximaci´ n exhaustiva tomar´a en promedio 35 d´as para encontrar el conjunto de cambios o ı ı ´ que introdujo el fallo. Puede usarla para encontrar cualquier “propiedad emergente” de un repositorio (Cualquier cosa que usted ´ no pueda encontrar con una b´ squeda de texto sencilla sobre los ficheros en el arbol) para la cual pueda escribir una u prueba binaria. “hg bisect” no era una orden inclu´da en la distribuci´ n principal: se ofrec´a como una extensi´ n de Merı o ı o curial. 9. para ver d´ nde es “r´ pido” y d´ nde es “lento”. Una forma sencilla de automatizar el proceso de b´ squeda ser´a probar cada conjunto de cambios. el buscar entre 10. En este caso. Usted desea a o saber qu´ conjunto de cambios introdujo esta disminuci´ n de desempe˜ o. Finalmente. Con esta aproximaci´ n. pero no o a sabe cu´ ndo fue introducido. ´ Para estos ejemplos deber´a ser claro que la orden “hg bisect” es util no solamente para encontrar la fuente de ı los fallos. De nuevo la prueba binaria revisa la e o presencia del fallo. No tiene que saber qu´ pieza de c´ digo introdujo el cambio. pero usted no recuerda qu´ conjunto de cambios arregl´ tal fallo. Una prueba es algo que usted ejecuta cuando “hg bisect” elige un conjunto de a cambios. o o La versi´ n m´ s reciente de su programa tiene un fallo que usted recuerda no estaba hace unas semanas. y es hora de dar por cerrado el caso en la base de datos de fallos de su o equipo de trabajo. Uso de la orden “hg bisect” A continuaci´ n un ejemplo de “hg bisect” en acci´ n. ´ Su programa funciona correctamente. Al limitar la b´ squeda a la u a u ´ ultima centena de conjuntos de cambios. Esta secci´ n describe la orden embebida y no la extensi´ n anterior. a Usted arregl´ un fallo en un apurto. Un sondeo es lo que “hg bisect” ejecuta para decidir si una revisi´ n es buena. o o Creamos un repostorio para probar el comando “hg bisect” de forma aislada 1 2 $ hg init mybug $ cd mybug 103 . o A continuaci´ n un conjunto de escenarios que puede ayudarle a entender c´ mo puede aplicar esta orden. Lo cual escala u ı muy poco. para aclarar qu´ partes del proceso de b´ squeda son su respono ı e u sabilidad y cu´ les de Mercurial. tomar´ a lo sumo una hora (Apenas unas 7 pruebas). La idea tras la orden “hg bisect” es que el conjunto de cambios que ha introducido un cambio de comportamiento pueda identificarse con una prueba binaria sencilla. Puede evitar ı u ramas enteras de historial con un solo sondeo. incluso a diez minutos por prueba (La b´ squeda requerir´ cerca de 14 pruebas). La base de datos de fallos requiere el ID del conjunto de cambios que permita dar por cerrado el caso. su prueba binaria busca la presencia de tal fallo. usaremos la o palabra “biseccionar’. pero si e o requiere que sepa c´ mo probar la existencia de un fallo.5. A continuaci´ n introduciremos algo terminolog´a. Si le tom´ diez minutos hacer pruebas sobre un conjunto de cambios y tiene 10. as´ que no hay problemas al tratar con ramas. y sospecha que n algo cambio en la forma en que se construye su proyecto. estar´a tomabdi m´ s de 40 horas para encontrar al conjunto de cambios culpable. La orden “hg bisect” usa su prueba para dirigir su b´ squeda o u del conjunto de cambios que introdujo el c´ digo causante del fallo.000 conjuntos de cambios tomar´ menos de u o a 3 horas.automatizar este proceso y a alcanzarlo muy eficientemente. o o Nota: En las versiones 0. pero core 15 % m´ s lento que la ultima vez que lo midi´ .5 y anteriores de Mercurial. en frases como “buscar con la orden “hg bisect””.9. n o a o Los tama˜ os de los componentes del proyecto que usted lleva se expandieron recientemente. a La orden “hg bisect” tiene en cuenta la naturaleza “ramificada” del historial de revisiones del proyecto con Mercurial. Incluso si supiera que el fallo se introdujo en un de los ultimos 500 conjuntos de cambios y limitara la b´ squeda a ellos. u ı a La orden “hg bisect” usa su conocimiento de la “forma” del historial de revisiones de su proyecto para hacer una b´ squeda proporcional al logaritmo del n´ mero de conjunto de cambios a revisar (el tipo de b´ squeda que realiza u u u se llama b´ squeda binaria).1. fusiones o cabezas m´ ltiples en un repositorio.

i < 35. cada uno a˜ ade un unico fichero al ı n repositorio. i++ )). usted se lo indicar´ a “hg bisect” ejecutando la orden “hg bisect good”. To use. de la siguiente forma: 1. mark the working directory as bad or good and bisect will either update to another candidate changeset or announce that it has found the bad revision. Usted ejecuta una prueba binaria. o e o 3. 104 . e indicaremos que ´ un cambio espec´fico sea el “fallo”. ejecutar´ la orden “hg bisect --bad”. Representaremos nuestro “fallo” con un fichero que contiene el texto “tengo un gub”. Este ciclo crea 35 conjuntos de cambios. mark the earliest changeset you know exhibits the problem as bad. then mark the latest changeset which is free from the problem as good. Actualiza el directorio de trabajo a tal conjunto de cambios y el proceso se lleva a cabo de nuevo. a 2. Si la prueba es exitosa. 1 2 3 4 5 6 7 8 9 10 $ buggy_change=22 $ for (( i = 0. Podemos usar el mecanismo de ayuda embebida o o que trae Mercurial. then > echo ’i have a gub’ > myfile$i > hg commit -q -A -m ’buggy changeset’ > else > echo ’nothing to see here. do > if [[ $i = $buggy_change ]].Simularemos de forma sencilla un proyecto con un fallo: haremos cambios triviales en un ciclo. La orden usa su informaci´ n para decidir qu´ conjuntos de cambios deben probarse a continuaci´ n. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $ hg help bisect hg bisect [-gbsr] [REV] subdivision search of changesets This command helps to find changesets which introduce problems. move along’ > myfile$i > hg commit -q -A -m ’normal changeset’ > fi > done A continuaci´ n observaremos c´ mo usar la orden “hg bisect”. Bisect will update your working directory to a revision for testing. a Si falla. Once you have performed tests. options: -r -g -b -s -U --reset --good --bad --skip --noupdate reset bisect state mark changeset good mark changeset bad skip testing changeset do not update to target use "hg -v help bisect" to show global options La orden “hg bisect” trabaja en etapas.

la orden “hg bisect” o “acotar´ ” su b´ squeda entre el primer par de conjuntos de cambios buenos y malos. Si la tiene.0 --init disappeared > hg bisect --init > fi En nuestro caso. 1 $ hg bisect --bad Nuestra pr´ xima tarea es nominar al conjunto de cambios que sabemos no tiene el fallo. a a o o 1 2 3 4 5 6 7 8 9 10 11 $ if grep -q ’i have a gub’ * > then > result=bad > else > result=good > fi $ echo this revision is $result this revision is bad $ hg bisect --$result Testing changeset 16:8fb73e2ea5f9 (12 changesets remaining. 0 files unresolved Esta prueba luce como candidata perfecta para automatizarse. a a Actualiz´ el directorio de trabajo al siguiente conjunto de cambios. si no esta revisi´ n es buena. y cu´ ntas pruebas se requerir´ n. 6 files removed. Ahora ejecutamos nuestra prueba en el directorio de trabajo. y nos dijo qu´ conjunto de cambios est´ evalo e a uando. u 1 2 3 4 5 $ if hg -v | head -1 | grep -e "version 0. Por convenci´ n. mientras que el otro que no la tiene es “bueno”. es indispensable ejecutar la orden “hg bisect --reset”. 0 files merged. la revisi´ n del directorio actual (usualmente la punta) exhibe el problema introducido por ı o el cambio con el fallo. 0 files unresolved Note que esta orden mostr´ algo. Usamos la orden grep para ver si nuestro fichero “malo” est´ presente en el directorio de trabajo. (M´ s adelante dir´ un poco m´ s acerca de la elecci´ n del conjunto de cambios “bueno”. 12 files removed. 105 . 0 files merged.*" > then #On mercurial 1. o Nos dijo cu´ ntos conjuntos de cambios debe considerar antes de que pueda identifica aquel que introdujo el a fallo. o o Para comenzar la b´ squeda. esta revisi´ n es mala. este conjunto de cambios contiene aquel que “caus´ el fallo”. la prueba binaria es sencilla: revisamos si el fichero en el repositorio contiene la cadena “tengo un gub”. Si lo est´ .´ El proceso termina cuando “hg bisect” identifica un unico conjunto de cambios que marca el punto donde se encontr´ la transici´ n de “exitoso” a “fallido”. un conjunto de o o cambios que tiene la propiedad que estamos buscando es “malo”. En nuestro caso.) o ı a e a o 1 2 3 $ hg bisect --good 10 Testing changeset 22:ec1c6526e0eb (24 changesets remaining. sabemos que la a u revisi´ n 10 no ten´a el fallo. ˜4 tests) 0 files updated. por lo tanto la marcaremos como “mala”. ˜3 tests) 0 files updated. En la mayor´a de casos. por lo tanto la convertimos en una funci´ n de interfaz o de comandos.

y hemos terminado. 0 files removed. la orden “hg bisect” nos permiti´ encontrar ı o el conjunto de cambios que introdujo el “fallo” con s´ lo cinco pruebas. 0 files merged. 0 files merged. a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ mytest this revision is good Testing changeset 20:c0c13593daf1 (3 changesets remaining. En todo caso.5. ˜2 tests) 3 files updated. 0 files unresolved Unas invocaciones m´ s de nuestra prueba. ˜1 tests) 1 files updated.com> date: Tue Feb 10 18:23:14 2009 +0000 summary: buggy changeset Aunque ten´amos unos 40 conjuntos de cambios en los cuales buscar. 0 files unresolved $ mytest this revision is good Testing changeset 21:d70e5938b22b (2 changesets remaining.1 2 3 4 5 6 7 8 9 10 $ mytest() { > if grep -q ’i have a gub’ * > then > result=bad > else > result=good > fi > echo this revision is $result > hg bisect --$result > } Ahora podemos ejecutar un paso entero de pruebas con un solo comando. ´ Limpieza despu´ s de la busqueda e Cuando haya terminado de usar la orden “hg bisect” en un repositorio. ˜1 tests) 1 files updated. mytest. 0 files removed. Lar orden no usa mucho espacio.2. 0 files merged. 0 files removed. o u as´ que no hay problema si olvida ejecutar la orden. la ventaja que esto tiene ı frente a la b´ squeda por“fuerza bruta” crece con cada conjunto de cambios que usted adicione. 1 2 3 4 $ mytest this revision is good Testing changeset 19:ffbbdeaade97 (6 changesets remaining. u 9. puede usar la orden “hg bisect reset” para deshacerse de la informaci´ n que se estaba usando para lograr la b´ squeda. Porque el n´ mero de pruebas que la orden “hg o u bisect” ejecuta crece logar´tmicamente con la cantidad de conjuntos de cambios a buscar. “hg bisect” no le permitir´ comenzar una nueva ı a b´ squeda sobre el repositorio hasta que no aplique “hg bisect reset”. 0 files unresolved $ mytest this revision is good The first bad revision is: changeset: 22:ec1c6526e0eb user: Bryan O’Sullivan <bos@serpentine. u 1 $ hg bisect --reset 106 .

6. e la orden “hg bisect” no podr´ ayudarle directamente. Verificar los resultados Dado que la salida de la b´ squeda de “hg bisect” es tan buena como los datos ofrecidos por usted. Su prueba deber´a reportar este(os) conjunto(s) de o ı cambios como bueno(s). Automatizar tanto como se pueda Cuando comenc´ a usar la orden “hg bisect”.3. En cambio. Un hijo del conjunto de cambios. intent´ ejecutar algunas veces las pruebas a mano desde la l´nea e e ı de comandos. Es posible que este fallo “enmascare” completamente al suyo. no conf´e en u ı esto como si fuera la verdad absoluta. si el problema que est´ buscando es m´ s sutil. y que podr´a haberse revelado antes de que su propio ı fallo haya tenido oportunidad de manifestarse. le dir´ que un conjunto de cambios particular es a la vez bueno y malo. Sin su conocimiento. Su prueba deber´a dar un reporte de o o ı fallo. digamos que su u programa se revienta en la revisi´ n 100. Su prueba deber´a reportar al conjunto de cambios hijo como malo. si es una fusi´ n). 9.6. puede marcar este conjunto de cambios como al a ejecutar “hg bisect --skip”. a e La clave para las pruebas automatizadas se puede resumir en: pruebe siempre buscando el mismo s´ntoma y ı ofrezca siempre datos consistentes a la orden “hg bisect”. y que funcion´ correctamente en la revisi´ n 50. obtuve mejores resultados. la orden grep busca el s´ntoma. Si puede ı identificar una inconsistencia en sus reportes.9. 9.6. Es una aproximaci´ n a la cual no esta acostumbrado. Una vez que comenc´ a automatizar mis pruebas. este evita que su proyecto se arme o compile). La funci´ n mytest los une o de una forma reproducible. 9. Una forma sencilla de asegurarse es ejecutar manualmente su prueba a cada uno de los siguientes conjuntos de cambios: El conjunto de cambios que se report´ como la primera versi´ n erronea. y la construcci´ n if toma el resultado de esta ı o prueba y verifica que siempre alimentamos con los mismos datos a la orden “hg bisect”. Despu´ s de algunos intentos. y de esta forma no se pueda revisar si su fallo est´ presente en un conjunto particular de cambios. Por ejemplo. 107 . me di cuenta que o e estaba cometiendo tantas equivocaciones que ten´a que comenzar de nuevo con mis b´ squedas varias veces antes de ı u llegar a los resultados deseados. o el n´ mero de pruebas que “hg bisect” debe aplicar. Sus resultados estar´an o o o ı distorcionados de una o muchas formas.2. El conjunto de cambios padre (cada padre. ı 9. Consejos para encontrar fallos efectivamente Dar una entrada consistente La orden “hg bisect” requiere que usted ofrezca un reporte correcto del resultado de cada prueba que aplique. logrando que cada prueba sea uniforme y consistente. podr´a detectar la inconsistencia.4. Tener en cuenta la interferencia entre fallos Es posible que su b´ squeda de un fallo pueda viciarse por la presencia de otro. alguien o o o introdujo un fallo con consecuencias grandes en la revisi´ n 60. Si no puede saltar el otro fallo (por ejemplo. n a a u la posibilidad de errar es mucho m´ s alta. a Aunque puede no hacerlo.1. Mi problema inicial al dirigir a la orden “hg bisect” manualmente ocurrieron incluso con b´ squedas en repositou rios peque˜ os. y lo arregl´ en la revisi´ n 80. estar´a tratando de reportar un conjunto de cambios como el responsable de un fallo aunque ı no lo sea. Si usted le dice que una prueba falla cuando en realidad era acertada.6. En mi tutorial de ejemplo anterior.6.

solamente esta´a adicioa r nando unas pruebas contadas para “hg bisect”. el conjunto de cambios “m´ s nuevo” a por convenci´ n es el “malo”. para informar a “hg bisect”. Desde la perspectiva de “hg bisect”. ´ Acotar la busqueda perezosamente Elegir los primeros “buenos” y “malos” conjuntos de cambios que marcar´ n los l´mites de su b´ squeda en general a ı u es sencillo. o Incluso si termina “muy atr´ s” por miles de conjuntos de cambios o meses de historial. ı 108 . gracias al comportamiento logar´tmico. podr´a terminar confundiendo a “hg bisect”. Pero recuerde eliminar aquellos conjuntos de cambios que podr´an no exhibir el fallo (tal vez ı porque la caracter´stica donde se presenta el fallo todav´a no est´ presente) y aquellos en los cuales otro fallo puede ı ı a enmascararlo (como se discuti´ anteriormente). tal vez porque alguien consign´ un cambio que hac´a imposible la o o ı construcci´ n del proyecto. Si ı ı usted busca “mi programa se revienta”. podr´a hacer pruebas aleatorias a ı ı en el peor de los casos. o Si no recuerda cu´ l podr´a ser el cambio “bueno”.Un problema distinto podr´a surgir si su prueba de la presencia de un fallo no es suficientemente espec´fica. ı ı Otra situaci´ n en la cual ser´a de mucha utilidad emplear a “hg bisect --skip” surge cuando usted no puede o ı probar una revisi´ n porque su proyecto estaba en una situaci´ n de rompimiento y por lo tanto en un estado en el o o cual era imposible hacer la prueba en esa revisi´ n. o 9. pero vale la pena discutirlo. y el otro conjunto de cambios es el “bueno”.5. entonces tanto su fallo como el otro fallo sin relaci´ n que terminan presentando o s´ntomas distintos.6.

Es ejecutado antes de iniciar la transmisi´ n de un grupo de conjuntos de cambios desde el repositorio. prechangegroup Es ejecutado antes de iniciar la recepci´ n de un grupo de conjuntos de cambios en el repositorio. o que la transacci´ n que hace permanente el cambio sea completada. Vistazo general de ganchos en Mercurial A continuaci´ n se encuentra una breve lista de los ganchos que Mercurial soporta. Note la diferencia ı o respecto al gancho changegroup. Mercurial usa el t´ rmino gancho para identificar estas acciones. Volveremos a cada uno de estos o ganchos con m´ s detalle despu´ s. e pero antes de que la transacci´ n se complete y los cambios sean permanentes dentro del repositorio. ı u commit Es ejecutado despu´ s de la creaci´ n de un conjunto de cambios en el repositorio local. usted puede controlar incluso la respuesta de Mercurial a dichos eventos. o pretag De control. En algunos casos. que es ejecutado una vez por cada grupo de conjuntos de cambios que se traiga. e o 109 . o preoutgoing De control. a e o changegroup Es ejecutado luego de que un grupo de conjuntos de cambios ha sido tra´do al repositorio desde alg´ n otro sitio. Es ejecutado luego de la creaci´ n de un conjunto de cambios en el repositorio local. en la secci´ n 10. pero los dos nombres se refieren al mismo concepto. Es ejecutado antes de crear una etiqueta.1. pretxnchangegroup De control. e o incoming Es ejecutado una vez por cada conjunto de cambios tra´do al repositorio desde otra ubicaci´ n. Es ejecutado despu´ s de haber recibido un grupo de conjuntos de cambios en el repositorio local. o o tag Es ejecutado despu´ s de la creaci´ n de una etiqueta. Los ganchos son conocidos como “disparadores” e en algunos sistemas de control de revisiones. o precommit De control. pero antes de o preupdate De control. o pretxncommit De control. 10. Es ejecutado antes de iniciar una actualizaci´ n o fusi´ n en el directorio de trabajo.8. Es ejecutado antes de iniciar una consignaci´ n. outgoing Es ejecutado luego de que un grupo de conjuntos de cambios ha sido transmitido desde el repositorio.Cap´tulo 10 ı Manejo de eventos en repositorios mediante ganchos Mercurial ofrece un poderoso mecanismo para permitirle a usted automatizar la ejecuci´ n de acciones en respuesta o a eventos que ocurran en un repositorio.

Ganchos y seguridad Los ganchos se ejecutan con sus privilegios de usuario Cuando usted ejecuta un comando de Mercurial en un repositorio. Nota: Esto s´ lo aplica si usted est´ jalando desde un repositorio en un sistema o a de ficheros local o de red. en su m´ quina. y usar un fichero hgrc global para definir los o a ganchos que ver´ n todos los usuarios. esto es algo m´ s f´ cil de manejar. Si est´ jalando a trav´ s de http o ssh. o jala de. usted puede estar expuesto a ganchos que usted no instal´ .2.2. Usted deber´a documentar los ganchos que usted espera que la gente use. no los del suyo. tenga en cuenta que Mercurial ejecutar´ los ganchos definidos en el fichero hgrc. ya que usted puede. Mercurial podr´ ejecutar los ganchos definidos a a en el repositorio de dicho usuario. Es posible hacer caso omiso de los ganchos Mercurial le permite hacer caso omiso de la deficini´ n de un gancho. por ejemplo. no se hace control de revisiones de los ganchos. si usted est´ colaborando con otras personas en un proyecto com´ n. ya que esto ofrecer´a maneras f´ cilmente aprovechables de subvertir las cuentas ı a de los usuarios del sistema de control de revisiones. ı En una intranet corporativa.2. Usted o e o puede deshabilitar el gancho fijando su valor como una cadena vac´a.1.2. XXX Para ver qu´ ganchos han sido definidos en un repositorio. a trav´ s de la redefinici´ n del mismo. 10. Los ganchos no se propagan En Mercurial. debe entender que sus usuarios pueden deshabilitar o hacer caso omiso de los mismos. recuerde que los ganchos que debe considerar son los del otro repositorio. Sin embargo. a Ser´a extremadamente descuidado de parte de cualquier sistema distribuido de control de revisiones el implementar ı control de revisiones para ganchos. pero los ejecutar´ como “usted”. o bien la actividad no es permitida. un repositorio. y el . aun cuando usted no es el propietario del repositorio. la actividad puede continuar. 10. en su cuenta de usuario. ı o En algunos casos. o dicho gancho se ejecuta en su sistema. proveer una a a instalaci´ n “est´ ndar” de Mercurial en un sistema de ficheros NFS. usando “hg pull” a a o “hg incoming”). Por ejemplo.hg/hgrc define un gancho saliente (outgoing).update Es ejecutado despu´ s de que termina una actualizaci´ n o una fusi´ n. ı Si usted instala un fichero hgrc a nivel de sistema o sitio completo que define algunos ganchos. y no se propagan cuando usted clona. Si el gancho se ejecuta con exito. use el comando “hg config hooks”. e o o Cada uno de los ganchos cuya descripci´ n empieza con la frase “de control” tiene la facultad de determinar si una o ´ actividad puede continuar. este enfoque tiene sus l´mites. 110 . El motivo para esto es simple: un gancho es c´ digo ejecutable arbitrario. vea m´ s abajo. o que los de ellos est´ n ı a a configurado correctamente. Si usted usa Mercurial en un sistema o extra˜ o. o se deshacen los cambios que se puedan haber llevado a cabo. cualquier gana e cho saliente (outgoing) se ejecutar´ bajo la cuenta que est´ ejecutando el proceso a a servidor.2. usted deber´a tratarlos con un nivel adecuado de desconfianza.3. 10. n a Si est´ trabajando con un repositorio propiedad de otro usuario. pero comunic´ ndose con otro que no le pertenece (por ejemplo. No instale un gancho o ı a menos en que conf´e en quien lo cre´ y en lo que el gancho hace. si falla. dependiendo del gancho involucrado. Ya que Mercurial no propaga los ganchos. a u no deber´a asumir que ellos est´ n usando los mismos ganchos para Mercurial que usted usa. si usted jala (“hg pull”) desde ese a repositorio. con o su nivel de privilegios. Si usted e est´ trabajando en un repositorio. con sus privilegios. en el servidor. y el comando causa la ejecuci´ n de un gancho. Ya que los ganchos son elementos arbitrarios de c´ digo ejecutable. o cambiar su comportamiento como desee. dicho gancho se ejecuta bajo su cuenta de usuario. a ı a 10. Se ejecuta bajo su identidad.

usted puede definir las pol´ticas para usar Mercurial de tal forma que se espere que los usuarı ios propaguen los cambios a trav´ s de un servidor “can´ nico” bien conocido que usted ha asegurado y configurado e o apropiadamente. debe tener cuidado con la forma de hacerlo. luego los datos del manifiesto (que contienen punteros a los nuevos datos del fichero). el servidor probar´ el conjunto de a cambios antes de aceptarlo como permanente. Si la transacci´ n o o debe ser deshecha. Asegurarse de que ganchos cr´ticos sean ejecutados ı Algunas veces usted puede querer hacer respetar una pol´tica.2. ı a Por ejemplo. Como un lector s´ lo a a o ´ acceder´ a las partes del manifiesto o de los metadatos de fichero que el puede ver en la bit´ cora de cambios. Precauciones con ganchos pretxn en un repositorio de acceso compartido Si usted desea usar ganchos para llevar a cabo autom´ ticamente alg´ n trabajo en un repositorio al que varias a u personas tienen acceso compartido. usted puede tener como requerimiento que cada conjunto de cambios debe pasar un riguroso conjunto de pruebas. servir´ para asegurarse de que todos los cambios que la gente jala han sido a examinados autom´ ticamente a 10. abre una ventana de tiempo en la que un o lector puede ver los metadatos de conjuntos de cambios que a´ n no son permanentes y que no deber´a considerarse u ı que est´ n “realmante ah´”. corrompiendo el repositorio. se guarda un registro de d´ nde estaba el final de fichero en su registro de transacciones. o Cuando Mercurial lee metadatos. Describirlo requiere algo de detalle respecto a c´ mo e o Mercurial a˜ ade conjuntos de cambios al repositorio y c´ mo lee esos cambios de vuelta. y por supuesto que los usuarios locales pueden evitar esto a voluntad haciendo caso omiso a del gancho. ı Cuando alguien empuja un conjunto de cambios al servidor del que todos jalan. Una manera de hacer esto es a trav´ s de una combinaci´ n de ingenier´a social y tecnolog´a. En vez de eso. nunca a a puede ver datos parcialmente escritos. Si la gente s´ lo a o jala cambios desde este servidor de filtro.3. Este esquema de lectura libre de bloqueos incremententa en gran medida el desempe˜ o y la concurrencia. uno de los cuales tiene el potencial de n ´ causarle problemas a menos de que usted est´ consciente de el. Cree una cuenta de e o ı ı acceso restringido. no necesita adquirir un bloqueo cuando desea leer datos del repositorio. Primero escribe los datos del fichero. lee la bit´ cora de cambios primero. Mercurial simplemente trunca cada fichero de vuelta al tama˜ o que ten´a antes de que empezara la n ı transacci´ n. los escribe directamente en el fichero de destino. En este escenario. e Si alguno de estos ganchos permanece en ejecuci´ n por mucho tiempo. y lo rechazar´ si no logra pasar el conjunto de pruebas.10. e ı a o a a 111 .4. a e ´ un usuario puede enviar un conjunto de cambios que contenga la porquer´a que el desee. pero Mercurial a´ n puede deshacer la transacci´ n y hacer que los u o datos reci´ n escritos desaparezcan. y no permitir que los dem´ s sean capaces de evitarla. Antes de la primera escritura a cada a fichero. y s´ lo las partes de Mercurial que escriben o a o al repositorio le prestan atenci´ n a los bloqueos. y luego todo lo dem´ s. n Sin embargo. para tener un gran desempe˜ o es necesario hacer sacrificios. Todos los metadatos han sido escritos. Algunos ganchos de control (pretxncommit y pretxnchangegroup) se ejecutan cuando una transacci´ n est´ casi o a completa. luego datos de la bit´ cora de cambios (que contienen punteros a los nuevos datos del manifiesto). n o Cuando Mercurial escribe metadatos. a ı Ya que Mercurial tiene cuidado con el orden en que lee y escribe datos. Definir este requerimientos a trav´ s de un gancho en un fichero hgrc global no servir´ con usuarios remotos e a en computadoras port´ tiles. Las partes de Mercurial que leen del repositorio nunca le prestan atenci´ n a los o bloqueos. Entre m´ s tiempo tome la ejecuci´ n del gancho. los usuarios pueden empujar cambios a trav´ s de la red a los repositorios administrados por esta e ´ cuenta. m´ s tiempo estar´ abierta esta ventana. pero no podr´ n ingresar a dicha cuenta para ejecutar ordenes en el int´ rprete de comandos. Los bloqueos de escritura son necesarios para evitar que m´ ltiples o u escritores simult´ neos interfieran entre s´. Mercurial s´ lo bloquea un repositorio cuando est´ escribiendo al mismo.

´ En la pr´ ctica. alguien confiado puede jalar cambios sin probar. Usted extiende n o 112 . Empecemos con un gancho que se ejecute cuando usted termine un a “hg commit”. o e Una aproximaci´ n que permite manejar mejor el crecimiento es hacer que la gente ensamble y pruebe antes de o empujar. A la izquierda est´ el nombre del evento respecto al cual dispararse.1. e a a ´ Permita que reciba cambios desde el exterior. y simplemente muestre el hash del conjunto de cambios que usted acaba de crear. y la visibilidad a de las transacciones no tiene nada que ver con el problema.4.1: Un gancho simple que se ejecuta al hacer la consignaci´ n de un conjunto de cambios o Todos los ganchos siguen el patr´ n del ejemplo 10. un buen uso del gancho pretxnchangegroup ser´a ensamblar y probar autom´ ticamente todos los ı a cambios entrantes antes de que sean aceptados en un repositorio central. y ejecutar el ensamble y pruebas autom´ ticas centralmente despu´ s de empujar. Esto le permitir´a a usted garantizar que nadie ı pueda empujar cambios que “rompan el ensamblaje”. la utilidad de esta prueba es nula. el gancho empuje los nuevos cambios a otro repositorio del que la gente pueda jalar.10. Mercurial le permite hacer esto a˜ adiendo una extensi´ n al final del nombre de un gancho.1. a la derecha est´ la acci´ n a llevar a a o a cabo. montar un cuello de botella centralizado como este a menudo no es una buena idea. El resultado inevitable a es frustraci´ n para todos los que est´ n involucrados. El gancho se llamar´ commit.hg/hgrc $ echo ’commit = echo committed $HG_NODE’ >> .1. Tutorial corto de uso de ganchos Escribir un gancho para Mercurial es f´ cil. en el que tiene m´ s conjuntos de cambios a probar que tiempo para ocuparse de ellos. usted se acerca r´ pidamente a un l´mite con este enfoque “pruebe antes de a ı comprar”. para asegurarse de que todo a e est´ bien. Como puede ver. Configure un gancho changegroup para que si el ensamblaje o prueba tiene exito.hg/hgrc $ cat . es posible ejecutar cualquier orden de la l´nea de comandos en un gancho. A medida que el tama˜ o de un proyecto—y el tiempo n que toma ensamblarlo y probarlo—crece. Mercurial le pasa ı informaci´ n extra al gancho usando variables de entorno (busque HG NODE en el ejemplo). Usted puede a˜ adir una entrada a la secci´ n [hooks] de su o n o fichero hgrc. 10. como se muestra en el ejema a plo 10.3. Llevar a cabo varias acciones por evento A menudo. pero no permita que nadie jale cambios de el (use el gancho preoutgoing ´ para bloquear esto). La ventaja de este enfoque es que no impone un l´mite a la rata en la que un repositorio puede aceptar e ı cambios. Ilustraci´ n del problema o En principio. usted querr´ definir m´ s de un gancho para un tipo de evento particular.4. a 1 2 3 4 5 6 7 8 9 10 11 $ hg init hook-test $ cd hook-test $ echo ’[hooks]’ >> . lo que potencialmente podr´a romper su proceso de ensamblaje.hg/hgrc [hooks] commit = echo committed $HG_NODE $ echo a > a $ hg add a $ hg commit -m ’testing commit hook’ committed 233120f5d09c76e782c6ea86ccee729e735bf48f Figura 10. o 10.2. ı La respuesta t´ cnica m´ s segura frente a este retos es montar dicho repositorio “guardi´ n” como unidireccional. Pero si un cliente puede jalar cambios mientras est´ n siendo a probados.

Usted puede ejecutar comandos Mercurial normales para obtener la informci´ n o 113 . la transacci´ n es revertida. Si el gancho falla. Mercurial define un n´ mero de eventos que ocurren antes de que una actividad empiece.2: Definici´ n de un segundo gancho commit o Para dar un orden bien definido de ejecuci´ n cuando hay m´ ltiples ganchos definidos para un evento. o si su ejecuci´ n es abortada. Escoger c´ mo debe ejecutarse su gancho o Usted puede escribir un gancho que funcione como un programa normal —t´picamente un gui´ n de l´nea de ı o ı comandos—o como una funci´ n de Python que se ejecuta dentro del proceso Mercurial.bar cuando a o a ocurra el evento commit. y el gancho commit es ejecutado. Esto le ayudar´ a recordar para o a qu´ se usa el gancho. 10. Si el gancho pretxncommit termina con un c´ digo de salida o o diferente de cero.5. Mercurial imprimir´ un mensaje antes o a de llamar cada gancho. o Escribir un gancho como un programa externo tiene la ventaja de que no requiere ning´ n conocimiento del funu cionamiento interno de Mercurial. Si lo contiene. o con el a o valor de configuraci´ n verbose fijado en “true” (verdadero). se permite que la transacci´ n se complete. En el ejemplo de arribam commit.el nombre del gancho poniendo el nombre del gancho. seguido por una parada completa (el caracter “.2. Mercurial o u ordena los ganchos de acuerdo a su extensi´ n. Si no. o luego de que empiece. pero no se ha terminado la transacci´ n. seguido de algo m´ s de texto de su elecci´ n.3 revisa si el mensaje de consignaci´ n contiene el ID de alg´ n fallo. la o u consignaci´ n puede continuar. o Si el gancho pretxncommit termina con un c´ digo de salida de cero. 1 2 3 4 5 $ echo ’commit. Cuando lo haga. usamos el gancho commit.2).1. El gancho o pretxncommit tiene la capacidad de decidir si una transacci´ n se completa. El gancho en el ejemplo 10. los metadatos representando el conjunto de cambios son borrados. date’ >> . a a Es una buena idea usar una extensi´ n descriptiva cuando usted define un gancho.when = echo -n "date of commit: ".”). o o 10.4.foo. y el o gancho commit no es ejecutado. o El gancho pretxncommit se ejecuta justo antes de que una consignaci´ n se ejecute. y los ejecuta en dicho orden.bar se o ejecutar´ antes que commit. Este es uno de los varios ganchos que Mercurial ejecuta luego de que una actividad termina. Controlar cu´ ndo puede llevarse a cabo una actividad a En los ejemplos anteriores.4.foo como commit. y commit se ejecutar´ antes de ambos. Escribir sus propios ganchos ´ Cuando usted escriba un gancho. Tales o ganchos no tienen forma de influenciar la actividad como tal.hg/hgrc $ echo a >> a $ hg commit -m ’i have two hooks’ committed df4f3f8972104d2a43d114e51edd05719efccd42 date of commit: Tue Feb 10 18:23:23 GMT 2009 Figura 10. En otras palabras. la o o consignaci´ n termina. Los ganchos que se disparan con estos eventos tienen la capacidad adicional de elegir si la actividad puede continuar. u pero antes de que termine.5. los metadatos o que representan el conjunto de cambios han sido escritos al disco. que es ejecutado despu´ s de que se ha completado una e consignaci´ n. Por ejemplo. puede encontrar util el ejecutar Mercurial o bien pas´ ndole la opci´ n -v. Mercurial ejecutar´ tanto commit. usted recibir´ un mensaje de error que contiene el nombre y la extensi´ n del e a o gancho. o 10. as´ que usar una extensi´ n descriptiva le dar´ una pista inmediata de porqu´ el gancho fall´ (vea un ejemplo ı o a e o en la secci´ n 10. o debe deshacerse. la consignaci´ n es cancelada.

o retornar o el valor booleano “falso”. que hace la interpretaci´ n correspondiente. un par´ metro se pasa r a como argumento de palabra clave a su funci´ n de gancho. Si un par´ metro se llama foo. Un par´ metro booleano ser´ representado como un valor a ı a a a booleano en Python.5. pero como el n´ mero 1 (para “verdadero”) o 0 (para falso) en una variable de entorno para un u gancho externo. Esto significa que usted puede usar elementos e o 114 .2.bug_id_required hook exited with status 1 $ hg commit -m ’i refer you to bug 666’ committed d558e8617cbdf0b482db27a79d17f9a28af4701f date of commit: Tue Feb 10 18:23:23 GMT 2009 Figura 10. dicha definici´ n pasa a su o int´ rprete de comandos.3. La contraparte de esto es que los ganchos externos son m´ s lentos que los ganchos internos a ejecutados dentro del proceso.3: Uso del gancho pretxncommit para controlar consignaciones extra que pueda necesitar. Para los ganchos que controlan si una actividad puede continuar o no. y no se “externaliza” a otro proceso.4. escribir sus ganchos en Python puede ser una buena n elecci´ n. Si un gancho interno genera una excepci´ n. cuando usted tiene un gancho bastante directo por escribir y no le importa el desempe˜ o (el o n caso de la mayor´a de los ganchos). o 10. es perfectamente admisible un gui´ n de l´nea de comandos. o requiere un alto desempe˜ o. los par´ metros son pasados o a como variables de entornos. Adicionalmente es m´ s f´ cil obtener la mayor´a de ı a a a a ı la informaci´ n que un gancho requiere a trav´ s de llamadas directas a la API de Mercurial que hacerlo ejecutando o e comandos Mercurial. Sin embargo. En Python./check_bug_id $HG_NODE’ >> . Un fallo se indica con un c´ digo de salida diferente de cero desde un gancho o externo.5. los nombres y valores de a o ı los par´ metros espec´ficos de los ganchos ser´ n los mismos. se considera que el o gancho ha fallado.bug_id_required = . ı o ı 10. Un gancho Python interno tiene acceso completo a la API de Mercurial. el argumento de palabra clave para un gancho en Python tambi´ n se a e llamar´ foo. Escribir un gancho externo Cuando usted define un gancho externo en su fichero hgrc y el mismo es ejecutado. mientras que no-cero/verdadero/excepci´ n quiere decir “no permitir”.5. Valores de retorno de ganchos y control de actividades Un gancho que se ejecuta exitosamente debe terminar con un c´ digo de salida de cero.1 2 3 4 5 6 7 8 9 10 11 12 13 $ cat check_bug_id #!/bin/sh # check that a commit comment mentions a numeric bug id hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]" $ echo ’pretxncommit. as´ que es inherentemente m´ s r´ pido que un gancho externo. a a 10. si es externo. Si se siente a gusto con Python. Par´ metros para ganchos a Mercurial llama cada gancho con un conjunto de pa´ametros bien definidos. mientras que la variable de entorno para un gancho externo se llamar´ HG FOO. cero/falso quiere decir “permitir”. Sin importar si su gancho est´ escrito en Python o como gui´ n de l´nea de comandos. si es interno. o un valor de retorno booleano “verdadero”.hg/hgrc $ echo a >> a $ hg commit -m ’i am not mentioning a bug id’ transaction abort! rollback completed abort: pretxncommit. Para un programa externo.

Interfaz para Programaci´ n de Aplicaciones o 115 . busca el objeto invocable llamado myhook. **kwargs): pass El primer argumento para un gancho Python siempre es un objeto mercurial.submodule.example = python:mymodule. 10.5. y tiene a a u como prefijo la cadena “HG ”. el nombre est´ en may´ sculas. repo. El simple gancho pretxncommit ı o ´ de la figura 10.6. 1 2 [hooks] commit. Con la excepci´ n de los par´ metros para los ganchos. a El m´ dulo en que vive un gancho es importado autom´ ticamente cuando se ejecuta un gancho. pero ilustra la estructura b´ sica de la API1 para ganchos: a a 1 2 def myhook(ui.normales del int´ rprete en el cuerpo del gancho. Ejemplos de ganchos Escribir mensajes de consignaci´ n significativos o Es dif´cil de imaginar un mensaje de consignaci´ n util y al mismo tiempo muy corto.ui. 10. El siguiente fragmento de ejemplo de un fichero hgrc ilustra la sintaxis y significado de los conceptos que acabamos de describir. 10.ui. Despu´ s de estos dos e argumentos est´ n los argumentos de palabra clave.5. y continuar con el nombre completamente cualificado de un objeto invocable que se usar´ como el valor del gancho. pero un gancho siempre puede ignorar los argumentos que no le interesen.myhook Cuando Mercurial ejecuta el gancho commit.localrepository. de momento. a 1 N. importa mymodule. Mercurial no define o modifica ninguna variable de entorno o a ´ al ejecutar un gancho.6.submodule.1. releg´ ndolos a un diccionario e a de argumentos por palabras clave. 10.localrepo. El valor del gancho debe comenzar con el texto “python:”. como se hizo arriba con **kwargs. del T. El segundo es un objeto repositorio.5. todo deber´a funcionar sin o ı problemas.4 evitar´ que usted consigne un conjunto de cambios con un mensaje de menos de 10 bytes de longitud. Indicar a Mercurial que use un gancho interno La sintaxis para definir un gancho interno en el fichero hgrc es ligeramente diferente de la usada para un gancho externo.6. Es util recordar esto al escribir un gancho global que podr´a ser ejecutado por varios usuarios ı con distintas variables de entorno fijadas. e Un gancho ejecutable siempre es ejecutado con su directorio actual fijado al directorio ra´z del repositorio. y lo invoca (llama). siempre es una instancia de mercurial.example. Escribir un gancho interno El gancho interno m´ s sencillo no hace nada. ni que sus valores sean los mismos que ten´an cuando usted prob´ el gancho en su ı o ambiente de trabajo. En situaciones con m´ ltiples usuarios. ı Cada par´ metro para el gancho es pasado como una variable de entorno. Siempre que usted o a tenga el nombre del m´ dulo y la variable de entorno PYTHONPATH ajustada adecuadamente. Application Progamming Interface. Los argumentos que se pasen depender´ n del tipo de gancho que se a a est´ llamando. usted no deber´a asumir la existencia u ı de ninguna variable de entorno.

Si usted a s´ lo quiere consignar un cambio al fichero foo. el espacio en blanco final es innecesario. si usted ingres´ el mensaje de consignaci´ n de manera interactiva y el gancho falla.4: Un gancho que proh´be mensajes de consignaci´ n demasiado cortos ı o 10.hg/hgrc [hooks] pretxncommit. y la gente en general prefiere deshacerse de el.*[ \t]$’) $ echo ’a ’ > a $ hg commit -A -m ’test with trailing whitespace’ adding a transaction abort! rollback completed abort: pretxncommit. Si usa el gancho precommit. ruido ı ı ´ invisible. 1 2 3 4 5 6 7 8 9 10 11 $ cat . Este no parece el a o enfoque adeucado.whitespace = hg export tip | (! egrep -q ’ˆ\+. la revisi´ n no ocurrir´a sino hasta justo antes de que la transacci´ n o ı o para la consignaci´ n se complete. Esto le permitir´ comprobar por posibles problemas s´ lo en los ficheros que ser´ n o a o a consignados. El espacio en blanco final es una serie de caracteres de espacio y tabulaci´ n que se o encuentran al final de una l´nea de texto. a Usted puede usar cualquiera de los ganchos precommit o pretxncommit para revisar si tiene el problema de los espacios en blanco finales.2. usted tendr´ que reingresar el mensaje de consignaci´ n luego de que corrija el problema o a a o con los espacios en blanco finales y ejecute “hg commit” de nuevo.6. Comprobar espacios en blanco finales Un uso interesante para ganchos relacionados con consignaciones es ayudarle a escribir c´ digo m´ s limpio.5: Un gancho simple que revisa si hay espacios en blanco finales La figura 10.hg/hgrc [hooks] pretxncommit.whitespace hook exited with status 1 $ echo ’a’ > a $ hg commit -A -m ’drop trailing whitespace and try again’ Figura 10. Un o a ejemplo simple de “c´ digo m´ s limpio” es la regla de que un cambio no debe a˜ adir l´neas de texto que contengan o a n ı “espacios en blanco finales”. pero no muestra ninguna informaci´ n que pueda ser n ı o 116 .1 2 3 4 5 6 7 8 9 10 $ cat . pero no brinda mucha ayuda. Termina con un c´ digo de salida de error si un cambio o a˜ ade una l´nea con espacio en blanco final a cualquier fichero. Si usted escogiera el gancho pretxncommit. la o o transacci´ n ser´ deshecha. pero ocasionalmente es problem´ tico.msglen = test ‘hg tip --template {desc} | wc -c‘ -ge 10 $ echo a > a $ hg add a $ hg commit -A -m ’too short’ transaction abort! rollback completed abort: pretxncommit. Sin embargo. por lo a e a que se tendr´ que revisar cada fichero modificado en el repositorio para ver si tiene espacios en blanco finales. y el fichero bar contiene espacios en blanco finales. el gancho no sabr´ qu´ ficheros se est´ n consignando. hacer la revisi´ n o o en el gancho precommit evitar´ que usted haga la consignaci´ n de foo debido al problem en bar. En la mayor´a de los casos.5 presenta un gancho pretxncommit simple que comprueba la existencia de espacios en blanco finales. Este gancho es corto.msglen hook exited with status 1 $ hg commit -A -m ’long enough’ Figura 10.

save transaction abort! rollback completed abort: pretxncommit. Usted puede encontrarlos en el directorio hgext del arbol de ficheros fuente de Mercurial.1. y si usted desea segurarse de que s´ lo se le permita a ciertos usuarios empujar cambios a dicho servidor. no en la identidad de quien hizo la consignaci´ n de los mismos.´ util para identificar el fichero o la l´nea de texto origen del problema. o 117 . line 2: trailing whitespace added commit message saved to . Usted puede proteger cualquier porci´ n de un repositorio (incluyendo el repositorio completo). s´ lo las l´neas que introducen nuevos espacios en blanco o ı o ı finales causan problemas. line 2: trailing whitespace added commit message saved to . Usar este gancho tiene sentido s´ lo si se o o tiene un servidor adecuadamente asegurado que autentique a los usuarios remotos. 10. El gancho procesa un diff unificado a e a ´ para revisar si alguna l´nea a˜ ade espacios en blanco finales.hg/commit. Si usted est´ usando un paquete binario de Mercurial.py $ echo ’a ’ >> a $ hg commit -A -m ’add new line with trailing whitespace’ a. *$.hg/commit. o Como anotaci´ n final. de o tal manera que un usuario remoto espec´fico pueda empujar cambios que no afecten la porci´ n protegida.6 el uso de la caracter´stica de edici´ n in-situ de perl para eliminar los o ı o espacios en blanco finales en un fichero. pero tambi´ n m´ s util.’ nombre fichero 10.7. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ cat . note en la figura 10. ı 1 perl -pi -e ’s. una vez usted haya corregido el problema.hg/hgrc [hooks] pretxncommit.hg/check_whitespace.save transaction abort! rollback completed abort: pretxncommit. A´ n mejor. antes de terminar e indicarle a o Mercurial que deshaga la transacci´ n.whitespace hook exited with status 1 Figura 10. acl—control de acceso a partes de un repositorio La extensi´ n acl le permite controlar a qu´ usuarios remotos les est´ permitido empujar conjuntos de cambios a o e a un servidor en red. Tambi´ n tiene la agradable propiedad de no ı e prestar atenci´ n a las l´neas que no sufrieron modificaciones. este gancho guarda el mensaje de u n consignaci´ n e imprime el nombre del fichero en el que el mensaje fue guardado. e imprime el nombre del fichero y el n´ mero de l´nea ı n u ı de cada ocurrencia. ı o Esta extensi´ n implementa control de acceso basado en la identidad del usuario que empuja los conjuntos de o cambios..\s+$. los ganchos estar´ n ubicados en el a a directorio hgext en donde su instalador de paquetes haya puesto a Mercurial. si el cambio a˜ ade espacios en blanco finales.’ a $ hg commit -A -m ’trimmed trailing whitespace’ a. para que uste pueda usar “hg commit -l nombre fichero” para reutilizar o el mensaje de consignaci´ n guardado anteriormente.. Ganchos adicionales ´ Mercurial se instala con varios ganchos adicionales.whitespace hook exited with status 1 $ sed -i ’s.whitespace = .6: Un mejor gancho para espacios en blanco finales El ejemplo de la figura 10.7.6 es mucho m´ s complejo. Esto es lo suficientemente conciso y poderoso para que lo presente aqu´.

allow] controla los usuarios a los que les est´ permitido a˜ adir conjuntos de cambios al reposo a n itorio. o mientras que practicante puede enviar cambios a cualquier fichero o directorio excepto fuentes/sensitivo. del T. ejec´ telo habilitando la opci´ n de salida de depuraci´ n habilitada.Configuraci´ n del gancho acl o Para administrar los conjuntos de cambios entrantes. respecto a la ra´z del repositorio. o ı 2 N.allow] docs/** = escritordoc [acl. un nombre usuario. e La secci´ n [acl.acl = python:hgext. o a a ı u La sintaxis para los ficheros [acl. o o serve Controlar conjuntos de cambios entrantes que est´ n llegando desde un repositorio a trav´ s de http o ssh. el usuario escritordoc s´ lo puede empujar cambios al directorio docs del repositorio.deny] es id´ ntica.allow] y [acl. se niega el acceso a todos los usuarios excepto a todos a los ı o a que se les haya permitido de manera expl´cita (as´ que una secci´ n vac´a implica que se niega el acceso a todos los ı ı o ı usuarios). o a ı pull Controlar conjuntos de cambios entrantes que lleguen v´a un pull (jalado) desde un repositorio local. 118 . ı bundle Controlar conjuntos de cambios entrantes que lleguen desde otro repositorio a trav´ s de un paquete. La secci´ n [acl. Fuentes. no se niega el acceso a ning´ n usuario.deny] determina a qu´ usuarios no se les permite a˜ adir conjuntos de cambios al repositorio. A la izquierda de cada entrada se encuentra e un patr´ n glob que asocia ficheros o directorios. no olvide que usted puede habilitar la salida de depuraci´ n en su hgrc: o 1 2 [ui] debug = true Con esto habilitado. o La secci´ n [acl] s´ lo tiene una entrada. Ya que u o o usted probablemente lo estar´ ejecutando en un servidor donde no es conveniente (o incluso posible) pasar la opci´ n a o --debug. sources2 .acl. Ejemplo: u 1 2 [hooks] pretxnchangegroup. Si o e n esta secci´ n no est´ presente o est´ vac´a. se debe usar el gancho acl como un gancho de tipo pretxnchangegroup. a la derecha. que lista las fuentes de los conjuntos de cambios entrantes a o o las que el gancho debe prestar atenci´ n. ı push Controlar conjuntos de cambios entrantes que lleguen v´a un push (empuje) desde un repositorio local. 1 2 3 4 5 [acl. o ı En el siguiente ejemplo. el gancho acl imprimir´ suficiente informaci´ n para permitirle saber porqu´ est´ permitiendo o a o e a denegando la operaci´ n de empujar a usuarios espec´ficos. Si esta secci´ n no est´ presente. Esto le permite ver qu´ ficheros son modificados por cada conjunto de cambios entrante.hook La extensi´ n acl es configurada mediante tres secciones. Si esta secci´ n no est´ presente. Este es a e ´ el valor por defecto de sources.deny] fuentes/sensitivo/** = practicante Pruebas y resoluci´ n de problemas o Si usted desea probar el gancho acl. Usualmente usted no necesita configurar esta secci´ n. y deshacer el efecto de un e grupo de conjuntos de cambios si alguno de ellos modifica alg´ n fichero “prohibido”. se le permite acceso a todos los usuarios excepto a los que se les haya negado o a expl´citamente el acceso. y usualmente es el unico valor de configuraci´ n que necesitar´ para este ´tem.

El esquema de base de datos que Bugzilla usa cambia ocasiono ´ almente. La informaci´ n para configurar este gancho se ubica en la secci´ n [bugzilla] de su hgrc.com> in the frobnitz repository. Ac´ hay algunas posibilidades: u a o a Requerir que cada conjunto de cambios tenga un ID de fallo en su mensaje de consignaci´ n. y porque Bugzilla no fue escrito con este tipo de integraci´ n o en mente. por ejemplo como ı sigue: 1 2 [hooks] incoming. el gancho podr´a reconocer la cadena “corregido fallo 31337” como n ı la se˜ al de que deber´a actualizar el estado del fallo 31337 a “requiere pruebas”.2. configurar este gancho es un proceso algo complejo. Entrante.bugzilla. n ı Configuraci´ n del gancho bugzilla o Usted deber´a configurar este gancho en el hgrc de su servidor como un gancho incoming3 . host El nombre de m´ quina (hostname) del servidor MySQL que almacena sus datos Bugzilla. Esto le permitir´ al gancho rechazar cambios que a a no contiene IDs de fallos. Se a˜ ade un comentario al fallo que se ve as´ (usted puede configurar los contenidos del comentario—vea m´ s n ı a abajo): 1 2 3 4 5 6 7 8 Changeset aad8b264143a. refers to this bug. For complete details. 119 . el gancho sea ejecutado. Usted puede usar el c´ digo de este gancho como un punto de partida para otras recetas de integraci´ n con Bugzilla o o a´ n m´ s ex´ ticas.node=aad8b264143a Changeset description: Fix bug 10483 by guarding against some NULL pointers El valor de este gancho se encuentra en que automatiza el proceso de actualizar un fallo cuando un conjunto de cambios ´ se refiera a el. Usted puede instalar este gancho en un servidor compartido. o o version La versi´ n de Bugzilla instalada en el servidor. para que cada o vez que un usuario remoto empuje cambios al servidor. made by Joe User <joe. usted o querr´ configurar el gancho como uno de tipo pretxncommit. Por ejemplo. A la fecha. har´ f´ cil para la gente navegar directamente desde un a a fallo Bugzilla a un conjunto de cambios que se refiere a ese fallo. Si no est´ disponible como paquete binario para su sistema. see http://hg. a 3 N. usted puede descargar el paquete a desde [Dus]. La base de datos debe a ser configurada para permitir conexiones desde las m´ quinas en las que usted ejecute el gancho bugzilla.7.hook Debido a la naturaleza especializada de este gancho.bugzilla = python:hgext.16. Antes de empezar. Permitir a los conjuntos de cambios entrantes modificar autom´ ticamente el estado de un fallo. En este caso. la unica versi´ n soportada ı e o es la 2. as´ que este gancho debe saber exactamente qu´ esquema usar. usted debe instalar la interfaz de Python para MySQL en los sistemas en los que se vaya a ejecutar el gancho.user@domain.domain.10. bugzilla—integraci´ n con Bugzilla o La extensi´ n bugzilla a˜ ade un comentario a un fallo Bugzilla siempre que encuentre una referencia al ID de o n dicho fallo en un mensaje de consignaci´ n. del T. Si usted configura este gancho adecuadamente. as´ como simplea ı mente a˜ adir un comentario.com/frobnitz?cmd=changeset.

conf . si usted ha instalado Bugzilla en /var/www/html/bugzilla: a ı 1 cd /var/www/html/bugzilla && . El fichero hgrc principal se ver´a as´: ı ı 1 2 3 # fichero hgrc normal se refiere a un fichero usermap externo [bugzilla] usermap = /home/hg/repos/userdata/bugzilla-usermap. La base de datos debe ser configurada a para permitir a dicho usuario conectarse desde cualquiera de las m´ quinas en las que se ejecute el gancho a bugzilla. El valor por defecto para este ´tem es bugs. 1 2 [usermap] jane. Si o esto no se ajusta a sus necesidades. o Cada ´tem en la secci´ n [usermap] contiene una direcci´ n de correo electr´ nico a la izquierda.user@example. el gancho bugzilla trata de usar la direcci´ n de correo electr´ nico de la persona que hizo la o o consignaci´ n del conjunto de cambios como el nombre de usuario Bugzilla con el cual debe actualizar el fallo.com = jane Usted puede mantener los datos de [usermap] en un fichero hgrc. El nombre por defecto para este ´tem es bugs. En este caso. Si Bugzilla y este gancho no est´ n instalados en la misma m´ quina.dentro de un repositorio hg [usermap] stephanie@example. ı que es el nombre est´ ndar de la base de datos MySQL en donde Bugzilla almacena sus datos. pero t´picamente se o ı ver´ as´. y un nombre de ı o o o usuario Bugzilla a la derecha.com El programa processmail de Bugzilla espera recibir un ID de fallo (el gancho reemplaza “ %s” por el ID del fallo) y una direcci´ n de correo. as´ que n ı usted deber´ asegurarse de que los usuarios no autorizados no puedan leer el fichero hgrc en donde usted guarda a esta informaci´ n. usted deber´ encontrar una manera a a a de ejecutar processmail en el servidor donde est´ instalado Bugzilla. Este usuario debe tener acceso y poder modificar las tablas de Bugzilla. necesitar´ que este gancho ejecute un comando siempre que actualice la base n a de datos. Esto hace posible para sus usuarios mantener sus propias entradas usermap.user El nombre de usuario que se usar´ para conectarse al servidor MySQL. ı a ´ password La contrase˜ a MySQL para el usuario configurado anteriormente. El comando que se ejecute depende de en d´ nde haya sido instalado Bugzilla. o db El nombre de la base de datos Bugzilla en el servidor MySQL. Esta es almacenada como texto plano./processmail %s nobody@nowhere. o decirle al gancho bugzilla que lea la informaci´ n desde un fichero usermap externo. a Asociar nombres de consignadores a nombres de usuario Bugzilla Por defecto.conf Mientras que el fichero usermap al que se hace referencia se ver´a as´: ı ı 1 2 3 # bugzilla-usermap. usted puede almacenar los datos de usermap en (por ejemplo) un o repositorio modificable por los usuarios. Tambi´ n espera poder escribir a ciertos ficheros en el directorio en que se o e ´ ejecuta.com = steph 120 . es posible asociar direcciones de correo a nombres de usuario Bugzilla usando una secci´ n [usermap]. a notify Si usted desea que Bugzilla env´e un correo de notificaci´ n a los suscriptores despu´ s de que el gancho haya ı o e a˜ adido un comentario a un fallo. que es el nombre est´ ndar del usuario para Bugzilla en una base de datos MySQL.

16 # server-side repos live in /home/hg/repos. como la cadena base a usar cuando se construya una URL que le permita a a los usuarios navegar desde un comentario de Bugzilla a la vista de un conjunto de cambios.conf template = Changeset {node|short}. usted no puede especificar ese tipo de condici´ n en un fichero o o sudoers. El gancho bugzilla pubn ı o licar´ esto cuando expanda una plantilla.com/ A continuaci´ n se presenta un ejemplo completo de configuraci´ n para el gancho bugzilla. Esta indirecci´ n a trav´ s de un gui´ n envoltorio es necesaria. El gui´ n processmail algunas veces hace que Bugzilla escriba en a o o ficheros en su directorio de configuraci´ n.node={node|short} nChangeset description: n t{desc|tabindent} Pruebas y resoluci´ n de problemas o Los problemas m´ s comunes que aparecen en la configuraci´ n del gancho bugzilla suelen estar relacionados con a o la ejecuci´ n del gui´ n de Bugzilla processmail y la asociaci´ n de nombres de consignadores a nombres de usuario.2 arriba el usuario que ejecuta el proceso Mercurial en el servidor es tambi´ n o e el usuario que ejecutar´ el gui´ n processmail. nFor complete details.example. A continuaci´ n se presenta una entrada de ejemplo para un fichero sudoers. Ejemplo: 1 2 [web] baseurl = http://hg. y usted tiene un repositorio cuya ruta es /home/hg/repos/app/tests. Usted puede hacer que processmail sea ejecutado con la identidad del usuario adecuado usando el comando sudo. refers to this bug. usted puede a˜ adir un ´tem baseurl a la secci´ n [web] de su hgrc. so strip 4 leading # separators strip = 4 hgweb = http://hg. Por ejemplo. si los repositorios en su servidor se ubican en /home/hg/repos. Adicionalmente. see {hgweb}{webroot}?cmd=changeset. entonces fijar strip a 4 resultar´ en una ruta a parcial de app/tests. usted los especifica como una plantilla n Mercurial. o 1 hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s Esto permite que el usuario hg user ejecute el programa processmail-wrapper con la identidad del usuario httpd user.7. o o o Recuerde que en la secci´ n 10. Los contenidos del giu´ n envoltorio son simples: o 121 . porque processmail espera que al ser ejecutado su o e o directorio actual sea aquel en el cual se instal´ Bugzilla. El gancho har´ disponible esta ruta parcial cuando expanda una plantilla. a template El texto de la plantilla a usar. esta o plantilla puede usar hgweb (el valor del ´tem de configuraci´ n hgweb de arriba) y webroot (la ruta construida ı o usando strip arriba). u o strip La cantidad de elementos iniciales de ruta a remover de un nombre de ruta del repositorio para construir una ruta parcial para una URL. como webroot.com/ usermap = /home/hg/repos/notify/bugzilla. y los ficheros de configuraci´ n de Bugzilla usualmente son propiedad del o o usuario bajo el cual se ejecuta el servidor web. o o 1 2 3 4 5 6 7 8 9 10 11 12 13 [bugzilla] host = bugzilla.˜ Configurar el texto que se anade a un fallo Usted puede configurar el texto que este gancho a˜ ade como comentario. made by {author} in the {webroot} repo.domain. Varias entradas hgrc (a´ n en la secci´ n [bugzilla]) controlan este comportamiento.com password = mypassword version = 2.example. En adici´ n a las variables usuales relacionadas con conjuntos de cambios.

Notificaci´ n. ni tiene una entrada en su [usermap] que lo asocie con un nombre de usuario v´ lido Bugzilla. muchas personas prefieren recibir las notificaciones de cambios v´a correo electr´ nico./processmail "$1" nobody@example. y asociar´ los subscriptores frente a dicha a ruta. Fije ı ı este ´tem en false para permitir el env´o de correos. strip La cantidad de caracteres iniciales de separaci´ n de ruta a remover de la ruta del repositorio. o o test Por defecto. o desactivar completamente esta caracter´stica.3. imprime el mensaje que se enviar´a. El gancho notify4 le permite a usted ı o enviar notificaciones a un conjunto de direcciones de correo cuando lleguen conjuntos de cambios en los que los subscriptores est´ n interesados.notify = python:hgext. y ser´a maleducado o ı enviar a los subscriptores una cantidad de notificaciones “rotas” mientras usted depura su configuraci´ n.notify = python:hgext. este gancho no env´a correos en absoluto.1 2 #!/bin/sh cd ‘dirname $0‘ && .hook La informaci´ n para configurar este gancho se ubica en la secci´ n [notify] de un fichero hgrc. del T. usted puede limitar el ı ´ tama˜ o del diff.com Lo que esto quiere decir es que la direcci´ n del consignador. notify—enviar notificaciones de correo electr´ nico o Aunque el servidor web embebido de Mercurial provee notificaciones de cambios en cada repositorio.com No parece importar qu´ direcci´ n de correo se le pase a processmail. actualizar sus subscripciones. a a 10. Configuraci´ n del gancho notify o Usted puede configurar el gancho notify para enviar un mensaje de correo por conjunto de cambios entrante. fijar strip a 4 har´ que a a notify elimine las partes iniciales de la ruta hasta shared/test. as´ que usted puede a ı personalizar los contenidos del mensaje de notificaci´ n que se env´a.notify.notify. Es util para permitir a los subscriptores revisar los n ı cambios inmediatamente. Esto se mantiene separado o o o del hgrc principal para que usted pueda mantenerlo en un repositorio. john. El mensaje de error se ver´ as´: a ı 1 cannot find bugzilla user id for john. los usuarios ver´ n un mensaje de error del gancho bugzilla a cuando empujen cambios al servidor. o ´ uno por grupo entrante de conjuntos de cambios (todos los que llegaron en un unico empuje o jalado). no es un nombre de o usuario Bugzilla v´ lido. e o Si su [usermap] no es configurada correctamente. El motivo por el que el env´o de correos est´ desactivado es ı ı ı a que hacen falta varios intentos para configurar esta extensi´ n exactamente como usted desea. Por ejemplo. el gancho notify incluye un diff de cada conjunto de cambios que se env´a. e De la misma forma que con el gancho bugzilla. o ı Por defecto. en vez de eso.q. o config La ruta a un fichero de configuraci´ n que contiene informaci´ n de subscripci´ n. el gancho notify est´ orientado a plantillas. si los repositorios en su servidor est´ n en /home/hg/repos. 4 N.q. en vez de tener que hacer clic para visitar una URL. 1 2 3 4 5 [hooks] # enviar un correo por grupo de cambios changegroup.public@example. o 122 .hook # enviar un correo por cambio incoming.com. y empujar los cambios de vuelta a su servidor.public@example. y a notify est´ trabajando con un repositorio llamado /home/hg/repos/shared/test. La gente puede clonar ese repositorio.7. al decidir si un o repositorio tiene subscriptores.

6 +212.template El texto de plantilla a usar cuando se env´en mensajes. Por defecto.example. por o ı ı ejemplo.example. o ı Si usted fija el ´tem baseurl en la secci´ n [web].h Wed Aug 02 15:25:26 2006 -0700 @@ -212.. A continuaci´ n se presenta un ejemplo completo de configuraci´ n para el gancho notify.node=3cba9bfe74b5 description: Handle error case when slave has no buffers diffs (54 lines): diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests. est´ fijado en 300. Especifica los contenidos de la cabecera del mensaje y el ı cuerpo del mismo. estar´ disponible como ı o a webroot.. o o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [notify] # enviar correo test = false # datos de subscriptores est´n en el repositorio notify a config = /home/hg/repos/notify/notify.snip.8. Esto le permite a usted indicar a notify para que s´ lo env´e correos acerca de cambios que usuarios remotos hayan empujado al repositorio v´a un servidor. Fije esto a 0 para omitir los diffs en los correos de notificaci´ n. usted lo puede usar en una plantilla. 2 Aug 2006 15:25:46 -0700 (PDT) changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave details: http://hg. Si la longitud de un diff es mayor u a ı n a eso. Vea la secci´ n 10. maxdiff El n´ mero m´ ximo de l´neas de datos de diff a a˜ adir al final de un mensaje..com/ Esto producir´ un mensaje que se ver´ como el siguiente: a a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 X-Hg-Repo: tests/slave Subject: tests/slave: Handle error case when slave has no buffers Date: Wed.] 123 .15 @@ static __inline__ void test_headers(void *h) [.conf # repos est´n en /home/hg/repos on server.h --. a o sources Una lista de fuentes de conjuntos de cambios a considerar.3 para las fuentes que usted puede especificar aqu´. se trunca.com/tests/slave?cmd=changeset.node={node|short} description: {desc|tabindent|strip} [web] baseurl = http://hg. as´ que elimine 4 a ı # caracteres"/" strip = 4 template = X-Hg-Repo: {webroot} Subject: {webroot}: {desc|firstline|strip} From: {author} changeset {node|short} in {root} details: {baseurl}{webroot}?cmd=changeset.a/include/tests.h Wed Aug 02 15:19:52 2006 -0700 +++ b/include/tests..

se considera que fall´ .localrepository. Si una variable de entorno se llama HG URL.node. “0” para “false”.localrepo. La a a cadena vac´a es usada para representar un “ID de conjunto de cambios nulo” en vez de una cadena de ceros. repo. 5 N. si puede ser determinada.8. Ejecuci´ n de ganchos externos o Un gancho externo es pasado al int´ rprete de comandos del usuario bajo el cual se ejecuta Mercurial. Si termina con un c´ digo de o o salida diferente de cero. El par´ metro repo es un objeto mercurial. o 6 N.ui.Pruebas y resoluci´ n de problemas o No olvide que por defecto. contendr´ la URL de un repositorio remoto. Si retorna “true”6 o genera una ´ excepci´ n.ui. se considera que este tuvo exito. ı Si hay un par´ metro llamado url.bin. El nombre de cada variable de entorno se pasa a a may´ sculas y se le a˜ ade el prefijo “HG ”. a a Los par´ metros booleanos son representados como objetos bool de Python. simplemente se imprimir´ el ı a mensaje que se enviar´a. se considera que tuvo exito.8. 10. a a Un par´ metro booleano se representa con la cadena “1” para “true”. ı 10. Por ejemplo. con las siguientes caraca ter´sticas en com´ n: ı u Si hay un par´ metro llamado node o parentN . o Note que los IDs de conjuntos de cambios son pasados a los ganchos de Python como cadenas hexadecimales. contendr´ un ID hexadecimal de un conjunto de cambios. del T. la extensi´ n notify no enviar´ ning´ n correo electr´ nico hasta que usted la configure o a u o expl´citamente para hacerlo. no como los hashes binarios que la API de Mercurial usa normalmente. se considera que ha fallado. fijando el valor de test a false. est´ n disponibles. como sustituci´ n de variables y redirecci´ n de comandos. Una manera util de pensar en esta convenci´ n de llamado es “d´game si usted o o ı fall´ ”. que son ejecutados desde la ra´z del repositorio). a a Los nombres y valores de los par´ metros en **kwargs dependen del gancho que se invoque. que se ejecutan desde el mismo ı directorio en que Mercurial fue ejecutado). Para convertir un hash de hexadecimal a binario. El gancho es ı e o o a ejecutado desde el directorio ra´z del repositorio (a diferencia de los ganchos internos. El gancho no debe cambiar el directorio de trabajo del ı proceso. use la funci´ n mercurial. el nombre de la u n a variable de entorno que almacena el par´ metro se llamar´ “HG NODE”. Los par´ metros para el gancho se pasan como variables de entorno. HG PARENT1 o HG PARENT2.1. Hasta que usted haga eso. 124 . ´ Si un gancho termina con un c´ digo de salida de cero. del T. Si una variable se llama a HG NODE.8. o 10. ı ´ ´ Si un gancho retorna el valor booleano “false”5 . Informaci´ n para escritores de ganchos o Ejecuci´ n de ganchos internos o Un gancho interno es llamado con argumentos de la siguiente forma: 1 2 def myhook(ui. contendr´ un ID de conjunto de cambios representado como una cadena hexa adecimal.2. **kwargs): pass El par´ metro ui es un objeto mercurial. contendr´ la URL de un repositorio remoto. Falso. porque esto har´a que falle cualquier llamada que se haga a la API de Mercurial. si puede ser determia nada. si el nombre de un par´ metro es “node”. La cadena vac´a es usada para representar un “ID de conjunto de cambios nulo” en vez de una cadena de ı ceros. a Un gancho interno es ejecutado sin cambiar el directorio de trabajo del proceso (a diferencia de los ganchos externos. Verdadero. Las care acter´sticas del int´ rprete.

Todos los n ´ ´ conjuntos de cambios entre este y la punta (tip). a Vac´o—no se pudo descubrir informaci´ n acerca del cliente remoto.3 para m´ s detalles. o o a o Veta tambi´ n: incoming (secci´ n 10. Vea la secci´ n 10. El ID del primer conjunto de cambios que fue a˜ adido en el grupo. ı o push Los conjuntos de cambios son transferidos v´a un empuje de un repositorio a otro.3 para m´ s informaci´ n.10. los medios usados para transferir los conjuntos de cambios a a entre repositorios. 125 . Mercurial le indicar´ a los ganchos la ubicaci´ n de “el otro lado” de una actividad que transfiera a o datos de conjuntos de cambios entre repositorios. o una variable o a de entorno llamada HG SOURCE. pretxnchangegroup (secci´ n 10. o a tendr´ la forma remote:https:ip-address. Par´ metros para este gancho: a node Un ID de conjunto de cambios. La fuente de estos cambios. o a url Una URL. En esos casos. fueron a˜ adidos por un unico jalado (“hg pull”).9.9. ı bundle Los conjuntos de cambios son transferidos desde o hacia un paquete. inclusive.3).9. Este gancho es ejecutado una vez por cada operaci´ n que ı o a˜ ade uno o m´ s conjuntos de cambios. A d´ nde van los cambios—URLs de repositorios remotos o Cuando es posible. o fueron. Esta informaci´ n es provista por Mercurial en un par´ metro Python llamado source7 .9) e o o o 7 N. sin importar si los cambios llegan en grupo. n empuje (“hg push”) o “hg unbundle”. Este gancho se diferencia del gancho incoming. No siempre esta informaci´ n est´ disponible. actun alizar una base de datos de fallos. Vea la secci´ n 10. y o o en muchos casos tambi´ n desde o hacia donde est´ n siendo transferidos.8.9. que es ejecutado una vez por n a cada conjunto de cambios. Mercurial sabe c´ mo son transferidos los conjuntos de cambios. prechangegroup (secci´ n 10.9. Esto es provisto por Mercurial en un par´ metro Python llamado url. la URL tendr´ una de las siguientes formas: a remote:ssh:ip-address—cliente ssh remoto. Referencia de ganchos ˜ changegroup—luego de anadir conjuntos de cambios remotos Este gancho es ejecutado luego de que un grupo de conjuntos de cambios preexistentes ha sido a˜ adido al reposn itorio. pero puede saber desde d´ nde se conecta el o a o cliente. e pull Los conjuntos de cambios son transferidos v´a una operaci´ n de jalado de un repositorio a otro. Averiguar de d´ nde vienen los conjuntos de cambios o Un gancho que involucra la transferencia de conjuntos de cambios entre un repositorio local y otro puede ser capaz de averiguar informaci´ n acerca de “el otro lado”. Mercurial no puede averiguar d´ nde est´ el repositorio remoto. e a Fuentes de conjuntos de cambios Mercurial le indicar´ a un gancho cu´ les son. por ejemplo v´a un “hg pull” o “hg unbundle”. en la direcci´ n IP dada.5).1.8. ı o 10. a o en una variable de entorno llamada HG URL. source Una cadena. Algunos usos posibles para este gancho includen el probar o ensamblar los conjuntos de cambios a˜ adidos. o remote:http:ip-address—cliente remoto http.8. Si el cliente est´ usando SSL. si es conocida. del T. Fuente. serve Los conjuntos de cambios son transferidos desde o hacia un repositorio remoto a trav´ s de http o ssh. 10. en la direcci´ n IP dada.3. La ubicaci´ n del repositorio remoto. Si un gancho es invocado un repositorio que es servido a trav´ s de o a e http o ssh. o notificar a subscriptores de que el repositorio contiene nuevos cambios.

9. Si un cliente remoto jal´ cambios de este o o o repositorio. La fuente de estos cambios. pretxnchangegroup (secci´ n 10. commit—luego de la creaci´ n de un nuevo conjunto de cambios o Este gancho es ejecutado luego de la creaci´ n de un nuevo conjunto de cambios.9. Vea la secci´ n 10.3 para m´ s detalles. n Usted puede usar este gancho para los mismos fines que el gancho changegroup (secci´ n 10. este gancho es ı n o ejecutado una vez por cada conjunto de cambios a˜ adido.10) e o o 10. mientras que a otras es m´ s util correrlo por cada conjunto de cambios. El ID del primer conjunto de cambios del grupo que fue enviado. e n source Una cadena.3 para m´ s informaci´ n.8. parent2 Un ID de conjunto de cambios. por n ejemplo. o Par´ metros para este gancho: a node Un ID de conjunto de cambios. outgoing—luego de la propagaci´ n de los conjuntos de cambios o ´ Este gancho es ejecutado luego de que un grupo de conjuntos de cambios ha sido propagado fuera de este repositorio. Si un grupo de conjuntos de cambios fue a˜ adido en una sola operaci´ n.4.3.1). pretxncommit (secci´ n 10. o o a o Vea tambi´ n: changegroup (secci´ n 10. si es conocida. ˜ incoming—luego de que un conjunto de cambios remoto es anadido Este gancho es ejecutado luego de que un conjunto de cambios preexistente ha sido a˜ adido al repositorio.9. source Una cadena.5).3 para m´ s informaci´ n.9.8. v´a un “hg push”. a o o url Una URL. o a url Una URL.9.7) e o 126 .9. La ubicaci´ n del repositorio remoto. El ID de conjunto de cambios del primer padre del conjunto de cambios que acaba de ser consignado.2.9.8.6).9. El ID del conjunto de cambios reci´ n a˜ adido. source ser´ serve.3). source a ser´ bundle. Vea la secci´ n 10. El ID de conjunto de cambios del conjunto de cambios que acab´ de ser o consignado. Vea la secci´ n 10. a ´ Par´ metros para este gancho: a node Un ID de conjunto de cambios. Par´ metros para este gancho: a node Un ID de conjunto de cambios.10. si es conocida. por ejemplo por un comando “hg push” o “hg bundle”. pull. simplemente o algunas veces es m´ s conveniente ejecutar un gancho una vez por cada grupo de conjuntos de cambios. parent1 Un ID de conjunto de cambios. El ID de conjunto de cambios del segundo padre del conjunto de cambios que acaba de ser consignado. Un uso posible para este gancho es notificar a los administradores que los cambios han sido jalados. Si el cliente que obtuvo los cambios desde este repositorio era local. Vea tambi´ n: precommit (secci´ n 10. La fuente de la operaci´ n (vea la secci´ n 10.1) prechangegroup (secci´ n 10.9. La ubicaci´ n del repositorio remoto.9. o o a o Vea tambi´ n: preoutgoing (secci´ n 10.9) e o o o 10. dependiendo de la operaci´ n que llev´ a cabo el cliente.8. o push.

o o Un uso para este gancho es deshabilitar la capacidad de consignar nuevos conjuntos de cambios. prechangegroup—antes de empezar la adici´ n de conjuntos de cambios remotos o Este gancho de control es ejecutado antes de que Mercurial empiece a a˜ adir un grupo de conjuntos de cambios de n otro repositorio.8. usted podr´a n ı usarlo para “congelar” temporal o permanentemente una rama ubicada en un servidor para que los usuarios no puedan empujar cambios a ella.4. La ubicaci´ n del repositorio remoto. porque es o n ejecutado antes de que se permita que empiece la transmisi´ n de dichos conjuntos de cambios. y permitir la o ´ consignaci´ n s´ lo si el ensamble/compilaci´ n o prueba tiene exito. o o a o Vea tambi´ n: changegroup (secci´ n 10.10. La ubicaci´ n del repositorio remoto.9. parent2 Un ID de conjunto de cambios.10) e o o 10.9. Si este gancho falla. . o la fecha de consignaci´ n. o o a o para ver los posibles valores de este par´ metro.9.8. Vea tambi´ n: commit (secci´ n 10. Par´ metros para este gancho: a source Una cadena. El ID de conjunto de cambios del segundo padre del directorio de trabajo. pretxncommit (secci´ n 10. Este gancho no tiene ninguna informaci´ n acerca de los conjuntos de cambios que van a ser a˜ adidos.9. pero permitiendo conjuntos de cambios entrantes. Es o ejecutado antes de que Mercurial tenga cualquier de los metadatos para la consignaci´ n.8. preoutgoing—antes de empezar la propagaci´ n de conjuntos de cambios o Este gancho es ejecutado antes de que Mercurial conozca las identidades de los conjuntos de cambios que deben ser transmitidos.9. o o a o Vea tambi´ n: outgoing (secci´ n 10. los padres del directorio de trabajo se convertir´ n en los padres del nuevo conjunto de o u a cambios. Vea la secci´ n 10. La fuente la operaci´ n que est´ tratando de obtener cambios de este repositorio (vea la seco a ci´ n 10.3).9) e o o o 10.2). precommit—antes de iniciar la consignaci´ n de un conjunto de cambios o Este gancho es ejecutado antes de que Mercurial inicie la consignaci´ n de un nuevo conjunto de cambios. Par´ metros para este gancho: a ´ source Una cadena.6. La fuente de estos cambios. el mensaje de consignaci´ n. a url Una URL. incoming (secci´ n 10. a Un uso para este gancho es prevenir que se a˜ adan cambios externos a un repositorio.7.9.9. si es conocida.4) e o 127 . pretxnchangegroup (secci´ n 10. Vea la secci´ n 10. Vea la secci´ n 10.3 para m´ s informaci´ n. o los conjuntos de cambios no ser´ n transmitidos. como los ficheros a ser o consignados. si es conocida.1).5. Por ejemplo. Revise la documentaci´ n para el par´ metro source del gancho outgoing.3). Otro es ejecutar un proceso de ensamble/compilaci´ n o prueba. o a url Una URL. y permitiendo al mismo tiempo modificaciones al repositorio por parte de un administrador local.9.3 para m´ s detalles.9. en la secci´ n 10. Un uso para este gancho es evitar que los cambios sean transmitidos a otro repositorio.9. Si la consignaci´ n contin´ a.8. o o o Par´ metros para este gancho: a parent1 Un ID de conjunto de cambios.3 para m´ s informaci´ n. El ID de conjunto de cambios del primer padre del directorio de trabajo.

3 para m´ s detalles. Si el gancho termina exitosamente. El nombre de la etiqueta por crear. Si el gancho tiene exito. Este gancho puede ser usado para examinar autom´ ticamente un grupo de conjuntos de cambios. podr´ ver los conjuntos de a a cambios casi a˜ adidos como si fueran permanentes.9. Si el gancho tiene exito. la o creaci´ n de la etiqueta contin´ a. inclusive. y o todos los conjuntos de cambios se vuelven permanentes dentro de este repositorio. si es conocida. Si el gancho falla. prechangegroup (secci´ n 10.e. Vea la secci´ n 10.9.10) tambi´ n ser´ n ejecutados. o o a o Vea tambi´ n: changegroup (secci´ n 10. si otro proceso Mercurial accesa este repositorio.9. podr´ ver el pr´ cticamente a a a nuevo conjunto de cambios como si fuera permanente.2 y 10. Vea la secci´ n 10.10. la transacci´ n es o deshecha.9. source Una cadena. Este gancho puede acceder a los metadatos asociados con los conjuntos de cambios casi a˜ adidos. Tampoco debe modificar el directorio de trabajo. ı ´ Mientras este gancho est´ corriendo. Si la etiqueta que se va a crear se encuentra bajo control de revisiones. si otro proceso Mercurial accesa el repositorio.8.9.1). La ubicaci´ n del repositorio remoto.8. e a Vea tambi´ n: tag (secci´ n 10. El ID del primer conjunto de cambios que fue a˜ adido en el grupo.9. Si el gancho falla. y los datos para los conjuntos de cambios son eliminados. Si el gancho falla. o Par´ metros para este gancho: a node Un ID de conjunto de cambios. almacenado en . la transacci´ n se completa.9. tag Una cadena. Mientras este gancho est´ corriendo. fueron a˜ adidos por un unico “hg pull”. pero no a deber´a hacer nada permanente con estos datos.10.5) e o o o 10. node Un ID de conjunto de cambios.3).hgtags). Todos los n ´ ´ conjuntos de cambios entre este y el tip. incoming (secci´ n 10. El ID del conjunto de cambios a etiquetar. “hg push” o “hg n unbundle”. Tampoco debe modificar el directorio de trabajo. Esto puede llevar a condiciones de carrera si usted no toma precauciones para evitarlas. pretag—antes de etiquetar un conjunto de cambios Este gancho de control es ejecutado antes de la creaci´ n de una etiqueta.9. la transacci´ n es deshecha.3 para m´ s informaci´ n. no se crea la etiqueta. y los datos de consignaci´ n son borrados. o u Par´ metros para este gancho: a ´ local Un booleano. Indica si la etiqueta es local a esta instancia del repositorio (p.hg/localtags) o administrado por Mercurial (almacenado en . o a url Una URL. Esto puede llevar a condiciones de carrera si usted no toma n precauciones para evitarlas. a todos los conjuntos de cambios son “rechazados” cuando la transacci´ n se deshace. o o Este gancho tiene acceso a los metadatos asociados con el pr´ cticamente nuevo conjunto de cambios. Si el gancho falla. pero no debe n hacer nada permanente con estos datos.9. La fuente de estos cambios.8. los ganchos precommit y pretxncommit (secciones 10. pretxncommit—antes de completar la consignaci´ n de un nuevo conjunto de o cambios Este gancho de control es ejecutado antes de que una transacci´ n—que maneja una nueva consignaci´ n—se como o ´ ´ plete. pretxnchangegroup—antes de completar la adici´ n de conjuntos de cambios o remotos Este gancho de control es ejecutado antes de una transacci´ n—la que maneja la adici´ n de un grupo de conjuntos o o ´ de cambios nuevos desde fuera del repositorio—se complete. Par´ metros para este gancho: a 128 .12) e o 10.9. la transacci´ n se completa y el conjunto de cambios se hace permanente dentro de este o repositorio.

o Par´ metros para este gancho: a ´ local Un booleano.9. la actualizaci´ n o fusi´ n pueden proceder. El ID del conjunto de cambios reci´ n consignado. Si se fusion´ el o directorio de trabajo. o o error Un booleano.hg/localtags) o administrado por Mercurial (almacenado en . a parent2 Un ID de conjunto de cambios. no se habr´ cambiado este padre.9. S´ lo est´ definido si se fusion´ el directorio de trabajo.9. Par´ metros para este gancho: a parent1 Un ID de conjunto de cambios.9. tag—luego de etiquetar un conjunto de cambios Este gancho es ejecutado luego de la creaci´ n de una etiqueta. El ID del padre al cual fue actualizado el directorio de trabajo.. Indica si la actualizaci´ n o fusi´ n fue completada exitosamente. Es ejecutado s´ lo si las o revisiones usuales de Mercurial antes de las actualizaciones determinan que la actualizaci´ n o fusi´ n pueden proceder. S´ lo est´ definido si se est´ fusionando el directorio de trabajo. tag Una cadena.8) e o 10. o o parent1 Un ID de conjunto de cambios.9. parent2 Un ID de conjunto de cambios.2) es ejecutado antes de este a o gancho. El ID de la o a a revisi´ n con la cual est´ siendo fusionado el directorio de trabajo.6) e o 10. este gancho indica si la actualizaci´ n o fusi´ n fueron completados adecuadamente. almacenado en .9.e. e parent1 Un ID de conjunto de cambios. Si la etiqueta creada est´ bajo control de revisiones. si falla.12. preupdate—antes de actualizar o fusionar el directorio de trabajo Este gancho de control es ejecutado antes de actualizar o fusionar el directorio de trabajo. El ID del conjunto de cambios que fue etiquetado. la actualizaci´ n o fusi´ n no o o o o empiezan. El ID del padre al que el directorio de trabajo ser´ actualizado. no cambiar´ este padre. a parent2 Un ID de conjunto de cambios. Indica si la etiqueta es local a esta instancia del repositorio (p. o o Si el gancho termina exitosamente. Vea tambi´ n: precommit (secci´ n 10. o a Vea tambi´ n: update (secci´ n 10. El ID de conjunto de cambios del primer padre del conjunto de cambios que acaba de ser consignado.node Un ID de conjunto de cambios.9. El ID de la revisi´ n con o a o o la que fue fusionado el directorio de trabajo.9. El nombre de la etiqueta que fue creada. Vea tambi´ n: preupdate (secci´ n 10.hgtags). update—luego de actualizar o fusionar el directorio de trabajo Este gancho es ejecutado despu´ s de una actualizaci´ n o fusi´ n en el directorio de trabajo. node Un ID de conjunto de cambios. Ya que una fusi´ n e o o o puede fallar (si el comando externo hgmerge no puede resolver los conflictos en un fichero). Si se est´ fusioa a nando el directorio de trabajo. el gancho commit (secci´ n 10.11) e o 129 .11. Vea tambi´ n: pretag (secci´ n 10.13. El ID de conjunto de cambios del segundo padre del conjunto de cambios que acaba de ser consignado.13) e o 10.

ı El estilo compact lo reduce a tres l´neas.1] 4b75acdd4698 2009-02-10 18:23 +0000 Added tag mytag for changeset 522d8d7a8fda 1[mytag] 522d8d7a8fda 2009-02-10 18:23 +0000 added line to end of <<hello>> file. a a 130 .com> date: Tue Feb 10 18:23:30 2009 +0000 summary: added line to end of <<hello>> file. o o Antes de dar un vistazo a los estilos que trae Mercurial.1. Usar estilos que vienen con Mercurial Hay ciertos estilos listos que vienen con Mercurial.1 for changeset 4b75acdd4698 2[v0. El mecanismo se o basa en plantillas. o 11. 1 2 3 4 5 6 7 $ hg log -r1 changeset: 1:522d8d7a8fda tag: mytag user: Bryan O’Sullivan <bos@serpentine. Puede usar plantillas para generar salida espec´fica para una orden particular o para especificar la ı visualizaci´ n completa de la interfaz web embebida.Cap´tulo 11 ı Personalizar los mensajes de Mercurial Mercurial provee un poderoso mecanismo que permite controlar como despliega la informaci´ n. Un estilo es simplemente una plantilla predeterminada que alguien escribi´ e instal´ en un sitio en el cual Mercurial puede encontrarla. pero ocupa mucho espacio—cinco l´neas de salida por cada conjunto de cambios. presentadas de forma suscinta. revisemos su salida usual. 0 d0c3b909ac1b added hello 2009-02-10 18:23 +0000 bos bos bos bos El estilo de la bit´cora de cambios vislumbra el poder expresivo del sistema de plantillas de Mercurial. Este a estilo busca seguir los est´ ndares de bit´ cora de cambios del proyecto GNU[RS]. Es en cierta medida informativa. ı 1 2 3 4 5 6 7 8 9 10 11 12 13 $ hg log --style compact 3[tip] b638ce454bd0 2009-02-10 18:23 +0000 Added tag v0.

1 2 [ui] style = compact Si escribe un estilo. Dado que son ´ las ordenes m´ s importantes que necesitan personalizaci´ n. puede usarlo bien sea proveyendo la ruta a su fichero de estilo o copiando su fichero de estilo a un lugar en el cual Mercurial pueda encontrarlo (t´picamente el subdirectorio templates de su directorio de ı instalaci´ n de Mercurial).1.hgtags: Added tag v0. del T. “hg log”. Cuestiones b´ sicas de plantillas a Una plantilla de Mercurial es sencillamente una pieza de texto.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ hg log --style changelog 2009-02-10 Bryan O’Sullivan <bos@serpentine. n 11. 11. added a file with the helpful name (at least i hope that some might consider it so) of goodbye. 1 N. no ha habido muchas solicitudes desde la comunidad de a o ´ usuarios de Mercurial para a˜ adir soporte de plantillas y estilos a otras ordenes.3.hgtags: Added tag mytag for changeset 522d8d7a8fda [4b75acdd4698] [v0. predeterminado 131 .1] * goodbye. o reemplazan con texto nuevo cuando es necesario. hello: added line to end of <<hello>> file. ´ Ordenes que soportan estilos y plantillas ´ Todas las ordenes de Mercurial“relacionadas con log” le permiten usar estilos y plantillas: “hg incoming”. otras partes se o expanden. in addition.1. “hg outgoing” y “hg tip”. [522d8d7a8fda] [mytag] * hello: added hello [d0c3b909ac1b] No es una sorpresa que el estilo predeterminado de Mercurial se llame default1 . Cierta porci´ n nunca cambia. o 11.1 for changeset 4b75acdd4698 [b638ce454bd0] [tip] * . ´ ´ Al momento de la escritura del manual estas son las unicas ordenes que soportan estilos y plantillas.com> * . Especificar un estilo predeterminado Puede modificar el estilo de presentaci´ n que Mercurial usar´ para toda orden v´a el fichero hgrc indicando el o a ı estilo que prefiere usar.2.

vea la secci´ n 11. o desc Cadena. Cada vez que Mercurial encuentra texto encerrado entre corchetes (“{” y “}”). Palabras claves m´ s comunes en las plantillas a Puede empezar a escribir plantillas sencillas r´ pidamente con las palabras claves descritas a continuaci´ n: a o author Cadena. branches Cadena.5. El nombre de la rama en la cual se consign´ el conjunto de cambios. Para imprimir un corchete de forma literal. Ser´ vac´a si el nombre de la rama o a ı es default. pero usemos una plantilla para modificar su salida: 1 2 $ hg log -r1 --template ’i saw a changeset\n’ i saw a changeset El ejemplo anterior ilustra la plantilla m´ s sencilla posible. ejecutemos la misma orden. la cadena “{desc}” en la plantilla ha sido reemplazada en la salida con la descricipci´ n de cada o conjunto de cambios. La descripci´ n en texto del conjunto de cambios.1 for changeset 4b75acdd4698 saw a changeset: Added tag mytag for changeset 522d8d7a8fda saw a changeset: added line to end of <<hello>> file.6 hay m´ s detalles acerca de filtros. en segundos.Antes de continuar. a a o ´ Una plantilla que imprime una cadena fija de texto siempre no es muy util. in addition.4. intentemos algo un poco m´ s complejo.com> date: Tue Feb 10 18:23:30 2009 +0000 summary: added line to end of <<hello>> file. debe o o pasarla por un firltro que la desplegar´ apropiadamente. added a file with the helpful name (at least i hope that some might consider it so) of goodby i saw a changeset: added hello Como puede ver. o a debe escaparlo. es solamente una porci´ n est´ tica de c´ digo que se a o a o imprime una vez por cada conjunto de cambios. Es una secuencia de control. Si omite esta nueva l´nea. o 132 . la segunda es el corrimiento horario de la zona horaria del UTC en la cual se encontraba quien hizo la consignaci´ n. como se describe en la secci´ n 11. que le indica a Mercurial imprimira una nueva l´nea al final de cada objeto de la plantilla. Ahora. o 11. Observe que la cadena de plantilla anterior termina con el texto “\n”. Mercurial ı ı colocar´ cada pieza de salida seguida. En la secci´ n 11. veamos de nuevo un ejemplo sencillo de la salida usual de Mercurial: 1 2 3 4 5 6 7 $ hg log -r1 changeset: 1:522d8d7a8fda tag: mytag user: Bryan O’Sullivan <bos@serpentine.5. La fecha en la cual se consign´ el conjunto de cambios. a 1 2 3 4 5 6 7 $ i i i hg log --template ’i saw a changeset: {desc}\n’ saw a changeset: Added tag v0. intentar´ reema plazar los corchetes y el texto con la expansi´ n de lo que sea est´ adentro. La a o a fecha se expresa como un par de n´ meros. date Informaci´ n de fecha. El autor NO modificado del conjunto de cambios. Si desea m´ s detalles acerca de secuencias de control. No es legible por un humano. El primer n´ mero corresponde a una marca de tiempo UNIX UTC u u (segundos desde el primero de enero de 1970). La opci´ n --template de la orden “hg log” indica a Mercurial usar o el texto dado como la plantilla cuando se imprime cada conjunto de cambios.

6. file dels Lista de cadenas. Los ancestros del conjunto de cambios. Esto involucra usar un filtro. node Cadena. u o tags Lista de cadenas.com> $ hg log -r1 --template ’desc:\n{desc}\n’ desc: added line to end of <<hello>> file. acerca de lo cual hay m´ s en la secci´ n 11. Secuencias de Control El motor de plantillas de Mercurial reconoce las secuencias de control m´ s comunmente usadas dentro de las a cadenas.1: Template keywords in use files Lista de cadenas.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $ hg log -r1 --template ’author: {author}\n’ author: Bryan O’Sullivan <bos@serpentine. file adds Lista de cadenas. in addition. adicionados o eliminados por este conjunto de cambios.1. ve el caracter siguiente y sustituye los dos caracteres con un reemplazo sencillo. El hash de identificaci´ n de este conjunto de cambios como una cadena hexadecimal de 40 caracteres. Cuando ve un backslash (“\”). Ficheros eliminados por este conjunto de cambios. Todos los ficheros modificados. Ficheros adicionados por este conjunto de cambios.5. Unos experimentos sencillos nos mostrar´ n qu´ esperar cuando usamos estas palabras claves. rev Entero. debemos tratarla de forma especial. Como mencionamos anteriormente. o parents Lista de cadenas. la palabra clave de fecha no produce salida legible por un humano. puede ver los resula e tados en la figura 11.00 $ hg log -r1 --template ’date: {date|isodate}\n’ date: 2009-02-10 18:23 +0000 11. El n´ mero de revisi´ n del repositorio local. como se describe a continuaci´ n: o 133 . Todas las etiquetas asociadas al conjunto de cambios. a o 1 2 3 4 $ hg log -r1 --template ’date: {date}\n’ date: 1234290210. added a file with the helpful name (at least i hope that some might consider it so) of goodby $ hg log -r1 --template ’files: {files}\n’ files: goodbye hello $ hg log -r1 --template ’file_adds: {file_adds}\n’ file_adds: goodbye $ hg log -r1 --template ’file_dels: {file_dels}\n’ file_dels: $ hg log -r1 --template ’node: {node}\n’ node: 522d8d7a8fda9a24dcac9c5ccfcca067b933220b $ hg log -r1 --template ’parents: {parents}\n’ parents: $ hg log -r1 --template ’rev: {rev}\n’ rev: 1 $ hg log -r1 --template ’tags: {tags}\n’ tags: mytag Figura 11.

relativa al tiempo actual. Por ejemplo.com>” se extrae “serpentine. o escape Cualquier texto. Muestra la edad de la fecha. firstline Cualquier texto. Extrae la primera cadena que luce como una direcci´ n de correo. “foo/bar/baz”. pero de mayor utilidad para la palabra clave author. El nombre de cada filtro est´ seguido ı a de la indicaci´ n de d´ nde puede ser usado y una descripci´ n de su efecto. pero de mayor utilidad para la palabra clave author. o o o addbreaks Cualquier texto. \} Corchete cerrado.\\ Backslash. Mercurial le permite o a especificar una cadena de filtros opcionales para modificar el resultado de expandir una palabra clave. \n Nueva l´nea. ASCII 11. \{ Corchete abierto. ASCII 175. Mostrar la primera l´nea de texto sin saltos de l´nea. “<” y “>” con las entidades XML. A˜ ade una etiqueta XHTML “<br/>” antes del final de cada l´nea excepto en la final. u fill76 Cualquier texto. ASCII 173. ı domain Cualquier texto. Es util emplearlo antes de pasar el texto por el filtro tabindent. o A continuaci´ n hay una lista de los filtros de Mercurial m´ s comunmente usados.6. de o o “Bryan O’Sullivan <bos@serpentine. o “{”. Encuentra la primera cadena que luce como una direcci´ n de correo electr´ nico. otros pueden usarse unicamente en circunstancias espec´ficas.com”. Mostrar la fecha como una cadena de texto en el formato. age palabra clave date. Por ejemplo.com>” extrae “bos@serpentine. y queremos que a´ n quepa en una ventana de fuente fija y 80 columnas. Muestra una cadena como “2006-09-04 15:13:13 -0700”. Mostrar la fecha como un par de n´ meros legibles. ASCII 13. “{”. ı \r Cambio de l´nea. Mostrar la fecha en un formato similar a la orden date de in a similar format to the Unix. “}”. debe o o escaparlo. Ciertos filtros pueden aplicarse o a ´ a cualquier texto. “\”. Trata el texto como una ruta. Ofrece una cadena como “10 minutes”. ASCII 12. Muestra una cadena como “1157407993 25200”. Lograr que el texto quepa en 76 columnas. Uso de filtros con palabras claves Algunos de los resultados de la expansi´ n de la plantilla no son f´ ciles de usar de inmediato. se convierte en “baz”. “foo\nbar” se convierte en “foo<br/>\nbar”. ASCII 134. u isodate date palabra clave. Una cadena como “Mon Sep 04 15:13:13 2006 -0700”. Reemplaza los caracteres especiales de XML/XHTML: “&”.com”. y extrae solamente el componente del dominio. \v Tab Vertical. ı \t Tab. si desea que la expansi´ n en una plantilla contenga un caracter literal “\”. basename Cualquier texto. Por n ı ejemplo. Lograr que el texto ocupe las primeras 68 columnas. Como se indic´ arriba. de “Bryan O’Sullivan <bos@serpentine. date date palabra clave. 11. Por ejemplo. pero de utilidad sobre todo en palabras claves relativas a ficheros. ASCII 15. pero con la zona horaria inclu´da. ı ı hgdate date palabra clave. retornando el nombre base. “{”. ´ fill68 Cualquier texto. 134 . email Cualquier texto. Ya ha visto el filtro usual isodate en acci´ n con anterioridad para hacer legible la fecha.

Muestra el campo de texto como una secuencia de entidades XML. 11. el segundo al resultado de la aplicaci´ n del primer filtro y as´ sucesivamente. util sobre todo para la palabra clave author. added a file with the helpful name (at least i hope that some might consider it so) of goodbye. esto es necesario ı para lograr que la primera l´nea luzca indentada. u o ´ person Cualquier texto. Muestra el texto que hay antes de la direcci´ n de o correo electr´ nico. y es util poder darle un nombre a una plantilla. De plantillas a estilos Una plantilla provee una forma r´ pida y sencilla para dar formato a una salida. Muestra una fecha con el mismo formato que se usa en los encabezados de correo. al usar un fichero de estilo se dispara el poder del motor de plantillas en un nivel imposible de alcanzar a u ´ usando las opci´ n --template desde la l´nea de ordenes. Retorna el “usuario” de una direcci´ n de correo. in addition. Las plantillas pueden volvers vera ´ bosas.com>” se convierte en “bos”. Un fichero de estilo es una plantilla con un nombre. foo bar se convierte en foo%20bar.7. n ı strip Cualquier texto. pero de mayor utilidad para la palabra clave author. tabindent Cualquier texto. o Por ejemplo. o ı 135 . Por ejemplo. Por ejemplo.obfuscate Cualquier texto. ´ user Cualquier texto. Mostrar a˜ o. Por ejemplo. “Bryan O’Sullivan <bos@serpentine. of a changeset hash. o Mercurial fallar´ e imprimir´ una excepci´ n de Python. Por ejemplo. Escapa todos los caracteres que se consideren como “especiales” por los parsers de URL.1. o ı rfc822date date palabra clave. La cadena de filtros siguientes arman una descripci´ n. es necesario debido a que tabindent indenta todas las l´neas excepto ı ı la primera. o 1 2 3 4 5 6 $ hg log -r1 --template ’description:\n\t{desc|strip|fill68|tabindent}\n’ description: added line to end of <<hello>> file. Combinar filtros Combinar filtros es para generar una salida en la forma como usted lo desea es muy sencillo. Muestra la forma corta de un hash de conjunto de cambios. p. almacenado en un fichero. Esto ayuda a eliminar ciertos robots est´ pidos de adquisici´ n de correo. Tenga en cuenta que el orden de los filtros importa. util sobre todo para la palabra clave author. Observe el uso de “\t” (un caracter tab) en la plantilla para forzar que la primera l´nea se indente. una cadena hexadecimal de 12 bytes. ı urlescape Cualquier texto. shortdate date palabra clave. Muestrauna cadena como “2006-09-04”. M´ s a´ n. Elimina todos los espacios en blanco al principio y al final de la cadena. en los que el tab por convenci´ n se extiende en 8 caracteres). El primer filtro se aplica primero al resultado de la palabra clave. el tratar de a a o ´ usar la salida de la palabra clave desc con el filtro isodate no resultar´ algo util. mes y d´a de una fecha. y las indenta con o e 8 caracteres (por lo menos en sistemas tipo Unix. 04 Sep 2006 15:13:13 -0700”. Muestra el texto con todas las l´neas excepto la primera que comience con el caracter tab. short Hash del conjunto de cambios. usar fill68|tabindent o ı es muy distinto al resultado de usar tabindent|fill68.com>” mostrar´a “Bryan O’Sullivan”. despu´ s aseguran que cabe limpiamente en 68 columnas. Mostrar´a ı una cadena como “Mon.e. Nota: Si trata de aplicar un filtro a una porci´ n de datos que no puede procesarse. “Bryan O’Sullivan <bos@serpentine.6. a 11.

com $ hg log -r1 --template ’{author|obfuscate}\n’ | cut -c-76 &#66. $ hg log -r1 --template ’{desc|strip}\n’ | cut -c-76 added line to end of <<hello>> file. added a file with the helpful name (at least i hope that some m 136 $ hg log -r1 --template ’{desc|tabindent}\n’ | expand | cut -c-76 added line to end of <<hello>> file.hello&gt. in addition.00 $ hg log -r1 --template ’{date|age}\n’ 1 second $ hg log -r1 --template ’{date|date}\n’ Tue Feb 10 18:23:30 2009 +0000 $ hg log -r1 --template ’{date|hgdate}\n’ 1234290210 0 $ hg log -r1 --template ’{date|isodate}\n’ 2009-02-10 18:23 +0000 $ hg log -r1 --template ’{date|rfc822date}\n’ Tue.&#83.&gt. added a file with the helpful name (at least i hope that some m $ hg log -r1 --template ’{desc|fill68}\n’ added line to end of <<hello>> file. added a file with the helpful name (at least i hope that some might consider it so) of goodbye.&#108.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 $ hg log -r1 --template ’{author}\n’ Bryan O’Sullivan <bos@serpentine.&#114.&#32.&lt.&#117.&#11 $ hg log -r1 --template ’{author|person}\n’ Bryan O’Sullivan $ hg log -r1 --template ’{author|user}\n’ bos $ hg log -r1 --template ’looks almost right.com $ hg log -r1 --template ’{author|email}\n’ bos@serpentine. added a file with the helpful name (at least i hope that some m $ hg log -r1 --template ’{desc|addbreaks}\n’ | cut -c-76 added line to end of <<hello>> file.<br/> <br/> in addition. in addition. in addition. but actually garbage: {date}\n’ looks almost right. in addition.&#110.&#108. in addition.&#39. $ hg log -r1 --template ’{desc|fill76}\n’ added line to end of <<hello>> file. added a file with the helpful name (at least i hope tha $ hg log -r1 --template ’{node}\n’ 522d8d7a8fda9a24dcac9c5ccfcca067b933220b .&#121. added a file with the helpful name (at least i hope that some might consider it so) of goodbye. in addition. file.&#105. 10 Feb 2009 18:23:30 +0000 $ hg log -r1 --template ’{date|shortdate}\n’ 2009-02-10 $ hg log -r1 --template ’{desc}\n’ | cut -c-76 added line to end of <<hello>> file. $ hg log -r1 --template ’{desc|firstline}\n’ added line to end of <<hello>> file. added a file with the helpful name (at least i hope that some m $ hg log -r1 --template ’{desc|escape}\n’ | cut -c-76 added line to end of &lt.&#97. but actually garbage: 1234290210.&#79.com> $ hg log -r1 --template ’{author|domain}\n’ serpentine.

137 . construiremos algunos ejemplos. imprime un mensaje a ´ de error suscinto. a 11.7.8. ı ı Se ignoran el espacio en blanco circundante. replicaremos el proceso usual de desarrollo de un fichero de estilo comenzando con algo muy sencillo.style trata de definir la palabra clave changeset. Cuando se le indica a Mercurial que use este fichero de estilo.”.1.8. use el texto de la derecha como la plantilla”. Los ficheros de estilo m´ s sencillos a Nuestro fichero sencillo de estilo contiene una sola l´nea: ı 1 2 3 $ echo ’changeset = "rev: {rev}\n"’ > rev $ hg log -l1 --style . se trata como el nombre de un fichero. ı e y puede contener subsecuentemente cualquier caracter alfanum´ rico o una raya al piso.11. Se omiten las l´neas en blanco. pero omite dar un contenido para esta. Ejemplos de ficheros de estilos Para ilustrar la creaci´ n de un fichero de estilo. Esta debe comenzar con una caracter alfab´ tico o una raya al piso.1.style changeset = Tenga en cuenta que broken. se queja inmediatamente. (En notaci´ n de expree o siones regulares debe coincidir con [A-Za-z_][A-Za-z0-9_]*. ı Si una l´nea comienza con los caracteres “#” o “. En lugar de ofrecer un fichero o completo de estilo y analizarlo. los contenidos de ı este fichero se leer´ n y se usar´ n como cuerpo de la plantilla. Identificar equivocaciones en ficheros de estilo Si Mercurial encuentra un problema en un fichero de estilo en el cual usted est´ trabajando. Si el resto de la l´nea comienza y termina con caracteres encerrados entre caracteres de comillas (bien sea ı sencillas o dobles).7. a a 11. Sintaxis de ficheros de estilo Las reglas de sintaxis para un fichero de estilo son sencillas: El fichero se procesa l´nea por l´nea. resulta muy util. a 11./rev rev: 3 Se le indica a Mercurial. 1 2 $ cat broken. que puede estar precedido o seguido por una cantidad arbitraria o de espacio. ı Una l´nea comienza con una palabra clave. se trata como cuerpo de la plantilla.) El pr´ ximo elemento debe ser un caracter “=”.2. y avanzando por una serie de ejemplos sucesivos m´ s completos. y se omite ı ı como si fuera vac´a. Si el resto de la l´nea no comienza con una comilla. cuando usted identifique lo que significa. “si est´ imprimiendo un conjunto de cambios. la l´nea completa se trata como un comentario.

pero aunque sea cr´ptica.style:1: parse error A continuaci´ n viene el nombre del fichero que contiene el error. a ı ı o Tampoco funcionar´ en caso (muy raro) cuando el repositorio sea una fusi´ n de dos repositorios independientes a o y tiene los dos directorios por ah´. u ı o 1 abort: broken. pero no es utill en ciertos casos: many cases.style:1: parse error La descripci´ n del problema no siempre es clara (como en este caso).1 2 $ hg log -r1 --style broken. casi siempre es o ı trivial la inspecci´ n visual de la l´nea en el fichero de estilo y encontrar lo que est´ mal. o ı a 11. ID revisi´ n}.style abort: broken.style:1: parse error Finalmente.2.style:1: parse error Siguendo el nombre del fichero viene el n´ mero de l´nea en la que se encontr´ el error. o 1 2 $ hg log -r0 --template ’{node}’ 92cb4692d38c537be0935f906eeff2a47033600c ´ No es garant´a de unicidad. Como una parte del par {ID repositorio.8.style:1: parse error Este mensaje de error luce intimidante. puede usar la primera revisi´ n en el repositorio. 1 abort: broken. porque un repositorio as´ no tiene una revisi´ n zero. la descripci´ n de lo que fall´ . 138 . pero no es muy dif´cil de seguir: ı El primer componente es la forma como Mercurial dice “me rindo”. o 1 abort: broken. o o 1 abort: broken. ´ Identificar de forma unica un repositorio ´ Si desea identificar un repositorio de Mercurial “de forma unica” con una cadena corta como identificador. de forma que pueda “reconstruir” posteriormente en caso de ser necesario. Almacene esta informaci´ n de forma independiente cuano o do ejecute construcciones automatizadas u otras actividades. ı No funcionar´ en un repositorio completamente vac´o. ı Hay ciertos casos en los cuales podr´a colocar el identificador: ı Como una llave en la tabla de una base de datos que administra repositorios en un servidor.

Usamos la palabra clave ı o ı header del motor de plantillas para imprimir una l´nea de separaci´ n como la primera l´nea de salida (ver m´ s ı o ı a abajo). also include the status for the error. e Emulamos las l´neas de “separaci´ n” de subversion con caracteres “-” en una l´nea. y a o reemplazar el texto producido previamente por Subversion con valores base que quisi´ ramos ver expandidos. mejor ı col´ quelo en una plantilla. rather than indicating a status of 0 when an error has occurred. La facilidad ı ı ı para leer es importante cuando est´ decidiendo si un texto pertenece a un fichero de estilo o a un fichero de plantilla a inclu´do en el estilo. No me tom´ m´ s de un minuto o dos de trabajo para reemplazar texto literal de un ejemplo de salida de la salida o a de Subversion con ciertas palabras claves y filtros para ofrecer la plantilla anterior. es f´ cil copiar y pegar una porci´ n de su salida en un fichero.template Podr´amos haber inclu´do el texto del fichero plantilla directamente en el fichero de estilo encerrando entre comillas ı ı y reemplazando las nuevas l´neas con secuencias “\n”. si inserta una pieza de texto literal. Si el fichero de estilo luce muy grande o complicado. pero har´a muy dif´cil de leer el fichero de estilos. La salida de subversion incluye un conteo en el encabezado del n´ mero de l´neas en el mensaje de consinaci´ n.8. o 139 . Mostrando salida parecida a Subversion Intentemos emular la salida usual que usa otro sistema de control de revisiones. Subversion.style header = ’------------------------------------------------------------------------\n\n’ changeset = svn.3. Signed-off-by: Sean Hefty <sean.hefty | 2006-09-27 14:39:55 -0700 (Wed. 27 Sep 2006) | 5 lines On reporting a route error. e 1 2 3 4 5 6 $ cat svn. 27 Sep 2006” en el ejemplo de salida anterior) en par´ ntee sis. El motor de plantillas de Mercurial no ofrece una forma sencilla de desplegar una fecha en este formato sin imprimir tambi´ n la hora y la zona horaria. para lograr una salida similara a la de Subversion.11.com> -----------------------------------------------------------------------Dado que la salida de Subversion es sencilla.template r{rev} | {author|user} | {date|isodate} ({date|rfc822date}) {desc|strip|fill76} -----------------------------------------------------------------------Esta plantilla difiere en algunos detalles de la salida producida por Subversion: Subversion imprime una fecha “legible” (el “Wed. 1 2 3 4 5 6 7 8 9 10 $ svn log -r9653 -----------------------------------------------------------------------r9653 | sean.hefty@intel. 1 2 3 $ cat svn. el motor de plantilla no ofrece en la actualidad un filtro que cuente la cantidad de objetos que se le pasen. u ı o No podemos replicarlo en Mercurial. El fichero de estilo se refiere sencillamente a la plantilla.

y otros un poco m´ s especulativos.Cap´tulo 12 ı Administraci´ n de cambios con Colas de o Mercurial 12. La prehistoria de las Colas de Mercurial A finales de los 90s. debe extraer su arreglo del arbol de fuentes anteriores y aplicarlo a la nueva versi´ n. Cuando hay pocos cambios por mantener. Probablemente la m´ s visible es cuando un o a usuario de un proyecto de software de fuentes abiertas contribuye con un arreglo de un fallo o una nueva caracter´stica ı a los mantenedores del proyecto en la forma de un parche. Aquellos que distribuyen sistemas operativos que incluyen programas abiertos usualmente requieren hacer cambios en los paquetes que distribuyen de tal forma que se armen apropiadamente en sus ambientes. de forma tal que pueda aplicarlos a versiones m´ s nuevas del arbol principal. ı a 140 . unos meses despu´ s necesita actualizar a una nueva versi´ n del paquete. y desear´a poder ı ´ mantener tales cambios separados.4 para ver c´ mo emplear tales herramientas). pero est´ “haciendo una sola cosa”). En esta situaci´ n. otros en aumentar las u caracter´sticas. tiene sentido mantener parches como “porciones de trabajo” individual. y se olvida del paquete por un tiempo. a El problema de administraci´ n de parches surge en muchas situaciones. Cuando la cantidad de cambios comienza o o a crecer. Con m´ s que una peque˜ a cantidad de cambios.2. que simo plifica en gran medida el problema de administraci´ n de parches. es muy sencillo administrar un solo parche con los programas est´ ndar a diff y patch (ver la secci´ n 12. El problema de la administraci´ n de parches o Un escenario frecuente: usted necesita instalar un paquete de software desde las fuentes. o ´ Mantener un solo parche frente a un arbol principal es algo tedioso y es f´ cil equivocarse. Algunos se enfocaban en estabilidad. de forma que cada cambio contiene solamente un arreglo de un fallo (el parche puede modificar varios ficheros. Hace sus cambios. muchos desarrolladores del n´ cleo de Linux comenzaron a mantener “series de parches” u que modificaron el comportamiento del n´ cleo de Linux. Si la nueva versi´ n del paquete todav´a tiene el e o o ı ´ fallo. Afortunadamente Mercurial provee una extensi´ n poderos: Colas de Mercurial (o simplemente “MQ”). a ´ Este es un caso simple del problema del “manejo de parches”.1. entender cu´ les ha aplicado se convierte de algo desordenado a a n a algo avasallante. si env´a un o ı parche que arregla un fallo a los mantenedores principales de un paquete y ellos incluyen su arreglo en una publicaci´ n o posterior. Usted tiene un arbol de fuentes del “mantenedor ´ principal” que no puede cambiar: necesita hacer algunos cambios locales sobre el arbol principal. o 12. a y puede tener cierta cantidad de tales parches para diferentes fallos y cambios locales. a ı Aunque. Una tarea tediosa en la cual o es f´ cil equivocarse. la complejidad del problema crece r´ pidamente a medida que la cantidad de parches que tiene que mantener a crece. puede deshacerse de tal parche cuando se actualice a la nueva versi´ n. pero encuentra un fallo que debe arreglar antes de poder comenzar a usarlo. pero no es dif´cil.

Los tama˜ os de las series de parches crecieron r´ pidamente. Las herramientas tradicionales de control de revisiones llevan un registro permanente e irreversible de todo lo que usted hace. push 3 N. Sus parches viven encima del historial de revisiones normales. Este almacena los nombres y los contenidos de estos ficheros. La gran ventaja de MQ No puedo sobreestimar el valor que MQ ofrece en la unificaci´ n de parches y el control de revisiones. as´ el arbol de directorios se restaurar´ con las modificaciones que vienen del parche. tambi´ n es bastante sutil. Cada parche que usted introduce se representa como un conjunto de cambios a en Mercurial. del T. edita los ficheros que est´ arreglando y a “refresca” el parche. que proporcion´ un comportamiento a Mercurial al estilo quilt. Para comenzar. mientras que MQ est´ integrado con Mercurial. a ´ Usted puede elegir qu´ cambios desea aplicar al arbol. Pasar de trabajo con parches con Quilt hacia Colas de Mercurial A mediados de 2005. Mercurial Queues 4 N. usted le indica a quilt que administre ´ un arbol de directorios. contin´ a siendo una porci´ n de u o ´ software tremendamente util para aquellas situaciones en las cuales no puede usar Mercurial y MQ. y puede trabajar bien sobre un conjunto de fuentes que viene de un fichero comprimido y empaquetado o una copia de trabajo de Subversion. o simplemente “quilt” (ver [Gru05] el paper que lo describe). 12. que har´ seguimiento de los cambios requeridos para modificar a ´ ´ el arbol desde “el arbol con un parch aplicado” a un “´ rbol con dos parches aplicados”. Lo m´ s importante es ı ´ a a ´ que puede ejecutar la orden “refresh” en cualquier momento. cambiar qu´ parches ser´ n aplicados y qu´ modificaciones hacen ellos. o La diferencia clave entre quilt y MQ es que quilt no sabe nada acerca del sistema de control de revisiones. en cualquier momento. e a e Quilt no tiene nada que ver con herramientas de control de versiones. ´ El paso de refresco hace que quilt revise el arbol de directorios. usaremos el original en ingl´ s cuando encontremos que facilita la e comprensi´ n o 2 N. En el 2002.4 Dado que quilt no se preocupa por las herramientas de control de revisiones. Andreas Gruenbacher y Martin Quinson tomaron la aproximaci´ n de los guiones de Ano drew y publicaron una herramienta llamada “patchwork quilt” [AG]. introduce originalmente es push y pop es sustraer en este contexto. 1 N. debe ser cuidadoso en c´ mo lo hace. Si “pop”1 un parche. desconcertantes o u o desestabilizantes— de los pasos y errores en el registro de revisiones de forma permanente.3. con la cohesi´ n de MQ con el control de revisiones distribuidos y los parches. del T.2. usted crea un nuevo parche (con una sola orden). y el ultimo parche ser´ actualizado. Esto significa que a puede. para que pueda “introducirlos”2 posterir e ormente. el conjunto de cambios desaparece. Puede crear otro parche sobre el primero.2. Si sustrae un parche. o u 12. 12. Si requiere realizar un experimento e ((((wild-eyed)))). Quilt recuerda qu´ parches ha sacado. En contraste. fue adoptado en gran medida o por desarrolladores de programas abiertos. Trabajar parches con quilt A comienzos del 2003.1. Andrew Morton public´ algunos guiones n a o ´ de l´nea de ordenes que estuvo usando para automatizar la tarea de administrar su cola de parches. Andrew us´ exı o it´ samente tales guiones para administrar centenas (a veces millares) de parches en el n´ cleo de Linux. o puede dejar trazas innecesarias–o peor a´ n. 141 . los cambios hechos por tal parchve e ´ desaparece´an del arbol de directorios. actualiza el parche con todos los cambios que usted haya hecho. A pesar de que esto tiene gran valor. ´ Quilt maneja una pila de parches sobre un arbol de directorios. saca del T. Dado que quilt automatizaba sustancialmente la administraci´ n de parches.2. o La principal raz´ n por la cual los parches han persistido en el mundo del software libre y de fuentes abiertas–a o pesar de la creciente disponibilidad de herramientas poderosas de control de revisiones– es la agilidad que ofrecen. resulta m´ s sencillo o a aislar su trabajo. le indica qu´ ficheros manejar. e Para arreglar un fallo. y puede hacer que ellos desaparezcan del T. Chris Mason tom´ las caracter´sticas de quilt y escribi´ una extensi´ n que llam´ Colas de o ı o o o Mercurial3 .

Y mucho m´ s.1: Uso sencillo de las ordenes diff y patch El tipo de fichero que diff genera (y que patch toma como entrada) se llama un “parche” o un “diff”.) e a Un parche puede comenzar con un texto arbitrario. Vea en la figura 12. que identifica el rango de e l´neas del fichero que el trozo debe modificar. puede usar “hg log filename” para ver qu´ conjuntos de e cambios y parches afectaron un fichero. Puede usar la o o orden “hg annotate” para ver qu´ conjuntos de cambios o parches modificaron una l´nea particular de un fichero e ı fuente. Si un parche no satisface todo lo que usted desea. dado que es el que m´ s comunmente se usa. la integraci´ n de parches con el control de revisiones hace que el entender los parches y revisar sus o efectos—y sus interacciones con el c´ digo en el cu´ l est´ n enlazados— sea mucho m´ s sencillo. pero MQ lo usa como el mensaje de consignaci´ n cuando se crean conjuntos de cambios. Entender los parches ´ Dado que MQ no esconde su naturaleza parche-c´ ntrica. e imprime una lista de diferencias de sus l´neas.000000000 +0000 @@ -1 +1 @@ -this is my original thought +i have changed my mind $ patch < tiny.patch $ cat tiny. con unas l´neas de contexto entre las modificaciones. a 12. es muy util para entender de qu´ se tratan los parches. Para encontrar el inicio del contenido de un parche. o la orden patch busca la primera l´nea que comience con la cadena “diff -”. pero MQ no). no hay diferencia entre un parche y un diff.patch --. ı Cada l´nea de contexto comienza con un caracter de espacio. Por ejemplo. puede desecharlo. puede arreglarlo—tantas veces como lo requiera.1 un ejemplo ´ sencillo de tales ordenes en acci´ n. si la l´nea comienza con un “+” significa “inserte esta l´nea”. La orden ı patch entiende esas diferencias como modificaciones para construir un fichero. Puede usar la orden bisect para hacer una b´ squeda binaria sobre todos los u conjuntos de cambios y parches aplicados para ver d´ nde se introdujo un fallo o d´ nde fue arreglado. Despu´ s del encabezaado vienen varios trozos. El encabezado de fichero describe el fichero que se est´ modificando.patch patching file oldfile $ cat oldfile i have changed my mind ´ Figura 12. busca un fichero con ese nombre para modificarlo. y e e un poco acerca de las herramientas que trabajan con ellos. continua integrando los trozos. Cuando patch ve un nuevo encabezado de fichero.oldfile 2009-02-10 18:23:25. (Usaremos el t´ rmino “parche”.o reaparezcan cuando lo desee. Cada trozo comienza con un encabezado. Despu´ s del encabezado.4. contiene el a nombre del fichero a modificar. diff no imprime un nuevo encabezado para n el trozo. Si no le gusta un parche. la orden patch ignora este texto. La orden de Unix tradicional diff compara dos ficheros. o 1 2 3 4 5 6 7 8 9 10 11 12 13 $ echo ’this is my original thought’ > oldfile $ echo ’i have changed my mind’ > newfile $ diff -u oldfile newfile > tiny. un trozo comienza y termina con unas pocas ı e l´neas (usualmente tres) de texto del fichero que no han sido modificadas. Si ı solamente hay una peque˜ a cantidad de contexto entre trozos sucesivos.000000000 +0000 +++ newfile 2009-02-10 18:23:25. Por ejemplo. Dado que todo parche o a a a que se aplique tiene un conjunto de cambios asociado. En el trozo. Un diff unificado contiene dos clases de encabezados. una l´nea que se ı ı ı ı 142 . ı MQ trabaja con diffs unificados (patch acepta varios formatos de diff adicionales. las cuales llamamos el contexto del trozo. si una l´nea comienza con “-” significa ı ı “elimine esta l´nea”. hasta que lo haya refinado lo suficiente hacia sus expectativas.

basta con preparar el repositorio con la orden “hg qinit” (ver la figura 12. Para verificar que la extensi´ n est´ trabajando.hg/patches. vea un ejemplo en la figura 12.hgrc. y a˜ ada las l´neas de la figura 12.5. MQ lo usar´ como el nombre del fichero en el directorio .3: C´ mo verificar que MQ est´ habilitado o a Puede usar MQ en cualquier repositorio de Mercurial. If -c is specified.6). a o ı (No necesita descargar nada. pero en el momento a o usted ya deber´a tener suficiente informaci´ n para usar MQ.hg/patches. a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ hg help qinit hg qinit [-c] init a new queue repository The queue repository is unversioned by default.4). qinit will create a separate nested repository for patches (qinit -c may also be run later to convert an unversioned patch repository into a versioned one). la ı a orden “hg qinit” no imprime nada cuando es exitosa. ı ı Retomaremos aspectos m´ s sutiles acerca de parches posteriormente (en la secci´ n 12. Comenzar a usar Colas de Mercurial Dado que MQ est´ implementado como una extensi´ n. 143 . ı o 12. el nombre del parche a crear. Esta orden recibe un argumento. Crear un nuevo parche Para comenzar a trabajar en un nuevo parche use la orden “hg qnew”.5. options: -c --create-repo create queue repository use "hg -v help qinit" to show global options Figura 12. edite su fichero o a ˜/. o e a o a puede usar “hg help” para ver si la orden “hg qinit” est´ disponible. n ı 1 2 [extensions] hgext. Como otras ordenes de Mercurial. Esta orden crea un directorio vac´o llamado . y sus comandos solamente operar´ n con tal repositorio.mq = Figura 12.5.5. 12. aparecer´ n varios comandos.) Para habilitar MQ. debe habilitarla expl´citamente antes de comenzar a usarla. a Para comenzar.modifica se representa con una l´nea eliminada y una l´nea insertada.2: L´neas a a˜ adir en ˜/. MQ viene con la distribuci´ n est´ ndar de Mercurial.3. como puede apreciarlo en a la figura 12. You can use qcommit to commit changes to this queue repository.1.hgrc para habilitar la extensi´ n MQ ı n o Cuando la extensi´ n est´ habilitada. donde MQ mantendr´ sus metadatos.

use la orden “hg qrefresh” (figura 12.2. puede editar los ficheros en el directorio de trabajo.hg/patches first. a Una vez que haya creado un nuevo parche.patch tag: tip tag: qbase user: Bryan O’Sullivan <bos@serpentine. Esta orden almacena los cambios que haya hecho al directorio actual de a 144 . El fichero series lista e todos los parches de los cuales MQ tiene noticia para este repositorio. cambiar el orden en que se aplican ciertos parches. Mercurial usa el fichero ı status para mantener registros interns. da seguimiento a todos los parches que MQ ha aplicado en el repositorio. por a ejemplo. Nota: En ciertas ocasiones usted querr´ editar el fichero series a mano. con un parche por l´nea. trabajar´ n de la misma a forma como lo han hecho antes.patch $ hg tip changeset: 1:495236f727e1 tag: qtip tag: first.com> date: Tue Feb 10 18:23:27 2009 +0000 summary: [mq]: first.5: Crear un nuevo parche Tambi´ n hay otros dos nuevos ficheros en el directorio .5) para actualizar el parche en el cual est´ trabajando.4: Preparar un repositorio para usar MQ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ hg tip changeset: tag: user: date: summary: 0:90039acadb36 tip Bryan O’Sullivan <bos@serpentine. Toda las ordenes que de a Mercurial.1 2 3 4 5 6 7 $ $ $ $ $ $ $ hg init mq-sandbox cd mq-sandbox echo ’line 1’ > file1 echo ’another line 1’ > file2 hg add file1 file2 hg commit -m’first change’ hg qinit Figura 12. dado que es f´ cil desorientar a a MQ acerca de lo que est´ pasando.com> Tue Feb 10 18:23:27 2009 +0000 first change $ hg qnew first.patch $ ls . A pesar de esto. Refrescar un parche Cuando usted llega a un punto en el cual desea guardar su trabajo. es una mala idea editar manualmente el fichero status.patch series status Figura 12.hg/patches: series y status.5. como lo har´a ı ´ usualmente. tales como “hg diff” y “hg annotate”. 12.

a/file1 Tue Feb 10 18:23:27 2009 +0000 +++ b/file1 Tue Feb 10 18:23:27 2009 +0000 @@ -1. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $ echo ’line 2’ >> file1 $ hg diff diff -r 495236f727e1 file1 --. desde el m´ s a antiguo hasta el m´ s nuevo (El aplicado m´ s recientemente).tip. a Note que el parche contiene los cambios en nuestro parche anterior como parte de su contexto (lo ver´ m´ s claramente a a en la salida de “hg annotate”). Mercurial aplicar´ este parche sobre su parche anterior. MQ puede manejar un parche sin que este haya sido aplicado al repositorio. intente un experimento.a/file1 Tue Feb 10 18:23:27 2009 +0000 +++ b/file1 Tue Feb 10 18:23:27 2009 +0000 @@ -1. MQ ofrece muchos comandos que son m´ s sencillos de usar cuando a est´ pensando acerca de parches. De todas maneras. como se puede ver en la figura 12. y efectivao o mente la hay.5. puede usar la orden “hg qnew” para crear un nuevo parche.6: Refrescar un parche Puede ejecutar la orden “hg qrefresh” tan seguido como quiera.1 +1. con excepci´ n de “hg qnew” y “hg qrefresh”. hemos sido cuidadosos para aplicar unicamente o ´ ordenes usuaales de Mercurial.3. a La orden “hg qapplied” lista cada parche que MQ haya aplicado en este repositorio.patch diff -r 90039acadb36 -r 131b8ed49ec4 file1 --. Use “hg revert” sobre sus modificaciones para volver al refresco anterior. Manipular la pila de parches La discusi´ n previa indic´ que debe haber una diferencia entre los parches “conocidos” y “aplicados”.qbase] 131b8ed49ec4 2009-02-10 18:23 +0000 [mq]: first. 145 .2 @@ line 1 +line 2 $ hg qrefresh $ hg diff $ hg tip --style=compact --patch 1[qtip. Refresque su parche en momentos oportunos.8.9: e La orden “hg qseries” lista cada parche del cual MQ tiene noticia en este repositorio.2 @@ line 1 +line 2 bos Figura 12.5.patch.trabajo en su parche. o necesite trabajar en otro. Aplicar un parche tras otro y dar seguimiento Cuando haya terminado de trabajar en un parche. 12. a a 12.4. de nuevo.1 +1. y es una buena forma de “colocar marcas” a su trabajo. si el experimento no funciona. ver la figura 12. Para un ejemplo.first. y almacena el conjunto de cambios correspondiente que contiene los cambios. desde el m´ s antiguo a ´ hasta el m´ s nuevo (El ultimo creado). ´ Hasta ahora.

Por ejemplo. “hg qnew -f” incorporar´ n a a cualquier cambio notorio en el nuevo parche que crea pero “hg qpop -f” revertir´ las modificaciones a cualquier a fichero que haya sido afectado por el parche que est´ siendo sustra´do. Puede deshacer la aplicaci´ n de un parche con la o orden “hg qpop”. y el directorio de trabajo no contendr´ los cambios hechos por el parche. ´ Las ordenes que revisan el directorio actual cuentan con una opci´ n “Se lo que estoy haciendo”. (Vea la secci´ n 12.patch 2009-02-10 18:23 +0000 bos diff -r 90039acadb36 -r 4fef714d728c file1 --. La opci´ n -a de “hg qpush” introduce todos los cambios que no hayan sido aplicados. Lo hacen para garantizar que usted no pierda cambio alguno de los que haya hecho. mientras o que la opci´ n -a de “hg qpop” sustrae todos los cambios aplicados.7: Refrescar un parche muchas veces para acumular cambios Un parche aplicado tiene su correspondiente conjunto de cambios en el repositorio. Medidas de seguridad y c´ mo saltarlas o ´ Muchas ordenes MQ revisan el directorio de trabajo antes de hacer cualquier cosa.11.qbase] 4fef714d728c [mq]: first.1 +1. causados en este caso por aplicado la orden “hg add” a file3. o ı la salida de“hg qseries” contin´ a igual.3 @@ line 1 +line 2 +line 3 Figura 12. pero el parche ya no tendr´ un conjunto de ı a cambios correspondientes en el repositorio. Puede reaplicar un parche no aplicado o sustra´do con la orden “hg qpush”. o maneja un parche sustra´do. y los cambios del parche estar´ n presentes de nuevo en el directorio de trabajo.) 12.a/file1 Tue Feb 10 18:23:27 2009 +0000 +++ b/file1 Tue Feb 10 18:23:27 2009 +0000 @@ -1.5. Introducir y sustraer muchos parches ´ Mientras que “hg qpush” y “hg qpop” operan sobre un unico parche cada vez. u 12.tip. El significado exacto de -f depende de la orden. Esto crea un nuevo conjunto de ı cambios correspondiente al parche. puede introducir y sustraer varios parches de una vez.5. y los efectos del parche y el conjunto de cambios son visibles en el directorio de trabajo. a La figura 12. a Vea ejemplos de “hg qpop” y “hg qpush” en acci´ n en la figura 12. la orden “hg qnew” no crear´ un nuevo parche si hay u a cambios notorios.6. y fallan si encuentran alguna modificaci´ n. pero que no hayan o sido incorporados en alg´ n parche. que siempre o est´ nombrada como -f. Vea que hemos sustra´do uno o dos parches.first. La figura 12. ¡Aseg´ rese de leer la documentaci´ n de la a ı u o opci´ n -f de cada comando antes de usarla! o 146 . MQ sabe acerca de.7 m´ s adelante en la cual se o o a explican otras formas de de introducir y sustraer varios cambios.patch.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ echo ’line 3’ >> file1 $ hg status M file1 $ hg qrefresh $ hg tip --style=compact --patch 1[qtip.13 ilusta esto. mientras que “hg qapplied” ha cambiado.10 ilustra la diferencia entre parches aplicados y seguidos.5.

patch. Arregla el fallo sobre la parte fundamental.patch 1[first.second. User Interface en ingl´ s e 147 . es f´ cil arreglar la parte fundamental. Si ve que hay o n un fallo en la parte fundamental mientras est´ trabajando en el parche de UI5 . a a Simplemente use “hg qrefresh” sobre el parche de la UI para guardar los cambios de su trabajo en progreso.a/file1 Tue Feb 10 18:23:27 2009 +0000 +++ b/file1 Tue Feb 10 18:23:28 2009 +0000 @@ -1. y use “hg qpop” para sacar sustraer el parche de la parte fundamental. aplique “hg qrefresh” sobre el parche fundamental. y aplique “hg qpush” sobre el parche de UI para continuar donde hab´a ı quedado.4 @@ line 1 line 2 line 3 +line 4 $ hg annotate file1 0: line 1 1: line 2 1: line 3 2: line 4 Figura 12.tip] 7cf293b98474 [mq]: second. sustraerlo o introducirlo para lograr que otro parche est´ de ultimo y trabajar en a e ese parche por un rato.patch 2009-02-10 18:23 +0000 bos diff -r 4fef714d728c -r 7cf293b98474 file1 --. Interfaz de Usuario.3 +1. 5 N.patch. El primero es un cambio en la parte fundamental de su programa. Digamos que est´ desarrollando una nueva o o a caracter´stica en dos parches.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 $ hg qnew second. Esto significa que usted puede suspender su ´ ´ trabajo en un parche (refresc´ ndolo). del T.7. A continuaci´ n un ejemplo que ilustra c´ mo puede usar esta habilidad.patch $ hg log --style=compact --limit=2 2[qtip.patch 4fef714d728c 2009-02-10 18:23 +0000 bos 2009-02-10 18:23 +0000 bos $ echo ’line 4’ >> file1 $ hg qrefresh $ hg tip --style=compact --patch 2[qtip. Trabajar con varios parches a la vez La orden “hg qrefresh” siempre refresca el ultimo parche aplicado.5. y el segundo–sobre ı el primero—cambia la interfaz de usuario para usar el c´ digo que ha a˜ adido a la parte fundamental.qbase] [mq]: first.patch.second.8: Aplicar un parche despu´ s del primero e 12.tip] 17da5d88f25b [mq]: second.

que no a est´ presente en la ruta. ı El resultado ser´a que el nombre del directorio original estar´a al principio de toda ruta en cada encabezado de fichero. La cantidad de franjas Si ve el encabezado de un parche. e 12. y la orden “hg import” y MQ esperan parches que tengan a uno como cuenta de eliminaciones. Este n´ mero se llama la cantidad de eliminaciones. La orden “hg diff” de Mercurial genera nombres de ruta de esta forma.patch Figura 12. desempacar´a el comprimido de nuevo (para lo cual necesit´ el renombramiento).1 2 3 4 5 6 $ hg qseries first.6. y ı ı o usar´a las opciones -r y -N de diff para generar recursivamente un parche entre el directorio original y el modificado. y querr´a crear un parche.patch 126b84e593ae a655daf15409 e50d59aaea3a Figura 12. la cantidad de a a eliminaciones se refiere a la cantidad de separadores de ruta (y los componentes que vayan con ellos) a eliminar.) a La cantidad a eliminar“est´ ndar” para parches es uno.10: Parches aplicados y no aplicados en la pila de parches de MQ 12.patch 201ad3209902 parches aplicados. pero no aplicado parche aplicado más recientemente { forbid−illegal−params. Conjuntos de cambios presentes { namespace−cleanup.1. Esta es una traza de c´ mo generaba anteriormente los parches la gente (algunos a´ n lo hacen.patch second.patc report−devinfo−correctly. casi todos los parches contienen un componente inicial de a la ruta que necesita ser eliminado.patch $ hg qapplied first. u La opci´ n con “-p1” significa “elimine uno”.patch second. uno original y el otro modiı ficado con exactamente los mismos nombres. a o u pero es raro con las herramientas de control de revisiones del actuales).patc prevent−compiler−reorder. Por lo tanto ella renomı ı ı brar´a su directorio de trabajo. la orden patch tiene la opci´ n -p que indica la cantidad de componentes o de la ruta a eliminar cuando se vaya a aplicar el parche.patch powerpc−port−fixes. Si patch ve un nombre de fichero foo/bar/baz en el encabezado o del fichero. Si el contador es uno volver´ foo/bar en bar. 148 . ı ı y el nombre del directorio modificado estar´a al frente de la porci´ n derecha de la ruta del fichero. eliminar´ foo y tratar´ de parchar un fichero llamado bar/baz. y tambi´ n acerca de los parches. pero /foo/bar (note la barra extra) en foo/bar.patch fix−memory−leak. Alicia desempaquetar´a un comprimido.6.9: Entender la pila de parches con “hg qseries” y “hg qapplied” presente en la serie. (Hablando estrictamente. editar´a sus ficheros. por lo tanto es util conocer ciertos detalles de c´ mo trabaja o patch. ı o Como alguien que reciba un parche de Alicia en la red podr´a obtener dos directorios. notar´ que la ruta al fichero tiene un componente adicional al principio. M´ s acerca de parches a ´ MQ usa la orden GNU patch para aplicar los parches.

patch $ cat file1 line 1 line 2 line 3 line 4 Figura 12. 149 .patch $ hg qpop Now at: first. no podr´ aplicar “hg qimport” en primera medida. imprime un mensaje indicando que aplic´ el trozo con un factor difuso (el n´ mero despu´ s del factor difuso indica cu´ ntas l´neas de contexto patch o u e a ı tuvo que eliminar antes de aplicar el parche). intenta varias estrategias sucesivas que decrecen en precisi´ n para intentar aplicarlo. o Esta t´ cnica de pruebas y error aveces permite que un parche que fue generado contra una versi´ n anterior de un e o fichero.patch Now at: second.12: Pushing all unapplied patches Si recibe un parche de alguien de quien desea adicionar adicionar a su cola de parches.patch second. 311).patch $ hg qseries first. a o 12. y despu´ s usar “patch -pN ” para aplicar tal parche. imprime una l´nea indicando que el trozo fue aplicado. Lo mejor que puede hacer es aplicar “hg ı o qnew” por su cuenta. consulte Fallo de Mercurial No. y el parche necesita una cuenta de eliminaci´ n que no sea uno. intenta encontrar una correspondencia exacta del contexto.11: Modificar la pila de parches aplicados 1 2 3 4 5 6 7 8 $ hg qpush -a applying second. sin tener en cuenta el n´ mero de l´nea.1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ hg qapplied first. u ı ´ Si falla la correspondencia por contexto. Esta complejidad puede ser innecesaria. Si el trozo con contexto reducido es exitoso. porque “hg qimport” o a no tiene todav´a una opci´ n -p option (ver Fallo de Mercurial No. pero a un corrimiento u ı ı del n´ mero de l´nea original. sea aplicada sobre una versi´ n m´ s nueva del mismo. e intenta una ı correspondencia reducida del contexto.patch $ cat file1 line 1 line 2 line 3 Figura 12. seguido de “hg addremove” para tener en e cuenta cualquier fichero adicionado o eliminado por el parche. 311 para m´ s informaci´ n. Estrategias para aplicar parches Cuando patch aplica un trozo. Si no lo logra.patch $ hg qapplied first. Si es exitoso. seguido de “hg qrefresh”. el contexto y el texto a modificar u ı deben coincidir perfectamente.2. patch elimina la primera y la ultima l´nea del contexto. o a Primero patch intenta una correspondencia perfecta donde los n´ meros de l´nea.6.patch second.

un a fichero foo. ı No se preocupa por el bit ejecutable. Cuidado con los difusos Cuando aplique un trozo con un corrimiento. 12. y uno de ellos falla al aplicarse. Si patch o “hg qpush” llegan a mencionar un corrimiento o un factor difuso. Tambi´ n almacena una copia igual al fichero original con la extensi´ n . tendr´ : un fichero original foo. ı e e Casi siempre es buena idea refrescar un parche que fue aplicado con un corrimiento o un factor difuso. y foo. y la o e extensi´ n . En algunos a o casos. Almacena los trozos desechados (tambi´ n llamados “descartados”) en un fichero con el mismo nombre. siempre que haya verificado los resultados del proceso de parchar. la copia del o n e o fichero sin extensi´ n contendr´ cualquier cambio hecho por los trozos que s´ se aplicaron sin problema. aveces ser´ taotalmente exitoso.6.patch abort: patch "add-file3. 150 .) patch no puede representar ficheros vac´os.patch $ hg qnew -f add-file3. pero no ejecutable.1 2 3 4 $ echo ’file 3. como por ejemplo. Por lo tanto en o ı un parche su idea de “A˜ ad´ este fichero” se ver´a como “toda l´nea de este fichero fue a˜ adida”.patch" already exists Figura 12. Los casos m´ s t´picos involucran aplicar a ı un parche dos veces o en un sitio incorrecto del fichero. Y por lo ı tanto su idea de “Borr´ este fichero” deber´a pensarse como “toda l´nea de este fichero fue eliminada” en un e ı ı parche.6. n ı ı 12.13: Crear un parche a la fuerza Cuando ninguna de estas t´ cnicas funciona. n ı ı ı n Trata el renombramiento de un fichero como la eliminaci´ n del nombre anterior y la adici´ n del nuevo nombre. Si usted tiene o a ı un parche que modifica foo con seis trozos.” no “siempre”. Algunos detalles de la representaci´ n de parches o ´ Hay ciertas cosas utiles por saber acerca de c´ mo trabaja patch con los ficheros: o Deber´a ser obvio que patch no puede manipular ficheros binarios. o o Esto significa que los ficheros renombrados dejan un rastro grande en los parches. line 1’ >> file3 $ hg qnew add-file3. es aceptable tener un parche aplicado algo difuso. o con un factor difuso. refrescar el parche genera nueva informaci´ n de contexto que permitir´ aplicarlo limpiamente. crea ficheros nuevos en modo lectura. tales t´ cnicas a e inexactas dejan claramente la posibilidad de corromper el fichero parchado. cuando usted est´ manteniendo un parche que debe estar encima de m´ ltiples revisiones de a u ´ un arbol de fuentes.rej a˜ adida. Digo “casi siempre. patch intenta eliminar un fichero como una diferencia entre el fichero a eliminar y un fichero vac´o. que contiene los cambios que se aplicaron por los cinco trozos exitosos. (Tenga en cuenta que Mercurial no trata de inferir cuando los ficheros han sido renombrados o copiados en un parche en este momento.4. por lo tanto no puede usar un parche para representar la noci´ n ı o ´ “A˜ ad´ este fichero vac´o al arbol”. patch imprime un mensaje indicando que el trozo en cuesti´ n se e o desech´ .rej que contiene el trozo. o a puesto que en ciertas ocasiones refrescar un parche lo har´ fallar frente a una revisi´ n diferente del fichero.orig. deber´a asegurarse que los ficheros modificados est´ n correctos despu´ s del suceso.orig.3. Trata la adici´ n de un fichero como un diff entre un fichero vac´o y el fichero a ser adicionado.

es mejor a a arreglar los trozos descartados antes de introducir parches adicionales o hacer cualquier otra cosa. En mi port´ til antiguo y lento. no hay grandes t´ cnicas para tratar los trozos descartados. consulte la secci´ n 12. tales ´ ordenes revisan el directorio de trabajo para asegurarse de que usted no ha hecho cambios y ha olvidado ejecutar “hg ´ ´ qrefresh”. La orden mpatch puede ayudar con cuatro razones comunes por las cuales un parche ha sido descartado: El contexto en la mitad de un trozo ha cambiado. logr´ aplicar “hg qpush -a” a los 1. y ya no lo hace porque ha cambiado c´ digo subyacente en el cual se basa ı o su parche. Emple´ la serie de parches para el n´ cleo ı e u Linux 2. dej´ ndolo a usted en un programa de e a fusi´ n cuando la herramienta haya terminado su trabajo. a n En primer lugar. el segundo es uno y as´ sucesivamente.17. ı a n Un trozo remueve l´neas con contenido ligeramente diferente que aquellas que est´ n presentes en el fichero. ı a Si usted usa wiggle o mpatch. trate de hacer “en lote” las operaciones.5 minutos.6 segundos. Casi siempre deber´ consultar el e a fichero .6. Si su parche sol´a aplicarse limpiamente.12.8.12-rc2 y 2.6. a Otro hacker del nucleo Linux. Cada vez que ejecute “hg qpush” o “hg qpop”.6. introducir´ tantos parches a como sea necesario hasta que el especificado est´ en el tope de la pila. o Desafortunadamente. un hacker del n´ cleo Linux. que es u o m´ s vigorosa que patch en su intento de hacer que se aplique un parche.779 l´neas de cambios en 287 e a ı ficheros) en 6. Si se refiere al n´ mero. deber´a ser doblemente cuidadoso al revisar sus resultados cuando haya terminado. Si es aventurero. Pero en un arbol mediano (con decenas n o ı de miles de ficheros). puede tomar un segundo o m´ s. ´ Claramente. (En un port´ til m´ s nuevo.rej y editar el fichero objetivo. aplicando los trozos descartados a mano. Puede o identificar el “parche destino” que desee. a ´ Las ordenes “hg qpush” y “hg qpop” le permiten introducir o sustraer varios parches en una operaci´ n. Si ha dejado ficheros . MQ funciona adecuadamente en arboles grandes. las Colas de Mercurial pueden ayudar. Los apliqu´ sobre un repositorio del n´ cleo de Linux con todas e u las 27. MQ e sustraer´ parches hasta que el parche destino est´ en el tope. En un arbol peque˜ o. Corr´ unos experimentos de desempe˜ o a mediados ı n del 2006 para una charla que d´ en la conferencia EuroPython 2006 [O’S06].738 parches en 3. de tal forma que usted pueda verificar lo que ha hecho y o pueda terminar de aplicar cualquier fusi´ n faltante. esto significa que el primer parche es cero. Un trozo ha perdido cierto contexto al principio o al final. y adem´ s hay unos trucos que pueden emplearse a para obtener el m´ ximo desempe˜ o. escribi´ una herramienta similar o llamada mpatch [Mas].17-mm1.738 parches. o 12. y “hg qpop -a” a e en 30 segundos. escribi´ una herramienta llamada wiggle [Bro]. maximizar el rendimiento de MQ MQ es muy eficiente al tratar con una gran cantidad de parches. que sigue una aproximaci´ n sencilla para automatizar la aplicaci´ n de trozos descartados por o o patch. mostrar´ un texto de error y saldr´ .6. Cuando aplique “hg qpush” con un destino. mpatch refuerza este m´ todo de revisar por partida doble su salida.472 revisiones entre 2. Un trozo largo podr´a aplicarse mejor—por completo o una parte—si estaba cortado en trozos m´ s peque˜ os. Chris Mason (el autor de las Colas de Mercurial). el tiempo para introducir todos los parches. se logr´ en menos de dos a a o minutos. que contaba con 1. los parches u u se contar´ n desde cero. a e Puede identificar un parche destino con el nombre del parche o con el n´ mero. a ı 151 . Cuando emplee “hg qpop” con un destino. Neil Brown.7. Manejo de descartes Si “hg qpush” falla al aplicar un parche.) Apliqu´ “hg qrefresh” sobre uno de los parches m´ s grandes (que hizo 22. el tiempo de esta revisi´ n puede ser m´nimo.5. ı De hecho.rej.

haga “hg qpush -a” sobre todos los parches que usted sepa se aplican limpiamente. a u foo.) e 4.12.N ” a o “hg strip”. e 152 .hg/patches. mientras que bar. por ejemplo se pasa el nombre foo. Si su pila de parches toca c´ digo que es modificado frecuentemente o de forma e o invasiva sobre el c´ digo subyacente. MQ puede usar esta informaci´ n para ayudarle a a resolver conflictos entre sus o parches y una revisi´ n distinta. y guarda los estados de los ficheros series y o status. Para hacerlo m´ s corto. o Cuando termine de resolver los efectos de un parche.patch-2 significa “dos parches antes de foo.patch”. vea m´ s a adelante por qu´ .N una vez que est´ seguro de que no lo necesita m´ s como copia de e a seguridad. Guarde una copia de seguridad de su directorio de parches con “hg qsave -e -c”.hg/patches. por ejemplo. MQ consulta la cola que usted guard´ con “hg qsave”. o 5. 12. por lo tanto puede mostrar o una herramienta de fusi´ n GUI para ayudarle a resolver los problemas. necesitar´ sincronizarse con el c´ digo. y ajustar cualquier trozo o a a o en sus parches que ya no est´ n al d´a. MQ refrescar´ su parche basado en el resultado de la fusi´ n. despu´ s hacer “hg pull” de los cambios ı a e en el repositorio. Tambi´ n consigna un “conjunto de cambios de seguridad” n e sobre sus parches aplicados. Es obvio hacerlo por el e u nombre.N . y aplica una fusi´ n de tres o o con el correspondiente conjunto de cambios. Guardar´ los parches en un directorio llamado a .patch+4 significa “cuatro parches despu´ s de bar. Actualice a la nueva revisi´ n punta con “hg update -C” para sobreescribir los parches que haya introducido. que introducir´ los parches hasta que foo. MQ dejar´ de de introducir parches a siempre que llegue a un parche que no se pueda aplicar debido a un conflicto.9. Identificar parches ´ Las ordenes de MQ le permiten trabajar refiri´ ndose al nombre del parche o al n´ mero. esto es para mantener el hist´ rico.patch a se aplique. 3. La opci´ n -m de “hg qpush” le indica a MQ que haga una o fusi´ n que involucra tres fuentes si el parche falla al aplicarse.hg/patches. Si sus parches se aplican limpiamente sobre algunas revisiones del repositorio subyacente. o El proceso resulta un poco complejo: 1. Puede eliminar la cabeza extra con “hg qpop -a -n patches. Esta aproximaci´ n es sencilla y funciona bien si no espera cambios en el c´ digo original que afecte en gran medida o o los parches que usted est´ aplicando. 2. arreglar trozos manualmente se vuelve desgastante. y finalmente hacer “hg qpush -a” con sus parches de nuevo. Para comenzar. Esta fusi´ n usa la maquinaria de Mercurial. Si un parche se aplica difusamente o se niea a aplicarse. Si est´ trabau a jando en cambios de c´ digo de otros. su repositorio tendr´ una cabeza extra de la antigua cola de parches. o Durante el “hg qpush -m”. y una copia de la a cola de parches anterio estar´ en . puede referirse a un parche con un nombre y un corrimiento de n´ mero. Use “hg pull” para traer los nuevos cambios en el repositorio subyacente.patch”. Esto imprime el nombre del directorio en el cual se han guardado los parches. (No ejecute “hg pull -u”.patch a “hg qpush”. Actualiar los parches cuando el c´ digo cambia o Es com´ n contar con una pila de parches sobre un repositorio que usted no modifica directamente. e ı La v´a m´ s sencilla de hacerlo es con “hg qpop -a” sobre sus parches. permiti´ ndole a usted arreglarlo. o en una caracter´stica que tarda bastante en desarrollarse comparada con la tasa o ı de cambio del c´ digo sobre la cual se est´ trabajando. Fusione todos los parches con “hg qpush -m -a”. Puede eliminar . o Es posible automatizar de forma parcial el proceso de rebase. donde N es un entero peque˜ o. aplicar e “hg qrefresh” al parche afectado y continuar introduciendo hasta que haya arreglado la pila completa. a o Al final de este proceso.8.N . cada parche en el fichero series se aplica normalmente. A esto se le llama hacer rebase a su serie de parches.

1.) e o ´ ¿Desea ver todos los parches desde que se aplic´ foo.14 muestra algunos comandos usuales de Mercurial al trabajar con parches. es el primero en los sistemas que comienzan su conteo en cero). usualmente con la salida normal. Adicionalmente.10. El primer parche que se imprime en la salida de “hg ı qseries” es el parche cero (si. a 12. parecer´ que ha sido exitoso. Otra consecuencia deseable al representar los nombres de parches como etiquetas es que cuando ejecute la orden “hg log”. Puede ser una forma util de trabajar. pero de los ı cuales es bueno estar enterado. o o e No es una buena idea aplicar “hg merge” de cambios de otra rama con un conjunto de cambios de parches. Si intenta hacerlo. desplegar´ el nombre del parche como una etiqueta.13 para obtener informaci´ n del por qu´ de esto.patch:qtip subdir Dado que MQ nombra los parches disponibles al resto de Mercurial con su maquinaria de etiquetas interna. Junto con las capacidades de Mercurial para etiquetar. Cada comando que acepte Identifia cadores de conjuntos de cambios tambi´ n aceptar´ el nombre de un parche aplicado. respectivamente. Otra informaci´ n util o ´ Hay una cantidad de aspectos que hacen que el uso de MQ no representen secciones en s´ mismas. Administrar parches en un repositorio Dado que el directorio .hg/patches de MQ reside fuera del repositorio de trabajo de Mercurial. por lo menos si desea mantener la “informaci´ n de parches” de ese conjunto de cambios y los conjuntos de cambios o que se encuentran por debajo en la pila de parches. puede trabajar en un parche por un rato. Tengo una copia original de las fuentes del ı u 153 . Los presentamos en aqu´: ı Usualmente cuando hace “hg qpop” a un parche y vuelve a hacerle “hg qpush”.patch sobre los ficheros de un subdirectorio en su arbol? o 1 hg log -r foo. o Puede tambi´ n compartir diferentes versiones de la misma pila de parches entre varios repositorios subyacentes.11. las etiquetas especiales qbase ´ y qtip identifican los parches “primero” y ultimo. el conjunto de cambios que representa el parche despu´ s de introducir/sustraer tendr´ una identidad distinta que aquella que representaba el e a conjunto de cambios anteriormente. usted no necesita teclear el nombre completo de un parche cuando desea identificarlo por su nombre.4.Referirse a un parche por su ´ndice no es muy diferente. 12. Esto le permite “devolverse” a esa e versi´ n del parche posteriormente. Esto facilita distinguir a visualmente los parches aplicados de las revisiones “normales”. Consulte la seccti´ n B. estas adiciones hacen que trabajar con parches sea muy sencillo. el repositorio “subyacente” de Mercurial no sabe nada acerca de la administraci´ n o presencia de parches. La figura 12. MQ aumenta las etiquetas nore a malmente en el repositorio con un distintivo para cada parche aplicado. ı ´ MQ facilita el trabajo cuando est´ usando ordenes normales de Mercurial. Por ejemplo. e Uso esto cuando estoy desarrollando una caracter´stica del n´ cleo Linux. pero MQ se a confundir´ . ´ ¿Desea enviar una bomba de parches a una lista de correo con los ultimos cambios que ha hecho? 1 hg email qbase:qtip (¿No sabe qu´ es una “bomba de parches”? Consulte la secci´ n 14. el segundo parche es uno y as´ sucesivamente. o Esto presenta la interesante posibilidad de administrar los contenidos del directorio de parches como un repositorio ´ de Mercurial por su cuenta. hacerle “hg qrefresh” y despu´ s hacer “hg commit” al estado actual del parche.

patch changeset: tag: tag: tag: user: date: summary: 2:c836697fbf55 qtip second. Soporte de MQ para repositorios de parches MQ le ayuda a trabajar con el directorio .com> date: Tue Feb 10 18:23:26 2009 +0000 summary: [mq]: first.11.1 @@ +double u.patch tag: qbase user: Bryan O’Sullivan <bos@serpentine.patch $ hg export second. puede pasarle la opci´ n -c para que se cree el directorio .14: Uso de las caracter´sticas de etiquetamiento al trabajar con MQ ı n´ cleo para varias arquitecturas.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 $ hg qapplied first.0 +1. 12.c --. 154 .c Tue Feb 10 18:23:26 2009 +0000 @@ -0.patch $ hg log -r qbase:qtip changeset: 1:b3508ccf62ad tag: first. Figura 12. u Llevar los parches en un repositorio permite que varios desarrolladores puedan trabajar en la misma serie de parches sin sobreponerse. y clon´ un rpositorio en cada una que contiene los parches en los cuales estoy trabau e jando. Cuando quiero probar un cambio en una arquitectura diferente.1.patch tip Bryan O’Sullivan <bos@serpentine.hg/patches como un repositorio.patch diff -r b3508ccf62ad -r c836697fbf55 other.patch second. armo y pruebo el n´ cleo./dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/other.patch # HG changeset patch # User Bryan O’Sullivan <bos@serpentine.hg/patches o como un repositorio de Mercurial. cuando usted prepara un repositorio para trabajar con parches usando “hg qinit”. sustraigo e introduzco todos mis parches.com> Tue Feb 10 18:23:26 2009 +0000 [mq]: second.com> # Date 1234290206 0 # Node ID c836697fbf55654f972d867359527813dbbc5d44 # Parent b3508ccf62adb8916c6a7b64105642fa516f5a90 [mq]: second. todo sobre la fuente base subyacente que pueden o no controlar. introduzco mis parches actuales al repositorio ´ de parches asociado con el arbol del kernel.

e De nombres descriptivos a sus parches. No olvide a˜ adir una entrada en el n fichero status del fichero . puede usar t´ cnicas sencillas para mantener su trabajo bien organizado.) e El paquete patchutils [Wau] es invaluable.Nota: Si olvida usar la opci´ n -c option. que ejecuta “hg commit” en el directorio . Si olvida hacerlo. e La orden diffstat [Dic] genera un histograma de modificaciones hechas a cada fichero en un parche. Por ejemplo. a a Los nombres adecuados son especialmente importantes cuando tiene bastantes parches con los cuales trabajar. o o 12. en sistemas Linux con el int´ rprete bash.2. tendr´ que aplicar “hg qpop -a” y despu´ s “hg a e qpush -a” en el repositorio subyacente para que los cambios se reflejen all´. MQ nota convenientemente que el directorio . har´ “hg add” autom´ ticamente a a a cada parche que usted cree e importe. puede ir al directorio . una unica invocaci´ n de filterdiff puede generear un parche m´ s peque˜ o que solamente o a n toca aquellos ficheros con un patr´ n. puesto que de otra forma intentar´ hacer cosas o a inteligentes con prefijos de ficheros que terminan confundi´ ndome. a o o 6 N.11. del T. puede incluir el siguiente recorte de c´ digo6 en su fichero e o ˜/.hg/patches o en cualquier momento y ejecutar “hg init”. “hg qcommit”. o hace “hg update” a los parches o el fichero series. o en una serie que desea tratar como un conjunto de cambios regular.bashrc.hg/patches es un repositorio. Otras herramientas para trabajar con parches Cuando haya trabajado por cierto tiempo con parches. Detalles a tener en cuenta El soporte de MQ para trabajar con un repositorio de parches es limitado en ciertos aspectos: MQ no puede detectar autom´ ticamente los cambios que haga al directorio de parches. dado un parche que modifica centenas de ficheros en ´ docenas de directorios. snippet 155 .2.hgignore. ı porque da de forma inmediata una pista del prop´ sito del parche. usted seguro no quiere administrar el fichero a status. edita a manualmente. puede confundir a MQ ı en cuanto a qu´ parches se han aplicado. y cu´ ntos cambios introduce a cada fichero y e a en total. cada una hace una cosa muy bien hecha a un parche. MQ provee una orden corta. e 12. 1 alias mq=‘hg -R $(hg root)/. La orden patchutils que m´ s uso es filterdiff. para administrar convenientemente el directorio de parches. Lo que ahorra tecleo recurrente. Puede ver otro ejemplo en la secci´ n 13.hg/patches’ ´ Puede aplicar las ordenes de la forma “mq pull” al repositorio principal. pero estar´ ejecutando regularmente ordenes como “hg qapplied” y “hg qtop”.9. Un buen nombre para un parche podr´a ser rework-device-alloc. Los nombres largos no deben ser un problema. o si est´ trabajando en diferentes tareas y sus parches toman solamente una porci´ n de su atenci´ n. (Me ha parecido interesante usar la opci´ n -p de diffstat. a pesar de que (“hg qinit -c” hace estodo de forma autom´ tica para usted).12. Provee una interesante forma de “dar un vistazo” al parche—qu´ ficheros afecta. Por ejemplo. Provee un conjunto de peque˜ as utilidades que siguen la “filosof´a n ı Unix”.patch.13. no o ´ los estar´ tecleando repetidamente. Si aplica “hg pull”. Buenas pr´ cticas de trabajo con parches a En caso de que est´ trabajando en una serie de parches para enviar a un proyecto de software libre o de fuentes e abiertas. Finalmente. desear´ herramientas que le ayuden a entender y manipular a los parches con los que est´ tratando. 12. cuando haya terminado. a que extrae subconjuntos de un fichero de parche.hg/patches. puede definir el alias mq en sistemas Unix.

12. Use la orden “hg qtop” para dar un vistazo al texto de sus parches e a frecuentemente—por ejemplo.5 netplug 156 . hg clone netplug-1.c | 22 ++++++---------------drivers/scsi/libata-scsi. particularmente diffstat y filterdiff.opt_mode) kfree(drv_info.c | 3 +-drivers/net/fs_enet/fs_enet-mii.bz2 tar jxf netplug-1. En distintas oportunidades o a me sucedi´ que apliqu´ “hg qrefresh” a un parche distinto al que deseaba hacerlo.c | 5 ++--drivers/char/hvcs.c @@ -743. y volverlo en un repositorio de Mercurial: 1 2 3 4 5 6 7 $ $ $ $ $ $ $ download netplug-1. + } module_init(au1100fb_init). tiene bastante sentido administrar parches de esta forma incluso si desea hacer algunos cambios al paquete de ficheros que descarg´ . 38 deletions(-) $ filterdiff -i ’*/video/*’ remove-redundant-null-checks.8 +743. y usualmente es complejo migrar o e los cambios al parche correcto despu´ s de haberlo hecho mal.2. mientras que la segunda permite seleccionar trozos de un parche para colocarlos en otro.c˜remove-redundant-null-checks-before-free-in-drivers +++ a/drivers/video/au1100fb. Recetas de MQ Administrar parches “triviales” Puesto que colocar ficheros en un repositorio de Mercurial es tan sencillo.12.c | 3 +-8 files changed.2.2.5.a/drivers/video/au1100fb.patch --.1.c | 4 +--drivers/video/au1100fb.5 hg init hg commit -q --addremove --message netplug-1.tar. La primera le dar´ una idea de qu´ cambios est´ haciendo o a e a su parche. 12. y lsdiff Tenga en cuenta en qu´ parche est´ trabajando.14.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $ diffstat -p1 remove-redundant-null-checks. use “hg tip -p”)—para asegurarse en d´ nde est´ ubicado.2.c | 3 +-drivers/net/wireless/ipw2200.c | 11 +++++-----drivers/message/fusion/mptfc. vale la pena invertir ese poco tiempo para aprender c´ mo usar otras herramientas que describ´ en o ı la secci´ n 12.5 cd . e Por este motivo. 19 insertions(+).7 @@ void __exit au1100fb_cleanup(void) { driver_unregister(&au1100fb_driver).c | 6 ++---drivers/message/fusion/mptsas.15: Las ordenes diffstat. o Para comenzar a descargar y desempaqueter un paquete de ficheros.patch drivers/char/agp/sgi-agp.. ´ Figura 12.opt_mode).tar.opt_mode). if (drv_info.14. kfree(drv_info. filterdiff.2.bz2 cd netplug-1.5.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 $ cd netplug $ hg qinit $ hg qnew -m ’fix build problem with gcc 4’ build-fix.c Tue Feb 10 18:23:26 2009 +0000 @@ -275.c --.com> date: Tue Feb 10 18:23:26 2009 +0000 summary: fix build problem with gcc 4 diff -r ca53495653b5 -r 4adf6cb9cc16 netlink.2. $ tar jxf netplug-1. 1 2 3 4 5 6 7 8 9 10 11 12 13 $ hg qpop -a Patch queue now empty $ cd . "Could not get socket details: %m").8.. Primero se traen sus o cambios al repositorio.c $ hg qrefresh $ hg tip -p changeset: 1:4adf6cb9cc16 tag: qtip tag: build-fix.a/netlink. $ download netplug-1.8 $ hg locate -0 | xargs -0 rm $ cd .8.tar.2.2.8 updating working directory 18 files updated.2. 0 files merged.patch tag: tip tag: qbase user: Bryan O’Sullivan <bos@serpentine. 0 files unresolved $ cd netplug-1.bz2 $ hg clone netplug-1. o a 157 . socklen_t addr_len = sizeof(addr).2.patch $ perl -pi -e ’s/int addr_len/socklen_t addr_len/’ netlink. (struct sockaddr *) &addr.tar.7 @@ exit(1). 0 files merged. if (getsockname(fd.5 netplug-1. 0 files removed.bz2 $ cd netplug-1. 0 files removed.8 La porci´ n que comienza con “hg locate” mostrada m´ s arriba. y el autor del paquete libera una nueva versi´ n.2.c Tue Feb 10 18:23:26 2009 +0000 +++ b/netlink. 0 files unresolved Continue creando una pila de parches y haga sus cambios. borra todos los ficheros en el directorio de trabajo.7 +275.8 9 updating working directory 18 files updated. Digamos que pasan unas semanas o meses. } + int addr_len = sizeof(addr).8 $ hg commit --addremove --message netplug-1. &addr_len) == -1) { do_log(LOG_ERR..2.

2. y despu´ s a e bar. Use “lsdiff -nvv” para imprimir algunos a metadatos del parche. e integra “hg qfold” ´ bar y quux en el.c 71 Hunk #1 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc. Usualmente no necesitar´ modificar el parche del cu´ l ha fusionado los cambios. fold 158 . el trabajo es un poco m´ s enredado. del T. en el orden que especifique. puede aplicar sus parches encima del nuevo arbol de fuentes 1 2 3 4 5 6 7 8 9 10 11 12 13 $ cd . y puede sencillamente aplicar “hg qrefresh” para eliminar los trozos replicados. 12.14../netplug-1. en el ultimo parche aplicado. Se “integran”7 los parches que ust´ ed nombre.patch Now at: build-fix. MQ reportar´ que hay unos trozos a a a que se han desechado cuando usted aplique “hg qpush” (de los trozos que haya movido al otro parche).c 24 Hunk #1 static int __devinit agp_sgi_init(void) 37 File #2 a/drivers/char/hvcs. Combinar parches completos MQ provee la orden “hg qfold” que le permite combinar parches enteros.2. Si tiene un parche que tiene varios trozos que modifican un fichero. seguido de quux. Si el parche ultimamente aplicado es foo./netplug-1.as´ que la opci´ n --addremove de “hg commit” puede indicar qu´ ficheros se han eliminado en la nueva versi´ n del ı o e o ´ arbol de fuentes. o a ´ El orden en el que integre los parches importa.8 pulling from .c 39 Hunk #1 static struct tty_operations hvcs_ops = 53 Hunk #2 static int hvcs_alloc_index_list(int n) 69 File #3 a/drivers/message/fusion/mptfc..c 87 Hunk #1 mptsas_probe_hba_phys(MPT_ADAPTER *ioc) 98 File #5 a/drivers/net/fs_enet/fs_enet-mii.patch 22 File #1 a/drivers/char/agp/sgi-agp. Deber´ sustraer los cambios para poder integrarlos.c 7 N..2.8 searching for changes adding changesets adding manifests adding file changes added 1 changesets with 12 changes to 12 files (run ’hg update’ to get a working copy) $ hg qpush -a (working directory not at tip) applying build-fix. in 85 File #4 a/drivers/message/fusion/mptsas. terminar´ con un parche que tiene el mismo efecto que si hubiera aplicado primero foo./netplug $ hg pull . ´ Finalmente.3.patch 12. y concatena sus descripciones al final de su descripci´ n. pero puede automatizarlo parcialmente. Fusionar una porci´ n de un parche dentro de otro o Fusionar partes de un parche dentro de otro es m´ s complejo que combinar completamente dos parches. En cambio.14. y desea mover solamente unos de ellos. a Si desea mover cambios de ficheros completos. 1 2 3 4 5 6 7 8 9 10 11 $ lsdiff -nvv remove-redundant-null-checks. puede usar las opciones filterdiff’s -i y -x para elegir las modificaciones remover de un parche. concatenar su salida al final del parche donde desea fusionarlo.

159 .12 13 14 15 16 17 18 19 20 21 111 164 178 100 Hunk #1 File #6 113 Hunk #1 126 Hunk #2 140 Hunk #3 150 Hunk #4 File #7 166 Hunk #1 File #8 180 Hunk #1 static struct fs_enet_mii_bus *create_bu a/drivers/net/wireless/ipw2200. que realmente son las ordenes “hg add” y “hg remove” de Mercurial.14.c void __exit au1100fb_cleanup(void) Esta orden imprime tres clases diferentes de n´ meros: u (en la primera columna) un n´ mero de fichero para identificar cada fichero modificado en el parche. indentado) el n´ mero de l´nea dentro de un fichero modificado donde comienza el trozo. a o u pero puede pasar posteriormente a las opciones --files y --hunks de filterdiff. y leer el parche para identificar los n´ meros de fichero y trozo que desea. o Debe haber notado que la mayor´a de comandos de quilt tienen su contraparte en MQ. o 12. Cuando tenga el trozo.c int ata_cmd_ioctl(struct scsi_device *sc a/drivers/video/au1100fb. Las excepciones son las ordenes add y remove de quilt. puede concatenarlo al final de su parche objetivo y continuar como en la secci´ n 12.2. No hay un equivalente en MQ para la orden edit de quilt. que simplemente comienzan ı ´ ´ con “q”. u (En la siguiente l´nea. ı u ı y (en la misma l´nea) un n´ mero de trozo que identifica el trozo. Hay algunas diferencias en c´ mo funcionan. para seleccionar exactamente el fichero y el trozo que desea extraer. MQ provee un conjunto similar de ordenes.15. ı u Tendr´ que hacer una inspecci´ n visual.c static struct ipw_fw_error *ipw_alloc_er static ssize_t clear_error(struct device static void ipw_irq_tasklet(struct ipw_p static void ipw_pci_remove(struct pci_de a/drivers/scsi/libata-scsi. Diferencias entre quilt y MQ ´ Si le es familiar quilt.

En este cap´tulo. Aproximaciones tentadoras que no funcionan adecuadamente Hay dos maneras est´ ndar de mantener una porci´ n de software que debe funcionar en muchos entornos diferentes. El controlador en cuesti´ n es grande (al menos en lo que se refiere a o controladores). y nunca ha sido estable internamente. Esto significa que una versi´ n del controlador que funciona bien con una a o versi´ n particular del kernel ni siquiera compilar´ correctamente contra. y sobre la que usted necesita hacer un mont´ n de desarrollo. Aunque mucho del material en este cap´tulo es espec´fico de Linux.) Finalmente. En este caso el mantenimiento del c´ digo o es compartido parcialmente por otros desarrolladores en la comunidad del kernel.1. tener algo de disciplina junto con a a algunas de las capacidadees menos usadas de MQ hace posible trabajar en entornos de desarrollo complejos. as´ que podemos entregar ı nuevas caracter´sticas a los clientes sin forzarlos a actualizar kernels completos o distribuciones. y luego propagarse a cada repositorio de backport. a o ´ La primera es mantener varias ramas. los mismos principios aplican a cualquier base ı ı de c´ digo de la que usted no sea el propietario principal. quienes hacen modificaciones “de-af´ n” al controlador a medida que desarrollan y refinan subsistemas en el kernel. t´picamente. El problema de esta aproximaci´ n o es que usted debe tener una disciplina f´ rrea con el flujo de cambios entre repositorios. usar´ como ejemplo una t´ cnica que he usado para administrar el desarrollo de un controlador de ı e e dispositivo Infiniband para el kernel de Linux.Cap´tulo 13 ı Usos avanzados de las Colas de Mercurial Auunque es f´ cil aprender los usos m´ s directos de las Colas de Mercurial. a 160 .1. a Tambi´ n mantenemos algunos “backports” para versiones antiguas del kernel de Linux. debemos tener en cuenta una buena cantidad de versiones de Linux en mente. ´ El problema de multiples objetivos El kernel de Linux cambia con rapidez. cualquier otra versi´ n. o o 13. para dar soporte a e las necesidades de los clientes que est´ n corriendo versiones antiguas de Linux que no incorporan nuestros a controladores. Es mantenido por un equipo peque˜ o de ı o n desarrolladores. con 25. o a ı o Para mantener un controlador. nosotros liberamos nuestro software de acuerdo a un cronograma que no necesariamente est´ alina eado con el que usan los distribuidores de Linux y los desarrolladores del kernel. Una nueva caracter´stica o un e ı arreglo de fallo deben empezar su vida en un repositorio “pr´stino”. ı 13.000 l´neas de c´ digo esparcidas en 35 ficheros fuente. ´ Un objetivo es el arbol de desarrollo principal del kernel de Linux. los desarrolladores hacen cambios dr´ sticos entre versiones frecuentemente. (Hacer el backport de un pedazo de c´ digo es modificarlo para que trabaje en una versi´ n de su o o entorno objetivo anterior a aquella para la cual fue escrito. cada una pensada para un unico entorno. ı Los cambios para backports est´ n m´ s limitados respecto a las ramas a las que deber´an propagarse. un cambio para a a ı backport que es aplicado a una rama en la que no corresponde probablemente har´ que el controlador no compile.1.

La idea detr´ s de la aplicaci´ n condicional es que usted puede “etiquetar” un parche con un guardia. Controlar los guardias de un parche El comando “hg qguard” le permite determinar qu´ guardias deben aplicarse a un parche. Ya que estos “ifdefs” no est´ n permitidos en el arbol del kernel de Linux. MQ tiene unas cuantas caracter´sticas adicionales que hacen el ı trabajo m´ s agradable. Para empezar. 1 2 3 4 5 6 7 8 9 $ $ $ $ $ $ $ $ $ hg qinit hg qnew hello. o mostrar los guardias e que est´ n en efecto. cada uno es positivo (“aplique el parche si este guardia es seleccionado”) o negativo (“omita este parche si este guardia es seleccionado”). a 13.patch echo goodbye > goodbye hg add goodbye hg qrefresh Esto nos brinda un peque˜ o repositorio que contiene dos parches que no tienen ninguna dependencia respecto al otro. Un parche sin guardias siempre es aplicado. o a ´ debe seguirse alg´ n proceso manual o autom´ tico para eliminarlos y producir un arbol limpio. Una base de c´ digo u a o mantenida de esta manera se convierte r´ pidamente en un nido de ratas de bloques condicionales que son dif´ciles de a ı entender y mantener. Estos enfoques tienen la debilidad adicional de dificultar la generaci´ n de parches bien formados para enviarlos a o la versi´ n oficial. Aunque este es de hecho el caso. u omitir´ . que sima o plemente es una cadena de texto de su elecci´ n. Ninguno de estos enfoques es adecuado para situaciones en las que usted no es “due˜ o” de la copia can´ nica n o ´ ´ de un arbol de fuentes.2.patch echo hello > hello hg add hello hg qrefresh hg qnew goodbye. En el caso de un controlador de Linux que es distribuido con el kernel est´ ndar. o En principio. sin que yo siquiera me entere de ello hasta despu´ s de e ´ que los cambios aparecen en el arbol de Linus. MQ provee una caracter´stica llamada “guardias” (que se origina del comando guards o ı ´ de Quilt) que hace precisamente esto.´ ´ La segunda es mantener un unico arbol de c´ digo fuente lleno de declaraciones que activen o desactiven secciones o ´ de c´ digo dependiendo del entorno objetivo. Sin ning´ n argumento. un parche vigilado. las Colas de Mercurial parecen ser un buen candidato para administrar un escenario de desarrollo como el de arriba. creemos un repositorio sencillo para experimentar.patch: unguarded 161 . 1 2 $ hg qguard goodbye. 13. el comando muestra los guardias del parche actual de la parte m´ s alta de a u a la pila. MQ entonces aplicar´ . Aplicar parches condicionalmente mediante guardias Tal vez la mejor manera de conservar la cordura con tantos entornos objetivo es poder escoger parches espec´ficos ı para aplicar para cada situaci´ n. La versi´ n oficial de “mi” o a o o controlador puede ser modificada por gente que no conozco. n porque tocan ficheros diferentes. el arbol de a Linux contiene la copia del c´ digo que ser´ considerada por el mundo como la can´ nica. dependiendo de los guardias que usted a a haya seleccionado.3. y luego decirle a MQ que seleccione guardias espec´ficos para usar o ı cuando aplique parches. Un parche puede tener una cantidad arbitraria de guardias.

1 2 3 4 $ hg qpush -a applying hello. no los modifica. usted no tiene que usar el comando “hg qguard” si no lo desea.patch 162 .patch: -quux Nota: El comando “hg qguard” pone los guardias en un parche.hg/patches/series hello.4. unapplied patches has changed from 1 to 2 $ hg qselect foo Si est´ interesado.Para poner un guardia positivo en un parche.patch applying goodbye. el comando “hg qselect” lista los guardias en efecto actualmente.patch Now at: goodbye.patch #+foo 13. El efecto de esto es e a determinar qu´ parches aplicar´ MQ la pr´ xima vez que usted ejecute “hg qpush”. los guardias seleccionados actualmente est´ n almacenados en el fichero guards. uno por cada l´nea de salida. est´ bien a simplemente editar el fichero series) 1 2 3 $ cat .patch hello. prefije el nombre del guardia con un “+”. Esto significa que si usted ejecuta “hg qguard +a +b” sobre un parche.hg/patches/guards foo Podemos ver el efecto que tienen los guardias seleccionados cuando ejecutamos “hg qpush”. prefije el nombre del guardia con un “-”. 1 2 3 $ hg qguard hello. y luego ´ “hg qguard +c” en el mismo parche. (En otras palabras.patch #-quux goodbye. el unico guardia sobre el parche despu´ s del e comando ser´ +c. No tiene ning´ n otro efecto.patch -quux $ hg qguard hello. Selecccionar los guardias a usar El comando “hg qselect” determina qu´ guardias est´ n activos en cualquier momento. la forma en que son almacenados es f´ cil tanto de entender a como de editar a mano. ı Cada argumento es tratado como el nombre de un guardia a aplicar. no hace nada a los parches que ya han sido aplicados. 1 2 3 $ hg qguard +foo $ hg qguard goodbye. en e a o u particular. 1 2 3 4 5 6 7 8 $ hg qpop -a Patch queue now empty $ hg qselect no active guards $ hg qselect foo number of unguarded. a a 1 2 $ cat . Sin argumentos. a Mercurial almacena los guardias en el fichero series.patch: +foo Para poner un guardia negativo en un parche.

Cuando tomo la instant´ nea. Este repositorio tiene un 1 % del tama˜ o del repositorio n ´ del kernel. Un parche sin guardias es aplicado siempre.patch 13. por lo que es m´ s f´ cil trabajar con el. Podar el entorno de trabajo ´ En el trabajo del controlador de dispositivo que mencion´ anteriormente. unapplied patches has changed from 0 to 2 $ hg qpop -a no patches applied $ hg qpush -a applying hello. pero ninguno corresponde con cualquiera de los guardias seleccionados. a a ´ Luego escojo una versi´ n “base” sobre la cual son aplicados los parches. Si el parche tiene alg´ n guardia positivo que corresponda con cualquiera de los guardias seleccionados. 1 2 3 4 5 6 7 8 $ hg qselect foo bar number of unguarded. applied patches has changed from 0 to 2 $ hg qpop -a Patch queue now empty $ hg qpush -a patch series already fully applied Usted puede ver en el ejemplo de abajo que los guardias negativos tienen precedencia sobre los guardias positivos. n 163 .patch applying goodbye.5.6. yo no aplico los parches a un arbol e normal del kernel de Linux. El nombre del guardia no debe contener espacios en blanco. puedo aplicar mis parches sobre mi peque˜ o repositorio o sobre un arbol normal del kernel.patch Now at: goodbye. Reglas de MQ para aplicar parches Las reglas que MQ usa para decidir si debe aplicar un parche son las siguientes. Si usted trata de usar un guardia con un nombre inv´ lido. se salta el parche. uso un repositorio que s´ lo contiene una instant´ nea de los ficheros fuente y o a de cabecera que son relevantes para el desarrollo de Infiniband. 1 2 3 4 5 6 $ hg qselect quux number of guarded.Un guardia no puede empezar con un caracter “+” o “-”. En cambio. pero muchos otros caracteres son aceptables. se salta u el parche. Es una instant´ nea del arbol del kernel o a de Linux en una revisi´ n de mi elecci´ n. Si el parche tiene alg´ n guardia negativo que corresponda con cualquiera de los guardias seleccionados. MQ se a quejar´ : a 1 2 $ hg qselect +foo abort: guard ’+foo’ starts with invalid character: ’+’ Cambiar los guardias seleccionados cambia los parches que son aplicados. almaceno el ID de conjunto de cambios en el o o a ´ mensaje de consignaci´ n. Si el parche tiene guardias positivos o negativos. se aplica u el parche. Ya que la instant´ nea preserva la “forma” y el contenido de las partes relevantes del arbol o a ´ del kernel. 13.

e e El grupo “aceptado”. pero que ya est´ n terminados. El orden de los grupos es importante. o 13. Si el solicita que modificaciones en alguno de ellos. El grupo “pendiente”. no necesito habilitar ning´ n guardia para obtener un arbol de fuentes u razonablemente seguro. Parches que adaptan el arbol de fuentes a versiones antiguas del arbol del kernel. Parches que por alguna raz´ n nunca deben ser enviados al mantenedor oficial del kernel. los mover´ al principio e e del grupo “revisar”. y no deber´an ser enviados a ninguna a ı parte a´ n. Yo habilito este guardia la mayor´a de las veces.´ ´ Normalmente. alguno de esos parches podr´a cambiar las cadenas de identificaci´ n embebidas del controlador ı o para hacer m´ s f´ cil la distinci´ n. a o ´ Tambi´ n desear´amos que los parches que sabemos que debemos modificar sean aplicados sobre un arbol de fuentes e ı que se parezca al oficial tanto como sea posible. entre una versi´ n del controlador de salida-del-´ rbol y a a o o a una versi´ n entregada por un vendedor de alguna distribuci´ n. pero que no est´ n presentes en la instant´ nea en la cual est´ basada el repositorio a a a ´ ´ peque˜ o. Parches que no he enviado al mantenedor oficial. Parches que est´ n siendo activamente desarrollados. Si estoy aplicando la pila a ´ ´ de parches a una copia del arbol oficial. el arbol base sobre el que se aplican los parches deber´a ser una instant´ nea de un arbol de desarrollo ı a ´ muy reciente. a Los parches que est´ n “terminados”. 13. no tienen guardias. Los parches de backport deben ser aplicados encima de todos los otros parches. o La secuencia de grupos de parches que mantengo se muestra a continuaci´ n.7. y que el ha aceptado. 164 . presentes unicamente para transformar el arbol en un estado n o similar al del repositorio del mantenedor oficial. pero sobre los que que el mantenedor oficial ha solicitado modificaciones antes de aceptarlos. uso varios guardias para controlar qu´ parches deben ser aplicados. Cada secci´ n de parches similares o o empieza con un bloque de comentarios que describen el prop´ sito de los parches que le siguen. Cuando ı ´ aplico los parches sobre un arbol donde los parches ya est´ n presentes. Estos son parches de “s´ lo lectura”. o explicar´ porqu´ luego de que presente los grupos. El grupo “en proceso”. Los parches “backport” y “no enviar” flotan al final del fichero series. Si el mantenedor oficial los acepta cuando los env´e. los a o ı ´ mover´ al final del grupo “aceptado”. e Los parches “aceptados” son vigilados con accepted. Esto facilita mucho el desarrollo de parches que puedan ser enviados al arbol oficial con pocas o ninguna modificaci´ n. Parches que yo he enviado. Dividir el fichero series Yo categorizo los parches en el fichero series en una serie de grupos l´ gicos. Es por esto que mantenemos los parches aceptados disponibles por una buena cantidad de tiempo. Mantener la serie de parches En mi trabajo. y los a parches que lo siguen se aplicar´ n sin problemas. Son parches que el equipo de desarrollo ha enviado al mantenedor del subsistema Infini´ band. Quisi´ ramos que los parches del e fondo de la pila sean tan estables como sea posible. Estos a parches ser´ n de “s´ lo lectura” por un buen tiempo.8. para no tener que revisar parches m´ s arriba debido a cambios de a contexto. u ´ ´ El grupo “backport”. puedo desactivar este parche. en pruebas de campo. El grupo “no enviar”. y los parches “no enviar” pueden perfectamente quedarse fuera del camino. El grupo “revisar”. o Por ejemplo. Poner los parches que nunca cambiar´ n en el primer lugar del fichero series sirve a este prop´ sito. o o Ahora volvemos a las razones para ordenar los grupos de parches en esta manera. pero no han sido enviados.

2.1. o a ´ La variedad de guardias me brinda una flexibilidad considerable para determinar qu´ tipo de arbol de fuentes acabar´ por e e obtener. Al usarlo en dos versiones del mismo diff. que muestra las diferencias entre dos diffs como un diff. o 13. usted puede almacenarlos en diferentes ı o directorios si lo desea. aparte de los parches “regulares” cuyos efectos son modificados por ellos. cada uno de ellos ı haciendo cambios incondicionales. usted necesitar´ un paquete de un tercero llamado a ´ patchutils [Wau]. Para hacer esto. o Usted puede habilitar la extensi´ n extdiff de la manera usual.1. la selecci´ n de guardias apropiados es automatizada durante el proceso de ı o compilaci´ n.9. escriba varios parches. escribir un parche de backport es un proceso simple.9. a ı u tengo un repositorio de parches que contiene m´ s de 250 parches. que es provisto junto con Mercurial. a Si usted puede agrupar estos parches en categor´as l´ gicas separadas. como se discuti´ en la secci´ n 12. Este paquete provee un comando llamado interdiff. Esto es debido en parte a que usted est´ mirando la segunda derivada a del c´ digo real (el diff de un diff). MQ no tiene problemas manejando nombres de parches que contienen separadores de ruta. para convertir un diff o de dos versiones de un parche en algo legible. Si lo hace. notar´ r´ pidamente que usar el comando “hg diff” o o a a para mirar el historial del repositorio no es viable.8.11. Sin embargo. Ver el historial de un parche Si usted est´ desarrollando un conjunto de parches en un per´odo de tiempo grande.9.6. pero puedo ajustar manualmente los guardias a usar para circunstancias poco comunes. Entre menos intrusivo el parche. o Hay dos razones para ubicar los parches de backport en un grupo diferente. no introduzca o o o #ifdefs dependientes de versiones espec´ficas en los parches.6. a˜ adiendo una l´nea a la secci´ n [extensions] o n ı o de su hgrc. no es dif´cil acumular un gran n´ mero de parches. m´ s f´ cil ser´ entenderlo y o a a a mantenerlo. ´ Consejos utiles para hacer desarrollo con MQ Organizar parches en directorios Si est´ trabajando en un proyecto grande con MQ.9. En vez de eso.Los parches que necesitan revisi´ n antes de ser reenviados tienen el guardia rework. Por ejemplo. y controle su aplicaci´ n usando guardias. uno para cada versi´ n del kernel a la que aplica. o ´ Una meta util al escribir un buen parche de backport es hacer parecer que el c´ digo hubiera sido escrito para la o versi´ n vieja del kernel que usted tiene como objetivo. o Para aquellos parches que a´ n est´ n bajo desarrollo. usted puede usar la extensi´ n extdiff. El arte de escribir parches de backport Al usar MQ.9 tendr´ un guardia 2. Por ejemplo. En la mayor´a de las situaciones. genera un diff que representa el diff de la primera a la segunda versi´ n. La segunda es que un o parche de backport puede perturbar el contexto en el que se aplica un parche regular subsecuente. para o o ı a o que el controlador siga funcionando correctamente en esa versi´ n anterior. haciendo imposible aplicar el parche normal limpiamente sin que el parche de backport sea aplicado antes. uso devel. Si usted est´ escribiendo una colecci´ n de parches de backport para evitar el efecto de “nido de ratas” de a o tener muchos #ifdefs (secciones de c´ digo fuente que s´ lo son usados condicionalmente) en su c´ digo. 13. 13. pero tambi´ n porque MQ a˜ ade ruido al proceso al modificar las marcas de tiempo o e n y los nombres de directorio cuando actualiza un parche. La primera es que mezclar los dos hace m´ s dif´cil usar herramientas como la a ı extensi´ n patchbomb para automatizar el proceso de enviar los parches a un mantenedor oficial. o un parche que hace backport de un segmento de c´ digo a 2. 13. es una buena idea mantenerlos a ı en un repositorio. u a Un parche de backport puede tener varios guardias. 165 . Todo lo que dicho parche debe hacer es modificar una secci´ n de c´ digo que usa una caracter´stica del kernel que no est´ presente en la versi´ n anterior del kernel.

path.walk(base): for f in files: path = os.join(base. n Este programa est´ disponible como hg-interdiff en el directorio examples del repositorio de c´ digo fuente que a o acompa˜ a a este libro.keys() files.argv[1]. f))): 166 . if os. files = dict(walk(sys. name(sys. pero la extensi´ n extdiff le pasa un par de o directorios al programa que ejecuta. for root.path.com> # # This software may be used and distributed according to the terms of # the GNU General Public License.isfile(base): yield ’’.argv[2])) files = files. f) yield path[len(base)+1:]. base # create list of unique file names under both directories.exists(path): return path return ’/dev/null’ ret = 0 for f in files: if os. import os.system(’interdiff "%s" "%s"’ % (name(sys. cada uno de los cuales puede contener una cantidad arbitraria de ficheros. n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #!/usr/bin/env python # # Adapter for using interdiff with mercurial’s extdiff extension. files in os.1 2 [extensions] extdiff = El comando interdiff espera recibir los nombres de dos ficheros.argv[2]. dirs.sort() def name(base. f): if f: path = os. use /dev/null if one is missing.join(root. incorporated herein by reference.argv[1])) files.update(walk(sys.path. f). # # Copyright 2006 Bryan O’Sullivan <bos@serpentine. sys def walk(base): # yield all non-directories below the base path. f) else: path = base # interdiff requires two files.path. path else: if os. Por esto necesitamos un programa peque˜ o que ejecute interdiff en cada par de ficheros de estos dos directorios.

y luego regenera el parche. a 1 hg interdiff -r A:B my-change.interdiff = hg-interdiff Esto le indica a hgext que ponga a disposici´ n un comando interdiff. interdiff ´ podr´a no producir ning´ n resultado util. 1 2 [extdiff] cmd.43 44 45 ret = 1 sys. vaya a la secci´ n 14.exit(ret) Con el programa hg-interdiff en la ruta de b´ squeda de su int´ rprete de comandos. puede hacer que hgext lo haga disponible a como un comando normal de Mercurial. ı u ´ La extensi´ n extdiff es util para m´ s que solamente mejorar la presentaci´ n de los parches MQ. o 167 . modifica los ficheros subyacentes. desde dentro de un directorio de parches MQ: 1 hg extdiff -p hg-interdiff -r A:B my-change. con lo que usted puede abreviar la invocaci´ n o o anterior de “hg extdiff” a algo un poco m´ s manejable.patch Ya que usted seguramente querr´ usar este comando tan largo a menudo. puede ejecutarlo como u e sigue.2. editando de nuevo su hgrc.patch Nota: El comando interdiff trabaja bien s´ lo si los ficheros contra los cuales o son generadas las versiones de un parche se mantienen iguales. Si usted crea un parche. Para leer m´ s o a o a acerca de esto.

1.3 cubre la extensi´ n fetch.Cap´tulo 14 ı ˜ Anadir funcionalidad con extensiones A pesar de que el coraz´ n de Mercurial es muy completo desde el punto de vista de funcionalidad. o En la secci´ n 14. ˜ Mejorar el desempeno con la extensi´ n inotify o ¿Desea lograr que las operaciones m´ s comunmente usadas de Mercurial se ejecuten centenas de veces m´ s r´ pido? a a a ¡A leer! Mercurial tiene gran desempe˜ o bajo circunstancias normales. Por ejemplo. Esta aproximaci´ n de preservar la simplicidad mantiene el programa ı o sencillo tanto para mantenedores como para usuarios.1. Dado que obtener el estado de los ficheros es crucial para obtener buen desempe˜ o. carece de o caracter´sticas rimbombantes deliberadamente. ı La extensi´ n de administraci´ n de parches MQ es tan invaluable que amerita dos cap´tulos y un ap´ ndice por o o ı e s´ misma. cubrimos muchas extensiones que son utiles en funcionalidades relacionadas con ganchos: ı Los acl a˜ aden listas de control de acceso. El cap´tulo 12 cubre lo b´ sico. 14. del T. Muchas otras ordenes tienen que hacer tal trabajo tras bambalinas. n Mercurial tiene que revisar casi todos los ficheros y directorios en su repositorio de forma que pueda desplegar el estado ´ de los ficheros. plugins 168 . por ejemplo la orden “hg diff” usa la maquinaria de estado para evitar hacer operaciones de comparaci´ n costosas en ficheros que obviamente no han o cambiado. discutiremos la posibilidad de mejorar el desempe˜ o en gran medida con la extensi´ n o n o inotify. Sin embargo. que combina jalar cambios y fusionarlos con los cambios locales en o o una sola orden: “hg fetch”. y notify env´a notificaciones por correo de nuevos cambios. no puede obviarse el hecho de que cuando ejecuta o “hg status”. cuando ejecuta la orden “hg status”. y el ap´ ndice B muestra en ı ı a ı e detalle cada orden. ´ Si embargo Mercurial no le cierra las posibilidades a un conjunto inflexible de ordenes: usted puede a˜ adir caracn ter´sticas como extensiones (aveces llamadas a˜ adidos1 ). En este cap´tulo cubriremos algunas extensiones adicionales disponibles para Mercurial. los autores de Mercurial han n optimizado este c´ digo en la medida de lo posible. ´ En el cap´tulo 10. bugzilla a˜ ade integraci´ n con el sistema de seguimiento de fallos n n o Bugzilla. Mercurial tendr´ que hacer por lo menos una costosa llamada al sistema por cada fichero administrado a 1 N. el cap´tulo 13 discute temas avanzados. y daremos un vistazo a la ı maquinaria que necesita conocer en caso de que desee escribir una extensi´ n. Ya hemos discutido algunas de estas extensiones en cap´tulos ı n ı anteriores: La secci´ n 3.

es mejor tener una copia de Mercurial funcional instalada: biendo cualquier instalaci´ n previa de Mercurial que pudiera de Mercurial “m´ s reciente y peligrosa”. Desde el 2008 para kernels 2. del T.000 ficheros administrador. Un daemonio est´ en el fondo recibiendo notificaciones del subsistema inotify. Clone el repositorio crew de Mercurial. modificado o borrado. ReiserFS) deber´an funcionar bien. o u La extensi´ n tiene dos componentes. por ejemplo. Con la extensi´ n inotify habilitada. ext3. o ı Muchos sistemas operativos modernos contienen una facilidad de notificaci´ n de ficheros. y es un poco m´ s o ı a compleja de activar que otras extensiones. un factor cien veces m´ s o o a r´ pido. No todos los sistemas de ficheros pueden usarse con la extensi´ n inotify. Retomando los diez segundos que med´ al ejecutar la orden “hg status” de Mercurial sobre un repositorio de ı 150. estar´ reempl o a o Para comenzar. evitando la o a necesidad de revisar cada directorio y fichero del repositorio. Para un repositorio suficientemente grande.6 viene en Mercurial. tenga en cuenta algunos detalles: La extensi´ n inotify es espec´fica de Linux. Clone el repositorio de parches de inotify de forma tal que las colas de Mercurial puedan aplicar los parches sobre el repositorio crew. y en algunas distribuciones de Linux se encuentra como de Python hacia el subsistema inotify. Clone el repositorio de interfaz entre Python e inotify.py build --force sudo python setup.e.kublai. pero no est´ activada de forma predeterminada a 169 . El sistema inotify del kernel no tiene forma de saber acerca de los cambios hechos en otro sistema. cre´ un repositorio que conten´a 150. Armelo e inst´ lelo: a 1 2 3 4 hg clone http://hg. u Deber´a funcionar en cualquier distribuci´ n Linux a partir de comienzos del 2005. el tiempo se disip´ a 0. Una de ellas ı se llama pyinotify. no funciona en otros sistemas operativos. No diga que no se le a ´ 1. le pregunta al daemonio. o a Tambi´ n escucha conexiones de una orden regular de Mercurial. puesto que tiene muchos fallos. en lugar de revisar el sistema de ficheros. u ´ La extensi´ n inotify habla con el componente inotify del n´ cleo para optimizar las ordenes de “hg status”. En sistemas Linux. o una versi´ n de glibc que no tiene necesariamente el soporte para o la interfaz.com/python/inotify cd inotify python setup. XFS. La extensi´ n modifica el comportamiento de Mercue o rial de tal forma que. montados todos sobre el mismo a sistema de ficheros en red. python-inotify.´ para determinar si ha cambiado desde la ultima vez que se consign´ . ı ı Hacia mayo de 2007 la extensi´ n inotify no ven´a de forma predeterminada en Mercurial2 .py install --skip-build 2. Porque se enlaza directamente con el subsistema inotify del o ı n´ cleo Linux. La mayor´a de sistemas de ficheros locales (p. si est´ corriendo Mercurial en vaios sistemas. el sistema operativo le notificar´ siempre que un fichero de inter´ s haya sido a e creado. el componente del n´ cleo que lo hace se llama inotify. Los sistemas de ficheros tales como o NFS no lo soportan. a pesar de que ninguno de los ficheros hab´a sido modificado. puede o tardar bastante tiempo. y es ineficiente para ser pr´ ctica. puede responder instant´ neamente con el resultado. a Antes de continuar. y una librer´a de interfaces o ı o ı Nota: Hay dos librer´as de enlace de Python hacia inotify. 2 N.000 ficheros. Si un programa se o registra con un servicio apropiado. u e ı Tard´ diez segundos para ejecutar “hg status”. Esta es la que no necesita.1 seconds. Dado que el daemonio tiene informaci´ n perfecta acerca del estado del repositorio. a Nota: Si sigue las instrucciones a continuaci´ n. Las distribuciones m´ s anı o a tiguas deben tener un kernel sin inotify. Para mostrar en n´ meros la magnitud de este efect. Pero la mejora en el desempe˜ o bien vale la pena! n La extensi´ n ven´a en dos partes: un conjunto de parches al c´ digo fuente de Mercurial.

2. Aseg´ rese de instalar la extensi´ n Colas de Mercurial mq y que est´ n habilitadas. Si alguna de estas situaciones ocurre.py install --skip-build Una vez que haya armado una versi´ n funcional parchada de Mercurial. con e o ı ´ la unica excepci´ n de que los comandos relacionados con el estado deber´an ejectuarse mucho m´ s r´ pido que coo ı a a ´ mo sol´an hacerlo. lea la u o e secci´ n 12. esperando actualizaciones del kernel y solicitudes de Mercurial.5 para poder comenzar r´ pidamente. Vaya al repositorio de inotify y aplique todos los parches de inotify con la opci´ n -a de la orden “hg o qpush”. o ı a a n u a medida que su repositorio sea m´ s grande.org/mercurial/crew hg clone crew inotify hg clone http://hg. 1 2 [extensions] inotify = Cuando la extensi´ n inotify est´ habilitada. ı La primera vez que ejecuta un comando de Mercurial en un repositorio cuando tiene la extensi´ n inotify hao bilitada. todo lo que necesita es habilitar la extensi´ n o o inotify colocando una entrada en su hgrc. 1 2 cd inotify hg qpush -a Si obtiene un mensaje de error de “hg qpush”. Ejecuta un daemonio de estado por repositorio.1 2 3 hg clone http://hg. Mejor pida ayuda. por favor reporte el fallo.hg/patches 3.py build --force sudo python setup. 170 . El daemonio inotify hace operaciones de estado a n a de forma casi instant´ nea en repositorios de todos los tama˜ os! a n Si lo desea. Arme e instale la versi´ n parchada de Mercurial. todo comando posterior que haga cualquier clase u de revisi´ n del estado deber´a ser notablemente m´ s r´ pido en repositorios con incluso un tama˜ o modesto. ı 5. mejor desempe˜ o ver´ . o a 4. De todas formas. Deber´a esperar espec´ficamente que las ordenes no deber´an ofrecer salidas distintas. puede iniciar manualmente un daemonio de estado con la orden “hg inserve”. Soporte flexible de diff con la extensi´ n extdiff o La orden predeterminada “hg diff” de Mercurial despliega diffs en texto plano unificadas. no deber´a ver diferencia en el comportamiento de Mercurial. o Cuando est´ usando la extensi´ n inotify. Si nunca ha usado MQ. ver´ que hay e o a algunos procesos de hg por ah´. Si mira a la lista de procesos en ejecuci´ n o despu´ s de habilitar la extensi´ n inotify y ejecuta unos pocos comandos en diferentes repositorios. Esto es debido a que el estado del a n daemonio necesita aplicar una b´ squeda normal sobre el estado para poder tener una l´nea de partida frente a la cual u ı aplicar posteriormente actualizaciones del n´ cleo. no deber´a continuar. 14. Mercurial iniciar´ transparente y autom´ ticamente el daemonio de eso e a a tado la primera vez que ejecute un comando que requiera estado del repositorio. Esta orden solamente estar´ disponible cuando haya a o ı a habilitado la extensi´ n inotify. ni ofrecer ı ı ı ı resultados diferentes.intevation. El daemonio de estado se inicia silenciosamente y se ejecuta en el fondo. Esto le da un control un poco m´ s fino acerca de c´ mo deber´a ejecutarse el daemonio.com/mercurial/patches/inotify inotify/. o 1 2 python setup. A´ n mejor.kublai. correr´ casi con el mismo desempe˜ o que una orden usual de Mercurial.

ı Por ejemplo. +The second line.2 @@ The first line. a a La extensi´ n extdiff viene con Mercurial. Cada instant´ nea de directorio a a a tiene sus identificadores de conjuntos de cambios al final del nombre en caso de que sea apropiado. 2009-02-10 18:23:22. La opci´ n -p le permite elegir un programa para ver las o diferencias. En la secci´ n [extensions] de su hgrc. y as´ sucesivamente. para ejecutar la orden usual del sistema diff. Por cuestiones de eficiencia solamente genera instant´ neas de los directorios y ficheros que han cambiado entre dos revisiones. Si su repositorio a tiene por ruta /quux/bar/foo. la segunda es la revisi´ n objetivo del directorio a o o de trabajo. La orden “hg extdiff” genera estas instant´ neas en un directorio temporal. querr´ usar la extensi´ n extdiff.1 2 3 4 5 6 7 $ hg diff diff -r d6e1fbefacc8 myfile --. Si dese emplear una herramienta externa para desplegar las modificaciones. Esta le a o permitir´ usar por ejemplo una herramienta gr´ fica de diff.2 @@ The first line. en lugar de diff. Para ver a a c´ mo luce en la pr´ ctica. para lograr que se generen diferencias de contexto (con la opci´ n -c) en lugar de diferencias unificadas. +The second line. Tenga en cuenta que los diffs o a tienen los nombres de las instant´ neas de directorio dentro de su encabezado. La primera instant´ nea es la revisi´ n fuente.a631aca1083f.d6e1fbefacc8/myfile Tue Feb 10 18:23:22 2009 171 . pasa el nombre de cada a directorio a un visor de diffs temporal y borra los directorios temporales. 1 2 3 4 5 6 $ hg extdiff --. o 1 2 $ hg extdiff -o -NprcC5 *** a. y cinco l´neas de contexto en lugar de las tres predeterminadas o ı (pasando 5 como argumento a la opci´ n -C). que de forma predeterminada usa su orden del sistema diff para generar un diff unificado de la misma forma que lo hace el comando predeterminado “hg diff”. incluso pasando las mismas opciones. sintaxis y argumentos para especificar las revisiones y los ficheros que quiere. Una instant´ nea del directorio de o a a trabajo no tendr´ el identificador del conjunto de cambios.000000000 +0000 El resultado no ser´ exactamente el mismo que con la orden interna “hg diff”. Con la opci´ n -o puede cambiar las opciones que “hg extdiff” pasa a tal programa o ´ (de forma predeterminada las opciones son“-Npru”. el directorio se llamar´ foo. la orden “hg extdiff” funciona creando dos instant´ neas de ı a ´ su arbol de fuentes.a. que tienen sentido unicamente si est´ usando diff). a Los nombres de los directorios de instant´ neas tienen los mismos nombres base de su repositorio. En otros a aspectos. y por lo tanto ser´ solamente foo en este ejemplo. veamos de nuevo el ejemplo “hg extdiff” antes mencionado. puesto que la salida de diff var´a de a ı un sistema a otro. foo ser´ el nombre de cada instant´ nea de directorio. n ı o 1 2 [extensions] extdiff = Esto introduce una orden llamada “hg extdiff”. Como lo indican las l´neas“making snapshot”.000000000 +0000 2009-02-10 18:23:22. la orden “hg extdiff” act´ a de forma similar a como lo hace la orden “hg diff” de Mercurial: usted usa u los mismos nombres de opciones.1 +1. y es f´ cil configurar. Si una instant´ nea a viene de la revisi´ n a631aca1083f. basta o a o con a˜ adir una entrada de una l´nea para habilitar la extensi´ n.d6e1fbefacc8/myfile +++ /tmp/extdiff83LA2p/a/myfile @@ -1 +1.a/myfile Tue Feb 10 18:23:22 2009 +0000 +++ b/myfile Tue Feb 10 18:23:22 2009 +0000 @@ -1. a La orden “hg extdiff” acepta dos opciones importantes.

/tmp/extdiff83LA2p/a/myfile *************** *** 1 **** --. en la cual la gente env´a sus modificaciones a una lista o ı de correo para que otros las lean y comenten antes de consignar la versi´ n final a un repositorio compartido. Enviar cambios v´a correo electr´ nico con la extensi´ n patchbomb ı o o Varios proyectos tienen la cultura de “revisi´ n de cambios”.2. seguido por el nombre de la orden a la cual se aplican las opciones.1.1. Algunos o proyectos tienen personas que act´ an como cancerberos. Se e usa el prefijo “opts. puede teclear “hg kdiff3” y la n e extensi´ n a extdiff ejecutar´ la orden kdiff3. Definici´ n de alias de comandos o ´ Acordarse de todas las opciones de las ordenes “hg extdiff” y el visor de diferencias de su preferencia puede ´ ser dispendioso. puede usar un poco de scripting para lograrlo. y a˜ adir una secci´ n llamada [extdiff]. Un ejemplo de un script con la extensi´ n mq junto con la orden interdiff est´ en la secci´ n 13. o a o 14. 172 . En este ejemplos se define la orden “hg vimdiff” que ejecuta la extensi´ n DirDiff del editor vim. 14. Despu´ s de definido. Dentro de esta secci´ n puede definir n o o ´ varias ordenes. ellos aplican los cambios de otras personas a un repositorio u para aquellos que no tienen acceso. Uso de la extensi´ n transplant para seleccionar o Need to have a long chat with Brendan about this. Para lanzar el visor kdiff3: 1 hg extdiff -p kdiff3 -o ’’ Si su orden para visualizar diferencias no puede tratar con directorios. 1 2 [extdiff] cmd.vimdiff = -f ’+next’ ’+execute "DirDiff" argv(0) argv(1)’ 14. como en el ejemplo.kdiff3 = Si deja vac´a la porci´ n derecha de la definici´ n. la extensi´ n extdiff usa el nombre de la ı o o o orden se definir´ como el nombre del programa externo a ejecutar. Pero tales nombres no tienen por qu´ ser iguales. + The second line.4.9.2. a e Definimos ahora la orden llamada “hg wibble”. o 1 2 3 [extdiff] cmd. Basta con editar su fichero hgrc. o a 1 2 [extdiff] cmd. Tue Feb 10 18:23:22 2009 Es sencillo lanzar unas herramienta usual de diferencias.wibble = kdiff3 Tambi´ n puede especificar las opciones predeterminadas con las cuales desea invocar el visor de diferencias.2 ---The first line. que ejecuta kdiff3.”.3.vimdiff = vim opts. y por lo tanto la extensi´ n extdiff le permite definir nuevas ordenes que invocar´ n su visor de o a diferencias con las opciones exactas.3 4 5 6 7 8 --. Mostraremos como a˜ adir la orden kdiff3.

Si prefiere enviar la a descripci´ n y el diff en partes separadas del cuerpo.4. o a o ı 1 2 [extensions] patchbomb = Cuando haya habilitado la extensi´ n. Que facilita a a la mayor cantidad de lectores citar y responder partes de un diff. solicitar´ tales valores de forma interactiva. Puede enviar un conjunto binario3 con la opci´ n -b. el correo o o electr´ nico a usar. a o La orden “hg email” acepta la misma clase de sintaxis de revisiones como cualquier otra orden de Mercurial. o o Las diferencias unificadas est´ n precedidas por un encabezado de metadatos. o Las diferencias usualmente se env´an “en l´nea”. Por ejemplo. o El comportamiento predeterminado es enviar diferencias unificadas (consulte la secci´ n 12. Toma un argumento.1. o a Si env´a varias revisiones. sin la opci´ n -n. enviar´ todas las revisiones entre la 7 y la punta. Si indica un repositoro sin revisiones. Una vez que haya dado un vistazo a los cambios y verificado que a ı est´ enviando los correctos. Si especifica a a ´ revisiones adicionalmente o el nombre de una rama (la ultima con la opci´ n -b). o a La forma mejor y m´ s segura para invocar la orden “hg email” es ejecutarla siempre con la opci´ n -n. respetar´ las revisiones enviadas. puede volver a ejecutar la misma orden. Enviar una gran cantidad de cambios por correos se llama por tanto “bombardear” el buz´ n o de entrada del destinatario. a a ´ tendr´ capacidades estilo–readline aumentadas cuando ingrese tales encabezados. la orden “hg email” enviar´ normalmente un mensaje por conjunto de cambios. y enviar diferencias a sin adornos con la opci´ n --plain.) a Cuando env´e una sola revisi´ n. o o 3 N. a 1 hg email -n 7:tip Tambi´ n puede especificar un repositorio para comparar. Toma un argumento: ı n el tema del mensaje a usar. inclusive.4 si desea una deo scripci´ n del formato). llamada “hg email”.Mercurial facilita enviar cambios por correo para revisi´ n o aplicaci´ n gracias a su extensi´ n patchbomb. use la opci´ n -a. use la opci´ n -f. la extensi´ n patchbomb o o ´ intenta acomodarse a diferentes variaciones gracias a las opciones de la l´nea de ordenes: ı ´ Puede escribir un tema para el mensaje introductorio en la l´nea de ordenes con la opci´ -s. (Si est´ usando Linux o un sistema tipo Unix. la orden “hg email” e enviar´ todas las revisiones en el repositorio local que no est´ n presentes en el repositorio remoto. o a Ejecutar la orden “hg email” sin los nombres de aquellas personas a las cuales desea enviar el correo es completamente seguro: si lo hace. la configuraci´ n b´ sica de la extensi´ n patchbomb consta de una o dos l´neas en su hgrc. que le a o mostrar´ lo que la orden enviar´a. binary bundle 173 . dado que algunos clientes de correo solamente citar´ n la primera parte MIME del cuerpo de un mensaje. la orden “hg email” de forma predeterminada usar´ la primera l´nea de descripı o a ı ´ ci´ n del conjunto de cambios como el tema del unico mensaje que se enviar´ . a 14. una por mensaje. La o o o extensi´ n es tan popular porque los cambios se formatean como parches y es usual que se env´a un conjunto de o ı cambios por cada correo. Puede omitirlo. del T. como parte del cuerpo del mensaje con la descripci´ n del ı ı o parche. Coloı a car´ como prefacio un mensaje introductorio en el cual usted deber´a describir el prop´ sito de la serie de cambios que a ı o est´ enviando. sin enviar nada. ı Como es usual. lo cual es sumamente util. de ah´ su nombre “bombardeo de parches”. dispondr´ de una nueva orden. Para cambiar el correo electr´ nico del campo del cual se origina. Cambiar el comportamiento de las bombas de parches Cada proyecto tiene sus propias convenciones para enviar cambios en un correo electr´ nico.

174 . el n´ mero o u de l´neas afectadas.En lugar de enviar mensajes de correo puede escribirlos a un fichero con formato-mbox. Lo cual ofrece a los ı a lectores una mirada cuantitativa de cuan complejo es el parche. el nombre del fichero en el cual escribir. La o opci´ n recibe un argumento. o Si desea a˜ adir un resumen con formato-diffstat en cada parche. y uno como mensaje introductorio. use la n opci´ n -d. La orden diffstat despliega una tabla que contiene el nombre de cada fichero parchado.con la opci´ n -m. y un historgrama mostrando cu´ nto ha sido modificado cada fichero.

1. Al o a especificar -a se forza a “hg diff” a tratar los ficheros como texto. con el formato unificado diff. esta orden no imprime las diferencias para los ficheros binarios que Mercurial est´ sigue iendo. Si desea ver una descripci´ n del formato unificado diff.4. Options opci´ n --nodates o Omite la fecha y hora cuando se muestran los encabezados de las diferencias. tambi´ n -X e --dry-run. A. vea las opciones -a y --git. ı --include. “hg diff”—imprime los cambios en el historial o el directorio actual Mostrar las diferencias entre revisiones para ficheros especificados o directorios. tambi´ n -I e Incluye ficheros y directorios cuyos nombres coinciden con los patrones elegidos. ˜ “hg add”—Anade ficheros en la pr´ xima consignaci´ n o o --include. Para controlar este comportamiento. Una l´nea que contiene espacios en ı ı blanco no se considera como una l´nea en blanco. --exclude.1. tambi´ n -I e --exclude. y generar diferencias para todos. --text. tambi´ n -B e No imprime los cambios que solamente insertan o eliminan l´neas en blanco. tambi´ n -n e A. o o De forma predeterminada. ver la secci´ n 12. tambi´ n -X e Excluye los ficheros y directorios cuyos nombres coinciden con los patrones elegidos. tambi´ n -a e Si no especifica esta opci´ n.2. “hg diff” no mostrar´ las diferencias de los ficheros que detecte como binarios. 175 .Ap´ ndice A e ´ Referencia de Ordenes A.2. --ignore-blank-lines.

las dos o especificaciones de revisiones a continuaci´ n son equivalentes: o 176 . tambi´ n -b e ´ No imprime si el unico cambio que en la l´nea es la cantidad de espacio en blanco.c --. 3. + return 10. a --ignore-space-change. tambi´ n -g e Mostrar diferencias compatibles con git. como en el ejemplo siguiente.4 @@ int myfunc() { return 1. ı --git. Despliega las diferencias entre la revisi´ n padre y del directorio de trabajo.4 +1. o o o ı Esta funcionalidad se habilita de forma predeterminada. Puede especificar dos revisiones usando o bien sea las opciones -r o la notaci´ n de rango. tambi´ n -r e >> $HGRC 10 18:23:18 2009 +0000 10 18:23:18 2009 +0000 10 18:23:18 2009 +0000 10 18:23:18 2009 +0000 Especifique una o m´ s revisiones para comparar. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ echo ’[diff]’ >> $HGRC $ echo ’showfunc = False’ $ hg diff diff -r a38a6c74a605 myfile. XXX reference a format description. Despliega las diferencias entre dos conjuntos de cambios especificados.a/myfile.c Tue Feb @@ -1. o 2. 1.c Tue Feb +++ b/myfile. --show-function. Por ejemplo.c --. tambi´ n -p e Mostrar el nombre de la funci´ n que contiene el c´ digo en una porci´ n del encabzado usando una heur´stica simple. as´ que la opci´ n -p no tiene efectos a menos que cambie el ı o valor de showfunc en la configuraci´ n.4 @@ int myfunc() int myfunc() { return 1. la salida ser´ incomprensible.4 +1. } $ hg diff -p diff -r a38a6c74a605 myfile. Despliega las diferencias entre el conjunto de cambios especificados y el directorio de trabajo. + return 10. } --rev.´ Esta opci´ n es util para los ficherso que son “texto en mayor medida” pero que tienen caracteres NUL. Si lo usa o en ficheros que contienen muchos datos binarios.c Tue Feb @@ -1.c Tue Feb +++ b/myfile. La orden “hg diff” acepta hasta dos opciones -r para especificar a las revisiones a comparar.a/myfile.

Hay cuatro o a o clases de cadenas de versi´ n posibles: o La cadena “unknown”. Esta versi´ n de Mercurial no fue construida en un repositorio de Mercurial. “hg diff” opera a´ n relativo solamente al primer padre. tal como “1.1. y no puede o determinar su propia versi´ n. “hg diff” imprime diferencias frente al primer padre del directorio de trabajo. Si ejecuta la orden “hg diff”. esto tiene significado para Mercurial. Esto significa que “hg diff -r10:20” producir´ un diff que transformar´ los ficheros desde los contenidos en la revisi´ n 10 a los contenidos de la revisi´ n a a o o 20. No hay forma de hacer que imprima las diferencias o relativas a los dos padres. o Una cadena num´ rica corta. ver´ una lista de ficheros para los cuales Mercurial almacenar´ cambios la a a pr´ xima vez que consigne. mientras que “hg diff -r20:10” significa lo opuesto: el diff que transformar´a los contenidos de los ficheros de ı la revisi´ n 20 a los contenidos de la revisi´ n 10.3. Hay dos posibles razones para este comportamiento: La primera es que “hg status” imprime cierta clase de modificaciones que “hg diff” no despliega normalmente. tal como “875489e31abe+20070205”. 177 .3.1 2 hg diff -r 10 -r 20 hg diff -r10:20 Cuando especifica dos revisiones. Una cadena hexadecimal seguida por una fecha. tambi´ n -w e A. Si ha ejecutado “hg merge” para fusionar dos conjuntos de cambios. su directorio de trabajo tiene dos padres (use “hg parents” para u o verlos). --ignore-all-space. Esta construcci´ n de la o revisi´ n de Mercurial fue la construcci´ n de un repositorio que tuvo cambios locales que no han sido consignao o dos. Lo m´ s notable es que las diferencias tradicionales no pueden representar a un cambio acerca de la ejecutabilidad de un fichero. Esta es una construcci´ n de una revisi´ n dada de Mercuo o rial. y su nota de derechos de reproducci´ n. Puede lograr que imprima las diferencias u relativas al segundo padre especificando tal padre con la opci´ n -r.1”. las cuales no tienen la habilidad de representar algunos cambios que Mercurial puede seguir. Mientras que “hg status” imprime modificaciones relativas a ambos padres despu´ s de una fusi´ n que no e o se ha consignado. Consejos y trucos ¿Por qu´ difieren los resultados de “hg diff” y “hg status”? e Cuando ejecuta la orden “hg status”. pero no ha consignado a´ n los resultados de la fusi´ n. No puede invertir el orden de esta forma si est´ haciendo un diff frente o o a al directorio de trabajo. tal como “875489e31abe”. Una cadena hexadecimal. “hg version”—imprime la informaci´ n de versi´ n y derechos de reo o producci´ n o Esta orden despliega la versi´ n de Mercurial que est´ usando. A. ı o Si usa la opci´ n --git de “hg diff”. Esta es una construcci´ n de una versi´ n de Mercurial que se idene o o tifica con una etiqueta espec´fica en el repositorio en el cual fue armada (Esto no significa necesariamente que ı est´ ejecutando una versi´ n oficial. pero Mercurial s´ almacena esta informaci´ n. mostrar´ diferencias compatibles con git que pueden desplegar esta inforo a maci´ n adicional. La orden “hg diff” usualmente despliega diferencias unificadas. ver´ que imprime diferencias solamente para un subconjunto o a de los ficheros que “hg status” liste. o La segunda raz´ n posible para que “hg diff” est´ imprimiendo diferencias para un subconjunto de ficheros de o e lo que muestra “hg status” es que si usted le invoca sin argumento alguno. alguien pudo haber a˜ adido tal etiqueta a cualquier versi´ n del repositorio a o n o en el cual armaron Mercurial).

La orden patch del sistema no puede tratar con o parches binarios. use la opci´ n “hg diff”–git cuando genere el parche.Generar diferencias seguras en binarios Si usa la opci´ n -a para forzar que Mercurial imprima las diferencias de los ficheros que so o bien “casi compleo tamente texto” o contienen muchos datos binarios. tales diferencias no pueden aplicarse subsecuentemente a la orden “hg import” de Mercurial o a la orden patch del sistema. Si desea generar una diferencia de un fichero binario que es seguro para usarlo como entrada a la orden “hg import”. 178 .

de tal forma que el ultimo parche aplicado es la uni´ n de todos los cambios de los parches en cuesti´ n. B. “hg qfold” saldr´ indicando un error si alguno ha sido a aplicado.Ap´ ndice B e Referencia de las Colas de Mercurial B.1.4. “hg qapplied”—imprimir los parches aplicados La orden “hg qapplied” imprime la pila actual de parches aplicados.1. “hg qdelete”—eliminar un parche del fichero series La orden “hg qdelete” elimina la entrada del fichero series para el parche en el directorio . o o Los parches a fusionar no deben haber sido aplicados.hg/patches”. ´ “hg qdiff”—imprimir la diferencia del ultimo parche aplicado La orden “hg qdiff” imprime un diff del parche m´ s recientemente aplicado.1.5. 179 . y seguido de b”. use la opci´ n -f para o hacerlo.hg/patches. por lo tanto el ultimo parche de la lista es el que u a e a est´ en el “tope”.hg/patches. ´ Referencia de ordenes MQ ´ Si desea dar un vistazo a las ordenes que ofrece MQ. “hg qcommit”—consignar cambios en la cola del repositorio La orden “hg qcommit” consigna cualquier cambio sobresaliente en el repositorio . B.1. Opciones: -f Elimina el fichero del parche. Los parches se imprimen en orden de ´ antig¨ edad.1. seguido de a. p. “hg qfold a b” significa “aplique el parche m´ s a reciente. a B. primero los m´ s antiguos y despu´ s los m´ s recientes. “hg qfold”—fusionar (“integrar”) varios parches en uno solo ´ ´ La orden “hg qfold” fusiona muchos parches en el ultimo parche aplicado.1.hg/patches es un repositorio. usted cre´ el directorio con “hg qinit -c” o o ejecut´ “hg init” en el directorio despu´ s de correr “hg qinit”. Es equivalente a “hg diff -r-2:-1”. No sca el parche si ha sido aplicado.3.e. o e Esta orden es un atajo para “hg commit --cwd .2. a B. De forma predeterminada no borra el fichero del parche. Esta orden solamente funciona si el directorio .1. use la orden “hg help mq”. El orden en el cual los parches se pliegan es significativo. B.

hg/patches como un repositorio por s´ mismo. Crea un directorio llamado . “hg qheader”—desplegar el encabezado/descripci´ n de un parche o La orden “hg qheader” imprime el encabezado o descripci´ n de un parche. o o B. Tambi´ n crea un fichero .hg/patches. B. rehusar´ crear un parche nuevo a meos a ´ que se emplee -f la opci´ n (ver m´ s adelante).7.hg/patches. B. el directorio de n trabajo no lucir´ modificado. ı o 180 . “hg qnew”—crear un parche nuevo La orden “hg qnew” crea un parche nuevo.1. “hg qimport” autom´ ticamente hace un “hg add” del parche a importado. ´ Cuando el directorio .1. Si “hg qnew” encuentra ficheros modificados en el directorio de trabajo.1. Opciones: -c Crea . “hg qimport”—importar el parche de un tercero en la cola La orden “hg qimport” a˜ ade una entrada de un parche externo al fichero series y copia el parche en el directorio n ´ . e Opciones: -e Edita el mensaje de consignaci´ n y la descripci´ n del parche del parche que se ha integrado. Este comportamiento le permite hacer “hg qrefresh” al ultimo parche o a aplicado antes de aplicar un parche nuevo encima de este. Este parche ser´a el pr´ ximo parche a aplicar si se ejecutara la orden “hg qpush”. n e Si el directorio . A˜ ade la entrada inmediatamente despu´ s del ultimo parche aplicado. Este texto se almacenar´ al principio del fichero del parche. Exige un argumento. imprime o ´ el encabezado del ultimo parche aplicado. con cada bloque de comentarios separado con tres asteriscos (“*”). y se introduce e a ı n e en el tope de ese parche. Opciones: -f Crea un parche nuevo si los contenidos del directorio actual han sido modificados. Cualquier modificaci´ n o significativa se a˜ ade al parche recientemente creado. o a antes de los datos del parche. imprime el encabezado del parche referenciado.1. a -m Usa el texto dado como el mensaje de consignaci´ n. a B.Los comentarios de los parches integrados se colocan al final de los comentarios del parche destino. las ordenes “hg qimport” y “hg qnew” hacen “hg add” autom´ ticamente a los parches nuevos. Se a˜ ade al fichero series despu´ s del ultimo parche aplicado.hg/patches es un repositorio.9. pero no introduce el parche.1. el nombre que se usar´ para tal parche.6. El parche a ´ reci´ n creado est´ vac´o inicialmente. -m Usa el texto dado como el mensaje de consignaci´ n y descripci´ n del parche para el parche integrado.hg/patches es un repositorio. o o -l Usa los contenidos del fichero dado como el nuevo mensaje de consignaci´ n y descripci´ n del parche para el o o parche a integrar. Si se da un argumento.hgignore que ignorar´ el ı e a fichero status.8. “hg qinit”—preparar un repositorio para trabajar con MQ La orden “hg qinit” prepara un repositorio para trabajar con MQ. “hg qnext”—imprimir el nombre del pr´ ximo parche o ´ La orden “hg qnext” imprime el nombre del siguiente parche en el fichero series a continuaci´ n del ultimo o parche aplicado. De forma predeterminada. Se usa la opci´ n -e para editar el mensaje de consignaci´ n o o para el conjunto de cambios/parches despu´ s de completarse el pliegue. B. de tal forma que al finalizar la orden.10.

Si no hay tal texto. la orden “hg qpop” no sustraer´ parche alguno si el directorio de trabajo ha sido modia ficado.11.1. Opciones: -a Introduce todos los parches que no han sido aplicados del fichero series hasta que no haya nada m´ s para a introducir. Esta orden elimina los conjuntos de cambios que representan los parches sustra´dos del repositorio. De forma predeterminada solamente remueve un parche. que usa como el nombre o el ´ndice del parche que desea sustraer. el conjunto de cambios que introduzca tendr´ una identidad distinta a la del conjunto de a cambios que sustrajo. Opciones: -a Sustrae todos los parches aplicados. a Este se volver´ el ultimo parche aplicado si ejecuta “hg qpop”. contando desde cero (no cuenta las l´neas vac´as o aquellas ı ı ı ´ ´ que sean unicamente comentarios). n n Esta orden crea un conjunto de cambios que representa cada parche aplicado y actualiza el directorio de trabajo aplicando los efectos de los parches. Su un parche contiene un encabezado de parche de Mercurial (XXX add link). “hg qpop” se constituye por tanto en una forma segura de sustraer un parche del fichero series o un parche que ha eliminado o renombrado completamente. o De forma predeterminada. Esta orden toma un argumento opcional. sustraer´ los parches hasta que el parche nombrado sea el ultimo parche aplicado. Restaura el repositorio al estado antes de haber aplicado parche alguno.1. un mensaje predeterminado se sua para identificar el nombre del parche. use el nombre del parche tal como lo hizo cuando lo aplic´ . “hg qpush”—introducir parches a la pila La orden “hg qpush” a˜ ade parches a la pila. Sustrae los parches hasta que el parche identificado por el ´ndice sea el ultimo ı parche aplicado. que revierte todas las modificaciones del directorio de o trabajo. y actualiza el ı directorio de trabajo para deshacer los efectos de los parches.1. Puede modificar este comportamiento con la opci´ n -f. Los datos predeterminados cuando se crea un conjunto de cambios corresponde a: La fecha de consignaci´ n y zona horaria corresponden a la hora actual de la zona. la informaci´ n en el encabezado del o parche tiene precedencia sobre el predeterminado. Dado que tales datos se o usan para computar la identidad de un conjunto de cambios. o -n Sustraer un parche de la cola dado un nombre. “hg a u qpop” lo trata como un ´ndice dentro del fichero series.B. Si se da ı ´ el nombre.13. ´ En los dos ultimos casos. -f Revertir forzadamente cualquier modificaci´ n del directorio de trabajo cuando se hace sustracciones. “hg qpop”—sustraer parches de la pila La orden “hg qpop” elimina los parches aplicados del tope de la pila de parches aplicados. De forma predeterminada a˜ ade solamente un parche. El autor es el mismo que el predeterminado usado por la orden “hg commit”.12. 181 . Si se da un n´ mero. La orden “hg qpop” no lee o escribe parches en el fichero series. significa que si hace “hg qpop” a un parche y “hg qpush” de nuevo. ı B. La orden “hg qpop” elimina una l´nea del final del fichero status por cada parche que se sustrae. “hg qprev”—imprimir el nombre del parche anterior ´ La orden “hg qprev” imprime el nombre del parche en el fichero series que est´ antes del ultimo parche aplicado. El mensaje de consignaci´ n es cualquier texto del fichero del parche que viene antes del primer encabezado del o diff. a ´ B.

el texto antes del primer encabezado de diff en el fichero del o parche. elimina el ultimo conjunto de cambios que represent´ el parche. a o La orden “hg qpush” lee. B. o o -n Usa la cola mencionada si se est´ fusionando en la introducci´ n. o o -m Modificar el mensaje de consignaci´ n y la descripci´ n del parche con el texto dado. usa la entrada para un parche en otra cola almacenada para computar los par´ metros en una fusi´ n de tres. a o o Usa la resoluci´ n de la fusi´ n como el contenido del parche nuevo. o “hg rename”. Con dos argumentos. mientras que los ficheros elimin n nados y las fuentes renombradas se eliminan. Se a˜ aden al parche los ficheros a˜ adidos.15. “hg qseries”—imprime la serie completa de parches La orden “hg qseries” imprime la serie completa de parches del fichero series. B.17.18. el ultimo aplicado. y aplica una fusi´ n de tres fuentes usando la maquinaria usual de Mercurial.1. Imprime primero el primero y de ultimo. “hg qrestore”—restaurar el estado almacenado de la cola XXX No idea what this does. Modifica el parche. o La orden “hg qrefresh” busca las siguientes modificaciones: Los cambios al mensaje de consignaci´ n.1. A˜ ade al final del fichero “hg status” una l´nea n ı por cada parche que se introduce. de todas maneras recrea el conjunto de cambios que representa el cambio. “hg qrename”—renombrar un parche La orden “hg qrename” renombra un parche y cambia la entrada del parche en el fichero series. “hg qsave”—almacena el estado actual de la cola XXX Likewise.1.-l A˜ ade el nombre del parche al final del mensaje de consignaci´ n n o -m Si un parche no se aplica limpiamente. “hg qrename” renombra el ultimo parche aplicado. o o B. ´ Con un argumento sencillo. se replejan en el nuevo conjunto de cambios que representa el parche. “hg remove”. B. ´ “hg qrefresh”—actualiza el ultimo parche aplicado ´ ´ La orden “hg qrefresh” actualiza el ultimo parche aplicado. “hg copy”.16.14. B. p. copiados y renombrados.e. Imprime solamente los nombres ´ ´ de los parches sin las l´neas en blanco o comentarios. Opciones: -e Modificar la descripci´ n de la consignaci´ n y el parche con el editor de texto preferido. renombra el primer argumento con el segundo. ı 182 . Las modificaciones a los ficheros a los que se les da seguimiento en el directorio de trabajo se a˜ ade al parche.1. n Los cambios a los ficheros a los que se les da seguimiento con “hg add”. Esto causa que la identidad del conjunto de cambios difiera del conjunto de cambios previo que identific´ al o parche. Incluso si “hg qrefresh” no detecta cambios. pero no modifica el fichero series.1. o o -l Modificar el mensaje de consignaci´ n y la descripci´ n del parche con el texto del fichero dado. y crea un nuevo conjunto de cambios para representar el parche modificado.

El fichero status El fichero status contiene los nombres y los hashes de los conjuntos de cambios de todos los parches que MQ ha aplicado. -n No almacene la copia de seguridad agrupada. y va hasta el final de la l´nea.1. y actualiza el directorio de trabajo hasta el primer padre de la revisi´ n removida.2. -f Si una rama tiene varias ramas principales remueve todos los frentes. B. No deber´a colocar este fichero n ı bajo el control de revisiones o modificarlo de forma alguna. Los imprime de acuerdo al orden en el cual ser´an introducidos. Tambi´ n es posible colocar el fichero series bajo control de revisiones.2. puede poner en comentario un parche temporalmente y “hg qpush” omitir´ tal parche cuando los aplique. esto o se har´ autom´ ticamente. o Opciones: -b Almacenar conjuntos de cambios no relacionados que se han mezclado con los conjuntos de cambios que est´ n a en franjas con el agrupamiento de copia de seguridad.1.1. Referencia de ficheros de MQ El fichero series El fichero series contiene una lista de los nombres de todos los parches que MQ puede aplicar. y todos sus descendientes del repositorio. o La orden “hg strip” almacena una copia de segurida de los conjuntos de cambios en un agrupamiento. Un comentario comienza con el caracter “#”.21.1. uno por l´nea. Si crea un directorio de parches con la opci´ n -c de “hg qinit”. ı ı En alg´ n momento podr´a editar el fichero series a mano. ´ “hg qunapplied”—imprimir los parches que aun no se han aplicado La orden “hg qunapplied” imprime los nombres de los parches del fichero series que todav´a no han sido ı aplicados. y usa -f para desagrupar revisiones cuando hay cambios pendientes. este NO ha sido dise˜ ado para ser editado.2. “hg strip”—remover una revisi´ n y sus descendientes o La orden “hg strip” remueve una revisi´ n. B. XXX This should be renamed. ı B. tambi´ n es favorable colocar todos los e e parches que refiera bajo control de revisiones. ı ı Se ignoran las l´neas vac´as y las que solamente contengan comentarios. B. A diferencia del fichero series. Se representa como una lista de nombres.20. Tambi´ n puede cambiar el orden en el cual se aplican los parches. ı Las l´neas pueden contener comentario. Deshace los efectos de las o revisiones removidas del repositorio. de forma tal que puedan ser reaplicados en caso de que se hayan removido por equivocaci´ n. Por ejemplo. o 183 . MQ lo usa estrictamente para administraci´ n interna. a e reordenando las entradas en el fichero series. Se ignora el espacio en blanco al principio y al final.2. a a B. “hg qtop”—imprime el nombre del parche actual ´ “hg qtop” imprime el nombre del ultimo parche aplicado.B. por tal motivo se admiten comentarios y l´neas en u ı ı blanco como se menciono anteriormente.19.

2. le recomiendo que mejor use un paquete binario. Descompr´malo: ı 1 gzip -dc mercurial-version.tar. e u e Probablemente necesitar´ establecer la variable de ambiente PYTHONPATH de tal forma que los ejecutables de Mera curial puedan encontrar el resto de los paquetes de Mercurial.com/mercurial/wiki/index.3 o superior) disponible. Si est´ decidido a construir Mercurial desde las fuentes en Windows. Por ejemplo. la establec´a a /home/bos/lib/python. Esto armar´ Mercurial y lo instalar´ en su directorio o o a a casa: 1 2 cd mercurial-version python setup. C. Personalmente. En un sistema tipo Unix Si usa un sistema tipo Unix que tiene una versi´ n suficientemente reciente de Python (2. y vea d´ nde se instalaron los a o contenidos del directorio mercurial se instalaron.Ap´ ndice C e Instalar Mercurial desde las fuentes C. y espere que el proceso sea realmente un trabajo duro. A menos que intente hacer hacks a Mercurial. 184 .cgi/WindowsInstall. siga el “camino dif´cil” indicado en el wiki de a ı Mercurial en http://www. Vaya al directorio fuente y ejecute el gui´ n de instalaci´ n. en mi port´ til.com/mercurial/download. No olvide asegurarse de o a ´ que este directorio est´ presente en el camino de b´ squeda de su int´ rprete de ordenes.py install --force --home=$HOME Cuando termine la instalaci´ n. Descargue un paquete fuente reciente de http://www.2. a ı La ruta exacta que usted use depender´ de como ha sido constru´do Python en su sistema. a 1.selenic.1. mire lo que haya mostrado el script en el paso anterior. no le recomiendo hacerlo si es un “usuario casual”. Mercurial estar´ en el subdirectorio bin de su directorio casa. cierta suficiencia t´ cnica y paciene cia considerable.selenic. o es f´ cil instalar Mercurial desde las fuentes.gz | tar xf - 3. Si no est´ seguro. pero deber´a ser f´ cil dea ı ı a ducirla. En Windows Armar e instalar Mercurial en Windows requiere una variedad de herramientas.

o a La referencia debe estar seguida inmediatamente por cualquier opci´ n elegida por el(os) autor(es) y/o editor(es) o del documento (consulte la secci´ n D. 185 . Si cualquier porci´ n de esta licencia no es aplicable en alguna jurisdicci´ n.1. Requerimientos en versiones modificadas y no modificadas Los trabajos bajo Publicaci´ n Abierta pueden reproducirse y distribuirse enteros o en porciones. o o Cualquier publicaci´ n en forma est´ ndar de libro (papel) requerir´ citar al editor y autor original. las porciones restantes o o se mantienen. y se incorpore esta licencia o ı o e su referencia (con cualquiera de las opciones elegidas por el autor y el editor) en la reproducci´ n. La simple agregaci´ n de trabajos de Publicaci´ n Abierta o una porci´ n de trabajos de Publicaci´ n Abierta con otros o o o o trabajos o programas en el mismo medio no causar´ n que esta licencia se aplique a los otros trabajos.6). 8 Junio de 1999 o D. o Separabilidad.3.0. Los agregados a deber´ n contener una nota que especifique la inclusi´ n de matrial de Publicaci´ n Abierta y una nota de derechos de a o o reproducci´ n acorde. Este material puede distribuirse solamente bajo los n ´ t´ rminos y condiciones especificados por la Licencia de Publicaci´ n Abierta.2.Ap´ ndice D e Licencia de Publicaci´ n Abierta o Versi´ n 1. o Se permite la redistribuci´ n comercial de los materiales sujetos a la Publicaci´ n Abierta. En todas las superficies externas el nombre a del editor deber´ aparecer en tama˜ o de la misma medida que el t´tulo del trabajo y ser´ citado como poseedor con a n ı a respecto al t´tulo.org/openpub/). o A continuaci´ n mostramos la forma correcta de incorporar por referencia: o Copyright (c) a˜ o por nombre del autor o designado. Alcance de la licencia Los t´ rminos de licencia dsecritos aplican a todos los trabajos bajo licencia de publicaci´ n abierta a menos que se e o indique de otra forma en este documento. Derechos de reproducci´ n o El derecho de reproducci´ n de cada Publicaci´ n Abierta pertenece al(os) autor(es) o designados.opencontent. siempre y cuando se respeten los t´ rminos de esta licencia. ı D. Los nombres o a a del editor y el autor aparecer´ n en todas las superficies externas del libro.y o posterior (la ultima e o versi´ n disponible est´ en http://www. vx. en cualquier o medio f´sico o electr´ nico. o o D.

expresa o impl´cita. Requerimientos sobre trabajos modificados Todas las versiones modificadas de documentos cubiertos por esta licencia. o o 3. El dar cr´ dito al autor original y al editor si se requiere de acuerdo a las pr´ cticas acad´ micas de citas. antolog´as. incluyendo. La versi´ n modificada debe estar etiquetada como tal. al documento.” a la referencia de la licencia o a la ı n o copia. se solicita a los redistribuidores y se recomienda en gran medida que: 1. ı compilaciones y documentos parciales. Todas las modificaciones sustanciales (incluyendo eliminaciones) deben estar marcadas claramente en el documento o si no descritas en un adjunto del documento.6. se considera de buenos modales enviar una copia gratis de cualquier expresi´ n en copia dura o CD-ROM de un trabajo licenciado con Publicaci´ n Abierta a el(os) o o autor(es). en caso de que haya. a Para lograr esto. Si est´ distribuyendo trabajaos de Publicaci´ n Abierta en copia dura o CD-ROM. No puede usarse el(os) nombre(s) del autor (de los autores) para implicar relaci´ n alguna con el documento o resultante sin el permiso expl´cito del autor (o de los autores). Opciones de licencia El(os) autor(es) y/o editor de un documento licenciado con Publicaci´ n Abierta pueden elegir ciertas opciones o a˜ adiendo informaci´ n a la referencia o a la copia de la licencia. aunque no es obligatorio bajo esta licencia. env´e una notificaci´ n por a o ı o correo a los autores acerca de su intenci´ n de redistribuir por lo menos con treinta d´as antes de que su manuscrito o ı o el medio se congelen. o 2. Estas opciones se consideran parte de la instancia de n o la licencia y deben incluirse con la licencia (o su incorporaci´ n con referencia) en trabajos derivados. Finalmente.Sin garant´a. deben seguir estos requerimientos: 1. La persona que hace la modificaci´ n debe estar identificada y la modificaci´ n con fecha. o 5. y se excluyen a simples cambios en el formato o correcciones tipogr´ ficas. Debe identificarse el lugar del documento original sin modificaci´ n. D. Recomendaciones de buenas pr´ cticas a Adicional a los requerimientos de esta licencia.4. o ı 2. Se o ı definen “modificaciones substanciales” como cambios en el contenido sem´ ntico del documento. Esta notificaci´ n deber´a describir las modificaciones. a˜ ada la frase “Se prohibe la distribuci´ n de versiones substancialmente modificadas de este n o documento sin el permiso expl´cito del due˜ o de los derechos de reproducci´ n. para permitir a los autores tiempo para proveer documentos actualizados. o A Prohibir la distribuci´ n de versiones substancialmente modificadas sin el permiso expl´cito del(os) autor(es). incluyendo traducciones. Los trabajos de Publicaci´ n Abierta se licencian y ofrecen “como est´ n” sin garant´a de ninguna ı o a ı clase. e a e 4. ı D.5. pero no limitados a las garant´as de mercabilidad y adaptabilidad para un ı ı prop´ sito particular o garant´a de no infracci´ n. 186 . o ı o D. 3.

o Para lograrlo. 187 .” a la referencia de la licencia n o o la copia. a˜ ada la frase “La distribuci´ n del trabajo o derivados en cualquier libro est´ ndar (papel) se prohibe n o a a menos que se obtenga un permiso previo del due˜ o de los derechos de reproducci´ n.B Est´ prohibido prohibir cualquier publicaci´ n de este trabajo o derivados como un todo o una parte en libros est´ ndar a o a (de papel) con prop´ sitos comerciales a menos que se obtenga un permiso previo del due˜ o de los derechos de o n reproducci´ n.

org/ prep/standards/html_node/Change-Logs. http://savannah.Bibliograf´a ı [AG] [BI] [Bro] [Dic] [Dus] Jean Delvare Andreas Gruenbacher. Simon Tatham.au/˜neilb/source/ Thomas Dickey. Patchwork quilt. Tim Waugh. diffstat–make a histogram of diff output.org/ projects/quilt. wiggle–apply conflicting patches.de/ ˜agruen/quilt. file parser. ConfigParser—configuration module-ConfigParser.his.oracle.html. Achieving high performance in mercurial. http://sourceforge. wiggle/.greenend.pythonmac. [O’S06] Bryan O’Sullivan.gnu. Ronald Oussoren Bob Ippolito. http://www.org/lib/ GNU Project volunteers Richard Stallman.com/diffstat/ diffstat. In EuroPython Conference. http://bob. http://docs. XXX. http://www. http://www. http://dickey. Neil Brown. July 2006. How to survive with many patches (introduction to quilt).com/˜mason/mpatch/.edu.unsw. http://cyberelk. Gnu coding standards—change logs. Andy Dustman. mpatch–help solve patch rejects.uk/ ˜sgtatham/putty/. [Gru05] Andreas Gruenbacher. [Pyt] [RS] [Tat] [Wau] Python.pdf.net/tim/ 188 .cse.html.org.nongnu. patchutils/. [Mas] Chris Mason.chiark. http://cgi.org/archives/2006/04/ 10/python-and-universal-binaries-on-mac-os-x/.net/projects/mysql-python.html. Universal macpython. Mysql for python. http://oss. June 2005. Putty—open source ssh client for windows.org.suse. Martin Quinson. patchutils–programs that operate on patch files.python.

comando. 168 o bugzilla. 68 author. 91. 113. 174 o opci´ n --exclude. 94. 179. comando. 168 o acl. 58. extensi´ n. 67. 83. 109. 73. 49–51. filtro de plantilla. 84. 75. 144. 151 .hg/patches. 155. 152 . 142.hg/hgrc. 132. 73. directorio. 112. 52–56. variable de entorno. 158 o opci´ n -A. 98. 127. 92. gancho. 117 o opci´ n -u. variable de entorno. 52. 88 bugzilla. 96. 95–102 opci´ n --merge. 41. 150 . 178. 10 o conver. 158. fichero de configuraci´ n. 70 clone. 134 filtro isodate. 174 o opci´ n --include. 126. 119–122. 142 o branches. 129 config. 134. comando. 155. 153–155. 145 authorized keys.´ Indice alfab´ tico e . comando. 124 HG SOURCE. 31. 134 addremove. 10 copy. 87. 10 o convert. 18. extensi´ n. 86. 150. 71. 134 filtro hgdate. 110 . 67. 112. directorio. 112. 153. 143. 20 HG NODE. fichero. 124 HG PARENT1. comando. 55 o cp. 117. 69 . 20 o commit. 155.hgtags. 116. 124. 125 HG URL. variable de entorno. 77. 115.ini. 174 o age. 174 o opci´ n -I. 54 date. variable de entorno. fichero. 13. 135 filtro domain. comando de sistema. comando. 174 o opci´ n -X. 117. 144. 20 HGMERGE. 174. 84. comando. 2. 33 HGUSER. 124 HG PARENT2.ssh. directorio. comando. 112. variable de entorno. 181 opci´ n --dry-run. comando. 84 opci´ n -r. fichero. fichero. gancho. extensi´ n. fichero. 134 bash. 52. 128. comando. 119. 125–128 chmod. variable de entorno. 95.hg/store/data. variable de entorno. 68 EMAIL. 134. directorio. 181 opci´ n --after. 86 branches.hg/patches. 120 bundle. 54. fichero. comando. 118 addbreaks. gancho. filtro de plantilla. comando de sistema. 132 branch. 101 o opci´ n -m. 19–21. filtro de plantilla. 155 bisect. 109. 102–108 bisect. 134 filtro person. palabra clave de plantilla. extensi´ n. 135 filtro user.orig.hgignore. 179 . 180 opci´ n --addremove. 125 Mercurial. 96 o basename.rej. 68. 126 changegroup. 74. 118. 49. variable de entorno. extensi´ n o comando convert. 135 filtro age. 135 filtro rfc822date. fichero. variable de entorno. comando. 134 date. 65. 135 189 . 30. 146. 183 acl. comando.hgrc. variable de entorno. 174 o opci´ n -n. 54 cp. 178. 110 convert. fichero. 52 o opci´ n -l. 20. 159. 135 filtro shortdate. 135 backout. comando de sistema. 44.ssh/config. 129 . gancho. 84 o commit. 68 PYTHONPATH. 66 o PATH. 132. fichero. 134 annotate. palabra clave de plantilla. 134 filtro date. 129 . 149 add. comando (extensi´ n conver). palabra clave de plantilla.hg/localtags. 134. 35 .N . 134 filtro email. 36 . 179 . 128. filtro de plantilla. 44.

166. comando de sistema. 171 o extdiff. comando (extensi´ n extdiff). 173 o opci´ n -a. 173 o opci´ n -m. 173 o opci´ n -s. 175 o opci´ n -r. comando. extensi´ n o comando extdiff opci´ n-o. 173 o opci´ n -f. 176 grep. fichero. 135 diffstat. 118 o secci´ n acl. 175. 134 filterdiff. 173 o opci´ n -d. 21. 172 extdiff. 172 o extdiff. 171 domain. fichero secci´ n acl. 13. 158 o opci´ n -x. filtro de plantilla. comando opci´ n -p. 35 fetch. 168 o comando fetch. 120 entrada usermap. 159 o opci´ n -i. 171 o opci´ n -p. 175. 148. 178 hg-interdiff. filtro de plantilla. 148 o opci´ n -p. comando de sistema. 155. 12. 156. 144. palabra clave de plantilla. 28 help. 134 email. 175 secci´ n extdiff. 171. 175 o opci´ n --include. 171 o opci´ n -g.deny. 174 o opci´ n -a. 167 o hgmerge. 165–167. 155. 174 o diff. 133 files. 168. 174 o opci´ n --nodates. 170–172 o comando extdiff. 176 o opci´ n -X. comando. 120 entrada user. 171. comando. 120 entrada password. 119 entrada notify. comando (extensi´ n fetch). 175 o opci´ n --show-function. palabra clave de plantilla. 35. filtro de plantilla. 148. 112 o secci´ n notify. 171 o fetch. fichero. 134 file adds. filtro de plantilla. 167 hgdate. 121 o entrada db. 174–178 opci´ n --exclude. 134 fill76.allow. 174 o opci´ n -b. 101 extdiff. palabra clave de plantilla. 118 o entrada bundle. 120 entrada version. 158 o filterdiff. 158. 174. comando. 174 o opci´ n --ignore-space-change. 172 o secci´ n extensions. 176 o opci´ n --ignore-blank-lines. palabra clave de plantilla. 118 secci´ n bugzilla. filtro de plantilla. 119. 162 header.desc. 139 heads. 63. 171 o opci´ n-p. 173 o email. 133 file dels. extensi´ n. 174–176 o opci´ n --ignore-all-space. 33. 148. comando (extensi´ n patchbomb) o opci´ n --plain. 118 entrada push. 168 o fetch. 173 o opci´ n -b. 19. 174 o opci´ n -N. 143. comando opci´ n --files. 107 guards. 165. comando de sistema. 173 o email. 171 o opci´ n -c. comando (extensi´ n extdiff) o opci´ n -o. 167. 142. 174 o opci´ n --git. 171 o secci´ n hooks. 134 export. 168 ficheros. filtro de plantilla. filtro de plantilla. 165. comando (extensi´ n patchbomb). comando de sistema. 176 o opci´ n -w. 118 entrada sources. comando. comando de sistema. 175 o opci´ n --text. 171. palabra clave de plantilla. 167. 129 hgrc. 119 secci´ n diff o entrada showfunc. 134 foo. 173 diff. extensi´ n. 88 git. 140. 156. 31. 134 hgext. 118 entrada pull. 155 o diffstat. 159 firstline. 175 o opci´ n -C. 35. 170. 132. extensi´ n. 133 fill68. 120 entrada host. palabra clave de plantilla. 175 o opci´ n -I. 159 o opci´ n --hunks. 173 o opci´ n -n. 134 escape. comando. 122 o 190 . 174 o opci´ n --rev. 118 entrada serve. comando de sistema. 118 o secci´ n acl. 105. 177 o opci´ n -B.

extensi´ n.cgi. m´ dulo o clase localrepository. 180 comando qprev. 22. 124 o mercurial. 122 entrada maxdiff. 131 incoming. 167. 152. 33. 74. 178 comando qcommit. 153. 70–74 hgweb. 72–74 hg. 182 comando qunapplied. 18 o lsdiff comando de sistema. 123 entrada contact. 147. 31. 69. 153. 72. 179 o opci´ n-l. gancho. 179 o opci´ n-m. comando. 73. 179 o comando qinit opci´ n-c. 134. 170 o interdiff. 96. 155. 180 comando qpush. 40–42. 73 entrada description. comando. 146. filtro de plantilla. 148. o 114. fichero. 151. 74 entrada stripes. 162 comando qheader. 179 comando qnext. comando (extensi´ n inotify). 176 merge. 83. 145. 182 comando qnew. 124 merge. 156. 145. 135 kdiff3. 123 entrada test. 149. 73 entrada maxfiles. 146. 155. 179 o comando qpop opci´ n-a. 146. 165–167. 151–153. comando de sistema. 73 entrada style. 178. 90. 18 o opci´ n --template. 122. 156 mercurial. 148. 149. fichero. 131. 74 entrada maxchanges. comando de sistema. 143. 68 import. 29. comando de sistema. 74 hgwebdir. 74 hgrc. 181 comando qrename. 74 entrada templates. 179 comando qpop. comando. 156. 131. 178 o comando qfold opci´ n-e. m´ dulo o clase ui. comando. 16. 154.ui. 153. 74. 144. 120. 35. 122 entrada template. 74 entrada allow archive. 182 o comando qnew opci´ n-f. 179 comando qinit. 172 locate. 151. extensi´ n o comando qdel opci´ n-f. 149. 157 log. 170. 158. 178. 182 mq. 152. 178 comando qdelete. 162 comando qseries. comando de sistema. 115. 145. 73. 74 entrada errorlog. 16. 143. 179. 177 incoming. 17 o opci´ n --rev. extensi´ n. 32. 87. 74 entrada address. 155. 172 isodate. 146. 150–153. 135 o opci´ n -p. 181 comando qrestore. 179. 73 entrada motd. fichero de configuraci´ n. 132. 170–172 hgweb. 122 o secci´ n web. 181 comando qtop. 155 mq. 180 o 191 . 74 entrada ipv6. 181 comando qsave. 110.node.localrepo. 151 mq comando de sistema. m´ dulo o funci´ n bin. 73 entrada allowpull. 20 entrada verbose. 154. comando de sistema. fichero. 65. 158. 88. comando. 124 mercurial. 109. 145. 113 secci´ n usermap. 158 lsdiff. 178 comando qfold. 125–128 init. 158. 21. 181 comando qselect. 161.cgi. 155. 90. 17 o opci´ n -r. 73. comando de sistema. 82. 148. 178 inotify. 155. 115. 155 mq. 80. 146. 118–122. 146. 115. 121. 178 comando qguard. 168–170 o comando inserve. 74 entrada name. 179.config. 147. 155. comando de sistema. 146. 123 entrada strip. 153 opci´ n --patch. 34 mpatch. comando. 162. 165. 20. 124 secci´ n ui o entrada username. 110–112. 123 o entrada accesslog. 170. 73 entrada baseurl. 147. 121. 178 comando qdiff. 170 inserve. 179–182 comando qrefresh. 142. 132. 119. 179 o opci´ n-m. 123 entrada sources. 172 o comando qapplied. 74 entrada port. 179 comando qimport.entrada config. 14–18.

113–116. 178 qfold. 101 o opci´ n -p. 73. 180 o opci´ n-n. 80. comando. 151. 143. 109. 178 o qdiff. comando (extensi´ n mq). 150–153. 165. 67 qapplied. 181 o opci´ n-m. 154. o 178 qcommit. 151. 143. gancho. 152. comando. 131 outgoing. 170. 155 opci´ n -u. 180 o opci´ n -f. 179 o qinit. comando (extensi´ n mq) o opci´ n -a. 133 patchbomb. 152. 110. comando (extensi´ n mq). 28. 180 o opci´ n -n. 24. gancho. comando de sistema. 179 o qguard. 178 o qfold. 178 qinit. 126– 128 preupdate. 152. extensi´ n o comando email opci´ n--plain. 68 parents. 122–124. 135 outgoing. 110. comando. 173 o opci´ n-n. 155. 179 o qnext. 112. palabra clave de plantilla. paquete. 146. 178 o qfold. 176 parents. comando (extensi´ n mq) o opci´ n -c. 146. 178. 140. comando (extensi´ n mq).opci´ n-f. 155 qpop. 155. comando (extensi´ n mq). 35. 179. 41. 151. comando (extensi´ n mq). 178 o qdel. comando (extensi´ n mq) o opci´ n -f. filtro de plantilla. filtro de plantilla. 173 o opci´ n-b. 161. 173 o comando email. comando de sistema. comando. 152. 149 patch. 181 o comando qsave opci´ n-c. 23. 126. 109. 153. 179 o opci´ n -m. 148–151. 180 o qprev. 173 o opci´ n-s. 102. 149. 173 o opci´ n-f. 173 o opci´ n-a. 173 o patchutils. 181 o comando qrefresh opci´ n-e. 179. 151. 146. comando. gancho. 152. 88. 152. 177 perl. 173 o opci´ n-d. 30. comando. comando de sistema. o 162. gancho. gancho. comando (extensi´ n mq). 179 o opci´ n -l. 146. 109. 90. 152 o node. 179 o opci´ n -m. 149. 152. 178 o qdelete. 180 o qpop. comando de sistema. 133 filtro short. 181 o opci´ n-l. 127 pageant. 170. 181 o opci´ n-n. 155. comando de sistema. 92. 152. 147. extensi´ n. comando. 155. 24. 155. 22–25. 127 pretag. 129 pretxnchangegroup. 152. comando. 179 o qnew. gancho. 181 o opci´ n -n. 178. comando (extensi´ n mq). 146. 109. 162 qguard. 173 patchbomb. 162 o qheader. 155 qpush. 109. comando (extensi´ n mq) o opci´ n -f. gancho. 109. 146. comando (extensi´ n mq). 170. 69 prechangegroup. gancho. 146 qnew. 146. 112. 168 o obfuscate. 111. 158. 148 o patch. 146. comando. 173 o opci´ n-m. 145. comando (extensi´ n mq). palabra clave de plantilla. 155. 181 o 192 . 119. 182 o qinit. 135 notify. 67 putty. 146. 181 o opci´ n -m. 25. 142. 128 puttygen. 125. extensi´ n. 126. comando (extensi´ n mq) o opci´ n -a. 147. comando (extensi´ n mq) o opci´ n -e. comando (extensi´ n mq). comando (extensi´ n mq). 172. 40. 67. 155. 129 pull. 126. 151. 118. 109. 179–182 qpush. comando (extensi´ n mq). 125–128 precommit. 180 o qpush. 154. comando (extensi´ n mq). 65. 148. comando. 125– 128 pretxncommit. 24 o push. comando (extensi´ n mq). comando de sistema. 158. 29. 165 patch comando de sistema. 128. 66. comando opci´ n --reverse. 182 o qnew. 152. 180 o opci´ n -l. 109. 117 person. 145. 180 o opci´ n-l. 116. 179 o qpop. 180 o comando qpush opci´ n-a. 181 o opci´ n-m. 146. 101. 128. 155. 179 o qimport. 111. 135 plink. 151. 146. 125. 152 o opci´ n-e. 126–129 preoutgoing. 80.

56. 134 fill68. 135 rfc822date. 133 tag. 146. 84 opci´ n -f. 155 opci´ n -C. 182 o qunapplied. 128. 133 rfc822date. 158. comando. comando. 152. comando de sistema. o 181 qtop. 135 193 . 152 o qselect. comando. 135 tags. 178–182 serve. 135 person. 76 sed. 182 strip. 80. 181 opci´ n -C. 101. 145. filtro de plantilla. comando de sistema. 59. comando. 73 tip. 147. 176 vim. 60. 69. 151 zip. comando. 134 domain. 73. 156 o transplant. 83 tags. 181 qrefresh. 153. 135 short. comando (extensi´ n mq). 134 age. 12 sudo. 57 fallo 311. 135 sudo apt-get install mercurial-py25. 149. 159. 135 user. 134 fill76. 152. 24. 67 ssh-keygen. 81. 180. 73. 95. comando de sistema. 73 Base de datos de fallos de Mercurial fallo 29. 162 o qseries. 156. 65 o shortdate. 135 obfuscate. 134. 55 o status. 135 ssh-add. 172 wiggle. 181 opci´ n --after. 12 sudo port install mercurial. 164. 87. 29. 181 opci´ n --after. 167. 144. comando opci´ n -C. 144. 74 opci´ n -p. 69 o ssh. filtro de plantilla. 181 o qrename. comando (extensi´ n mq). 145 rev. 168. 115. filtro de plantilla. 101. comando. 125. 134 escape. 76. 148. 55. 134 firstline. 155. 66–69 status. 88–90. 135 tabindent. 129 tar. gancho. 135 shortdate. 56 o revert. 60. 88. comando de sistema. 84 o tag. 68. 110. comando. 134 date. 152 qsave. 155. 144. filtro de plantilla. 61. 92. o 151–153. 49. comando de sistema. 66 hgrc (Linux/Unix). comando de sistema. 21. 91. 23. comando. 135 version. 179. 90. 68 ssh-agent. comando (extensi´ n mq) o opci´ n -c. palabra clave de plantilla. comando. comando. comando. 182 o remove. 12. 181 o qrestore. 19 series. 131. comando. 67. 114. extensi´ n. 93–95. 179. 152 o opci´ n -e. 42. comando. 109. 44. 35. comando (extensi´ n mq). comando. 135 strip. 182 o opci´ n -f. 172 o unbundle. 182 o opci´ n -n. 169. 155. 67 ssh. 134 hgdate. 134. 55. 135 rollback. 181 o qsave. 152. 76. fichero. 110–112. 149 fichero de configuraci´ n o Mercurial. 181 o opci´ n -m. comando de sistema. 82. 52.ini (Windows). 134 email. comando (extensi´ n mq). comando de sistema. 80. 65. 52. 134 isodate. 53. 58. 156 opci´ n -p. 87. 94. comando (extensi´ n mq). 102 root. 51. filtro de plantilla. comando (extensi´ n mq). 44. comando (extensi´ n mq) o opci´ n -e. 21. 152. 176. 145. 170–172 filtros de plantilla addbreaks. comando (extensi´ n mq). comando de sistema. 19. comando (extensi´ n mq). 181 o qsave. 165. fichero. 128 update. 83 o opci´ n -l. 156. palabra clave de plantilla. 152 o update. 95. 40. 135 short. 134 basename. 121 tabindent. 182 opci´ n -b. 129 urlescape. 101. 52 o rename. 61. 118–122. filtro de plantilla. 83. 74. 131. 152. palabra clave de plantilla. gancho. comando de sistema.qrefresh. comando de sistema. 23. 182 o strip. comando de sistema. 181 o opci´ n -l. 162. 51–53. 91. filtro de plantilla. comando. 56.

tabindent. 125–128 outgoing. 109. 79 o opci´ n --quiet. 133 file dels. 17. 109. 124 HG PARENT1. 127. 134. 90. 65. 109. 79 o palabras clave de plantilla author. 112. 109. 183 194 . 109. 112. 119. 133 parents. 134. 124 HG SOURCE. 128 special tag names qbase. 125 PATH. 125–128 precommit. 118. 126–129 preoutgoing. 77 o opci´ n -v. 132 date. 109. 125. 124. 135 urlescape. 153 qtip. 129 opciones globales opci´ n --debug. 113. 109. 18. 132. 139 node. 125– 128 pretxncommit. 109. 125–128 commit. 132. 115. 18 o opci´ n --verbose. 135 branches. 113–116. 134 file adds. 111. 77. 129 pretxnchangegroup. 127 prechangegroup. 119. 118 o opci´ n --exclude. 20 HGMERGE. 132. 68. 129 incoming. 135 desc. 18. 68 PYTHONPATH. 133 tags tip. 33 HGUSER. 20 HG NODE. 18 o opci´ n -I. 126. 109. 118 bugzilla. 133 tabindent. 116. 119. 134. 13. 129 update. 112. 71. 109. 111. 133 rev. 126. 135 user. 68. 127 pretag. 31. 133 header. 133 files. 79 o opci´ n --include. 109. 135 ganchos acl. 124 HG PARENT2. 110. 126. 129 tag. 135 ficheros. 17. 126–128 preupdate. 79 o opci´ n -q. 128. 13. 110. 135 tags. 128. 113 o opci´ n -X. 112. 112. 120 changegroup. 125 HG URL. 109. 153 variables de entorno EMAIL.