204
 Control Distribu ido de Revisiones con Mercurial Bryan O’Sullivan Copyright c 2006, 2007 Bryan O’Sullivan. Este material puede distribuirse ´ unicamente bajo los t ´ erminos y condiciones establecidos en la versi ´ on 1.0 de la Licencia de Publicaci ´ on Abierta (OPL). Re´ erase por favor al ap´ endice D para 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) .

Control Distribuido de Revisiones Con Mercurial

Embed Size (px)

Citation preview

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 1/204

Control Distribuido de Revisiones con Mercurial

Bryan O’Sullivan

Copyright c 2006, 2007 Bryan O’Sullivan.

Este material puede distribuirse unicamente bajo los terminos y condiciones establecidos en la

version 1.0 de la Licencia de Publicacion Abierta (OPL). Refierase por favor al apendice D para

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) .

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 2/204

Indice general

Indice general I

Prefacio 2

0.1. Este libro es un trabajo en progreso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

0.2. Acerca de los ejemplos en este libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

0.3. Colof on—este libro es Libre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1. Introduccion 31.1. Acerca del control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.1.1. ¿Por que usar control de revisiones? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.1.2. La cantidad de nombres del control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . 4

1.2. Historia resumida del control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.3. Tendencias en el control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.4. Algunas ventajas del control distribuido de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.4.1. Ventajas para proyectos de codigo abierto . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.4.2. Ventajas para proyectos comerciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.5. ¿Por que elegir Mercurial? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.6. Comparacion de Mercurial con otras herramientas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.6.1. Subversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.6.2. Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.6.3. CVS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.6.4. Herramientas comerciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1.6.5. Elegir una herramienta de control de revisiones . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.7. Migrar de otra herramienta hacia Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2. Una gira de Mercurial: lo basico 11

2.1. Instalar Mercurial en su sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.1.1. Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.1.2. Solaris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.1.3. Mac OS X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.1.4. Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.2. Arrancando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.2.1. Ayuda integrada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.3. Trabajar con un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.3.1. Hacer una copia local de un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.3.2. Que hay en un repositorio? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.4. Vistazo rapido al historial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.4.1. Conjuntos de cambios, revisiones, y comunicandose con otras personas . . . . . . . . . . . . 15

2.4.2. Ver revisiones especıficas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.4.3. Informacion mas detallada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

I

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 3/204

2.5. Todo acerca de las opciones para comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.6. Hacer y repasar cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.7. Grabar cambios en un nuevo conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.7.1. Definir un nombre de usuario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.7.2. Escribir un mensaje de consignacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.7.3. Escribir un buen mensaje de consignacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.7.4. Cancelar una consignacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.7.5. Admirar nuestro trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.8. Compartir cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.8.1. Jalar cambios desde otro repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.8.2. Actualizar el directorio de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.8.3. Empujar cambios a otro repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.8.4. Compartir cambios a traves de una red . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

3. Una gira de Mercurial: fusionar trabajo 26

3.1. Fusionar lıneas de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3.1.1. Conjuntos de cambios de frentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.1.2. Hacer la fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.1.3. Consignar los resultados de la fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3.2. Fusionar cambios con conflictos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303.2.1. Usar una herramienta grafica para fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.2.2. Un ejemplo real . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3.3. Simplificar el ciclo jalar-fusionar-consignar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

4. Tras bambalinas 36

4.1. Registro del historial de Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.1.1. Seguir el historial de un unico fichero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.1.2. Administracion de ficheros monitoreados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.1.3. Registro de informacion del conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . . . 36

4.1.4. Relaciones entre revisiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

4.2. Almacenamiento seguro y eficiente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

4.2.1. Almacenamiento eficiente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

4.2.2. Operacion segura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384.2.3. Recuperacion rapida de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

4.2.4. Identificacion e integridad fuerte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

4.3. Historial de revisiones, ramas y fusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

4.4. El directorio de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

4.4.1. Que pasa en una consignacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

4.4.2. Creacion de un nuevo frente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

4.4.3. Fusion de frentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

4.5. Otras caracterısticas de diseno interesantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

4.5.1. Compresion ingeniosa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

4.5.2. Reordenado de lectura/escritura y atomicidad . . . . . . . . . . . . . . . . . . . . . . . . . . 42

4.5.3. Acceso concurrente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

4.5.4. Evitar movimientos de brazo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

4.5.5. Otros contenidos del estado de directorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

5. Mercurial dıa a dıa 49

5.1. Como indicarle a Mercurial que ficheros seguir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

5.1.1. Nombramiento explıcito e implıcito de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . 49

5.1.2. Nota al margen: Mercurial trata ficheros, no directorios . . . . . . . . . . . . . . . . . . . . . 50

5.2. Como dejar de hacer seguimiento a un fichero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

II

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 4/204

5.2.1. Al eliminar un fichero no se afecta su historial . . . . . . . . . . . . . . . . . . . . . . . . . . 51

5.2.2. Ficheros perdidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

5.2.3. Nota al margen: ¿Por que decirle explıcitamente a Mercurial que elimine un fichero? . . . . . 52

5.2.4. Atajo util—agregar y eliminar ficheros en un solo paso . . . . . . . . . . . . . . . . . . . . . 52

5.3. Copiar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

5.3.1. Resultados de copiar un fichero durante una fusion . . . . . . . . . . . . . . . . . . . . . . . 53

5.3.2. ¿Por que los cambios se reflejan en las copias? . . . . . . . . . . . . . . . . . . . . . . . . . 545.3.3. Como hacer que los cambios no sigan a la copia? . . . . . . . . . . . . . . . . . . . . . . . . 54

5.3.4. Comportamiento de la orden “hg copy” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

5.4. Renombrar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

5.4.1. Renombrar ficheros y fusionar cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

5.4.2. Cambios de nombre divergentes y fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

5.4.3. Cambios de nombre convergentes y fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

5.4.4. Otros casos lımite relacionados con renombramientos . . . . . . . . . . . . . . . . . . . . . . 57

5.5. Recuperarse de equivocaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

6. Colaborar con otros 59

6.1. La interfaz web de Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

6.2. Modelos de colaboracion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

6.2.1. Factores a tener en cuenta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606.2.2. Anarquıa informal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

6.2.3. Un repositorio central unico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

6.2.4. Trabajo con muchas ramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

6.2.5. Ramas de caracterısticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

6.2.6. El tren de publicacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

6.2.7. El modelo del kernel Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

6.2.8. Solamente jalar frente a colaboracion publica . . . . . . . . . . . . . . . . . . . . . . . . . . 64

6.2.9. Cuando la colaboracion encuentra la administracion ramificada . . . . . . . . . . . . . . . . 64

6.3. Aspectos tecnicos de la colaboracion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

6.4. Compartir informalmente con “hg serve” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

6.4.1. Cuestiones adicionales para tener en cuenta . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

6.5. Uso del protocolo Secure Shell (ssh) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

6.5.1. Como leer y escribir URLs de ssh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666.5.2. Encontrar un cliente ssh para su sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

6.5.3. Generar un par de llaves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

6.5.4. Uso de un agente de autenticacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

6.5.5. Configurar el lado del servidor apropiadamente . . . . . . . . . . . . . . . . . . . . . . . . . 67

6.5.6. Compresion con ssh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

6.6. Servir sobre HTTP usando CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

6.6.1. Lista de chequeo de la configuracion del servidor web . . . . . . . . . . . . . . . . . . . . . 69

6.6.2. Configuracion basica de CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

6.6.3. Compartir varios repositorios con un guion CGI . . . . . . . . . . . . . . . . . . . . . . . . . 72

6.6.4. Descarga de ficheros fuente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

6.6.5. Opciones de configuracion en Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

7. Nombres de ficheros y asociacion de patrones 757.1. Nombrado de ficheros simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

7.2. Ejecucion de comandos sin ningun nombre de fichero . . . . . . . . . . . . . . . . . . . . . . . . . . 75

7.3. Reportar que esta pasando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

7.4. Uso de patrones para identificar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

7.4.1. Patrones glob estilo interprete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

7.4.2. Asociacion con patrones de expresiones regulares re . . . . . . . . . . . . . . . . . . . . . . 78

II I

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 5/204

7.5. Filtrado de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

7.6. Ignorar ficheros y directorios no deseados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

7.7. Sensibilidad a mayusculas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

7.7.1. Almacenamiento portable y seguro de repositorios . . . . . . . . . . . . . . . . . . . . . . . 80

7.7.2. Deteccion de conflictos de mayusculas/minusculas . . . . . . . . . . . . . . . . . . . . . . . 80

7.7.3. Arreglar un conflicto de mayusculas/minusculas . . . . . . . . . . . . . . . . . . . . . . . . 80

8. Administracion de versiones y desarrollo ramificado 81

8.1. Dar un nombre persistente a una revision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

8.1.1. Manejo de conflictos entre etiquetas durante una fusion . . . . . . . . . . . . . . . . . . . . . 83

8.1.2. Etiquetas y clonado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

8.1.3. Cuando las etiquetas permanentes son demasiado . . . . . . . . . . . . . . . . . . . . . . . . 84

8.2. El flujo de cambios—El gran cuadro vs. el pequeno . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

8.3. Administrar ramas en repositorios estilo gran cuadro . . . . . . . . . . . . . . . . . . . . . . . . . . 84

8.4. No repita trabajo: fusion entre ramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

8.5. Nombrar ramas dentro de un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

8.6. Tratamiento de varias ramas nombradas en un repositorio . . . . . . . . . . . . . . . . . . . . . . . . 88

8.7. Nombres de ramas y fusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

8.8. Normalmente es util nombrar ramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

9. Encontrar y arreglar sus equivocaciones 91

9.1. Borrar el historial local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

9.1.1. La consignacion accidental . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

9.1.2. Hacer rollback una transaccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

9.1.3. Erroneamente jalado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

9.1.4. Despues de publicar, un roll back es futil . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

9.1.5. Solamente hay un roll back . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

9.2. Revertir un cambio equivocado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

9.2.1. Errores al administrar ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

9.3. Tratar cambios consignados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

9.3.1. Retroceder un conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

9.3.2. Retroceder el conjunto de cambios punta . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

9.3.3. Retroceso de un cambio que no es la punta . . . . . . . . . . . . . . . . . . . . . . . . . . . 969.3.4. Mas control sobre el proceso de retroceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

9.3.5. Por que “hg backout” hace lo que hace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

9.4. Cambios que nunca debieron ocurrir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

9.4.1. Como protegerse de cambios que han “escapado” . . . . . . . . . . . . . . . . . . . . . . . . 102

9.5. Al encuentro de la fuente de un fallo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

9.5.1. Uso de la orden “hg bisect” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

9.5.2. Limpieza despues de la busqueda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

9.6. Consejos para encontrar fallos efectivamente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

9.6.1. Dar una entrada consistente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

9.6.2. Automatizar tanto como se pueda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

9.6.3. Verificar los resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

9.6.4. Tener en cuenta la interferencia entre fallos . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

9.6.5. Acotar la busqueda perezosamente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

10. Manejo de eventos en repositorios mediante ganchos 109

10.1. Vistazo general de ganchos en Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

10.2. Ganchos y seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

10.2.1. Los ganchos se ejecutan con sus privilegios de usuario . . . . . . . . . . . . . . . . . . . . . 110

10.2.2. Los ganchos no se propagan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

IV

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 6/204

10.2.3. Es posible hacer caso omiso de los ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

10.2.4. Asegurarse de que ganchos crıticos sean ejecutados . . . . . . . . . . . . . . . . . . . . . . . 111

10.3. Precauciones con ganchos pretxn en un repositorio de acceso compartido . . . . . . . . . . . . . . . 111

10.3.1. Ilustracion del problema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

10.4. Tutorial corto de uso de ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

10.4.1. Llevar a cabo varias acciones por evento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

10.4.2. Controlar cuando puede llevarse a cabo una actividad . . . . . . . . . . . . . . . . . . . . . . 11310.5. Escribir sus propios ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

10.5.1. Escoger como debe ejecutarse su gancho . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

10.5.2. Parametros para ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

10.5.3. Valores de retorno de ganchos y control de actividades . . . . . . . . . . . . . . . . . . . . . 114

10.5.4. Escribir un gancho externo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

10.5.5. Indicar a Mercurial que use un gancho interno . . . . . . . . . . . . . . . . . . . . . . . . . . 115

10.5.6. Escribir un gancho interno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

10.6. Ejemplos de ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

10.6.1. Escribir mensajes de consignacion significativos . . . . . . . . . . . . . . . . . . . . . . . . 115

10.6.2. Comprobar espacios en blanco finales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

10.7. Ganchos adicionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

10.7.1. acl—control de acceso a partes de un repositorio . . . . . . . . . . . . . . . . . . . . . . . . 117

10.7.2. bugzilla—integracion con Bugzilla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11910.7.3. notify—enviar notificaciones de correo electronico . . . . . . . . . . . . . . . . . . . . . . 122

10.8. Informacion para escritores de ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

10.8.1. Ejecucion de ganchos internos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

10.8.2. Ejecucion de ganchos externos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

10.8.3. Averiguar de donde vienen los conjuntos de cambios . . . . . . . . . . . . . . . . . . . . . . 125

10.9. Referencia de ganchos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

10.9.1. changegroup—luego de anadir conjuntos de cambios remotos . . . . . . . . . . . . . . . . . 125

10.9.2. commit—luego de la creacion de un nuevo conjunto de cambios . . . . . . . . . . . . . . . . 126

10.9.3. incoming—luego de que un conjunto de cambios remoto es anadido . . . . . . . . . . . . . 126

10.9.4. outgoing—luego de la propagacion de los conjuntos de cambios . . . . . . . . . . . . . . . 126

10.9.5. prechangegroup—antes de empezar la adicion de conjuntos de cambios remotos . . . . . . 127

10.9.6. precommit—antes de iniciar la consignacion de un conjunto de cambios . . . . . . . . . . . 127

10.9.7. preoutgoing—antes de empezar la propagacion de conjuntos de cambios . . . . . . . . . . 12710.9.8. pretag—antes de etiquetar un conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . 128

10.9.9. pretxnchangegroup —antes de completar la adicion de conjuntos de cambios remotos . . . . 128

10.9.10.pretxncommit—antes de completar la consignacion de un nuevo conjunto de cambios . . . . 128

10.9.11.preupdate—antes de actualizar o fusionar el directorio de trabajo . . . . . . . . . . . . . . . 129

10.9.12.tag—luego de etiquetar un conjunto de cambios . . . . . . . . . . . . . . . . . . . . . . . . 129

10.9.13.update—luego de actualizar o fusionar el directorio de trabajo . . . . . . . . . . . . . . . . . 129

11. Personalizar los mensajes de Mercurial 130

11.1. Usar estilos que vienen con Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

11.1.1. Especificar un estilo predeterminado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

11.2. Ordenes que soportan estilos y plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

11.3. Cuestiones basicas de plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

11.4. Palabras claves mas comunes en las plantillas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

11.5. Secuencias de Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

11.6. Uso de filtros con palabras claves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

11.6.1. Combinar filtros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

11.7. De plantillas a estilos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

11.7.1. Los ficheros de estilo mas sencillos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

11.7.2. Sintaxis de ficheros de estilo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

V

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 7/204

11.8. Ejemplos de ficheros de estilos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

11.8.1. Identificar equivocaciones en ficheros de estilo . . . . . . . . . . . . . . . . . . . . . . . . . 137

11.8.2. Identificar de forma unica un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

11.8.3. Mostrando salida parecida a Subversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

12. Administracion de cambios con Colas de Mercurial 140

12.1. El problema de la administracion de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14012.2. La prehistoria de las Colas de Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

12.2.1. Trabajar parches con quilt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

12.2.2. Pasar de trabajo con parches con Quilt hacia Colas de Mercurial . . . . . . . . . . . . . . . . 141

12.3. La gran ventaja de MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

12.4. Entender los parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

12.5. Comenzar a usar Colas de Mercurial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

12.5.1. Crear un nuevo parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

12.5.2. Refrescar un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

12.5.3. Aplicar un parche tras otro y dar seguimiento . . . . . . . . . . . . . . . . . . . . . . . . . . 145

12.5.4. Manipular la pila de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

12.5.5. Introducir y sustraer muchos parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

12.5.6. Medidas de seguridad y como saltarlas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

12.5.7. Trabajar con varios parches a la vez . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14712.6. Mas acerca de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

12.6.1. La cantidad de franjas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

12.6.2. Estrategias para aplicar parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

12.6.3. Algunos detalles de la representacion de parches . . . . . . . . . . . . . . . . . . . . . . . . 150

12.6.4. Cuidado con los difusos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

12.6.5. Manejo de descartes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

12.7. maximizar el rendimiento de MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

12.8. Actualiar los parches cuando el codigo cambia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

12.9. Identificar parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

12.10.Otra informacion util . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

12.11.Administrar parches en un repositorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

12.11.1.Soporte de MQ para repositorios de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

12.11.2.Detalles a tener en cuenta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15512.12.Otras herramientas para trabajar con parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

12.13.Buenas practicas de trabajo con parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

12.14.Recetas de MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156

12.14.1.Administrar parches “triviales” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156

12.14.2.Combinar parches completos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

12.14.3.Fusionar una porcion de un parche dentro de otro . . . . . . . . . . . . . . . . . . . . . . . . 158

12.15.Diferencias entre quilt y MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159

13. Usos avanzados de las Colas de Mercurial 160

13.1. El problema de multiples objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

13.1.1. Aproximaciones tentadoras que no funcionan adecuadamente . . . . . . . . . . . . . . . . . 160

13.2. Aplicar parches condicionalmente mediante guardias . . . . . . . . . . . . . . . . . . . . . . . . . . 161

13.3. Controlar los guardias de un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16113.4. Selecccionar los guardias a usar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

13.5. Reglas de MQ para aplicar parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

13.6. Podar el entorno de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

13.7. Dividir el fichero series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

13.8. Mantener la serie de parches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

13.8.1. El arte de escribir parches de backport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

VI

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 8/204

13.9. Consejos utiles para hacer desarrollo con MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

13.9.1. Organizar parches en directorios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

13.9.2. Ver el historial de un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

14. A ˜ nadir funcionalidad con extensiones 168

14.1. Mejorar el desempeno con la extension inotify . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

14.2. Soporte flexible de diff con la extension extdiff . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17014.2.1. Definicion de alias de comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

14.3. Uso de la extension transplant para seleccionar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

14.4. Enviar cambios vıa correo electronico con la extension patchbomb . . . . . . . . . . . . . . . . . . . 172

14.4.1. Cambiar el comportamiento de las bombas de parches . . . . . . . . . . . . . . . . . . . . . 173

A. Referencia de Ordenes 175

A.1. “hg add”—Anade ficheros en la proxima consignacion . . . . . . . . . . . . . . . . . . . . . . . . . 175

A.2. “hg diff”—imprime los cambios en el historial o el directorio actual . . . . . . . . . . . . . . . . . 175

A.2.1. Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

A.3. “hg version”—imprime la informacion de version y derechos de reproduccion . . . . . . . . . . . . 177

A.3.1. Consejos y trucos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

B. Referencia de las Colas de Mercurial 179

B.1. Referencia de ordenes MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

B.1.1. “hg qapplied”—imprimir los parches aplicados . . . . . . . . . . . . . . . . . . . . . . . . 179

B.1.2. “hg qcommit”—consignar cambios en la cola del repositorio . . . . . . . . . . . . . . . . . 179

B.1.3. “hg qdelete”—eliminar un parche del fichero series . . . . . . . . . . . . . . . . . . . . 179

B.1.4. “hg qdiff”—imprimir la diferencia del ultimo parche aplicado . . . . . . . . . . . . . . . . 179

B.1.5. “hg qfold”—fusionar (“integrar”) varios parches en uno solo . . . . . . . . . . . . . . . . . 179

B.1.6. “hg qheader”—desplegar el encabezado/descripcion de un parche . . . . . . . . . . . . . . 180

B.1.7. “hg qimport”—importar el parche de un tercero en la cola . . . . . . . . . . . . . . . . . . 180

B.1.8. “hg qinit”—preparar un repositorio para trabajar con MQ . . . . . . . . . . . . . . . . . . 180

B.1.9. “hg qnew”—crear un parche nuevo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

B.1.10. “hg qnext”—imprimir el nombre del proximo parche . . . . . . . . . . . . . . . . . . . . . 180

B.1.11. “hg qpop”—sustraer parches de la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181

B.1.12. “hg qprev”—imprimir el nombre del parche anterior . . . . . . . . . . . . . . . . . . . . . 181B.1.13. “hg qpush”—introducir parches a la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181

B.1.14. “hg qrefresh”—actualiza el ultimo parche aplicado . . . . . . . . . . . . . . . . . . . . . . 182

B.1.15. “hg qrename”—renombrar un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182

B.1.16. “hg qrestore”—restaurar el estado almacenado de la cola . . . . . . . . . . . . . . . . . . 182

B.1.17. “hg qsave”—almacena el estado actual de la cola . . . . . . . . . . . . . . . . . . . . . . . 182

B.1.18. “hg qseries”—imprime la serie completa de parches . . . . . . . . . . . . . . . . . . . . . 182

B.1.19. “hg qtop”—imprime el nombre del parche actual . . . . . . . . . . . . . . . . . . . . . . . 183

B.1.20. “hg qunapplied”—imprimir los parches que aun no se han aplicado . . . . . . . . . . . . . 183

B.1.21. “hg strip”—remover una revision y sus descendientes . . . . . . . . . . . . . . . . . . . . 183

B.2. Referencia de ficheros de MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

B.2.1. El fichero series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

B.2.2. El fichero status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

C. Instalar Mercurial desde las fuentes 184

C.1. En un sistema tipo Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

C.2. En Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

VI I

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 9/204

D. Licencia de Publicacion Abierta 185

D.1. Requerimientos en versiones modificadas y no modificadas . . . . . . . . . . . . . . . . . . . . . . . 185

D.2. Derechos de reproduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

D.3. Alcance de la licencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

D.4. Requerimientos sobre trabajos modificados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

D.5. Recomendaciones de buenas practicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

D.6. Opciones de licencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

Bibliograf ıa 188

Indice alfabetico 188

VIII

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 10/204

Indice de figuras

2.1. Historial grafico del repositorio hello . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3.1. Historial reciente divergente de los repositorios my-hello y my-new-hello . . . . . . . . . . . . . . 27

3.2. Contenidos del repositorio despues de jalar my-hello a my-new-hello . . . . . . . . . . . . . . . . 28

3.3. Directorio de trabajo y repositorio durante la fusion, y consignacion consecuente . . . . . . . . . . . 29

3.4. Cambios con conflictos a un documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.5. Usando kdiff3 para fusionar versiones de un fichero . . . . . . . . . . . . . . . . . . . . . . . . . . 32

4.1. Relacion entre ficheros en el directorio de trabajo y ficheros de registro en el repositorio . . . . . . . . 374.2. Relaciones entre metadatos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

4.3. Instantanea de un revlog, con deltas incrementales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

4.4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

4.5. El directorio de trabajo puede tener dos padres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

4.6. El directorio de trabajo obtiene nuevos padres luego de una consignacion . . . . . . . . . . . . . . . 46

4.7. El directorio de trabajo, actualizado a un conjunto de cambios anterior . . . . . . . . . . . . . . . . . 47

4.8. Despues de una consignacion hecha mientras se usaba un conjunto de cambios anterior . . . . . . . . 47

4.9. Fusion de dos frentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

5.1. Simular un directorio vacıo con un fichero oculto . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

6.1. Ramas de Caracterısticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

9.1. Retroceso de un cambio con la orden “hg backout” . . . . . . . . . . . . . . . . . . . . . . . . . . 97

9.2. Retroceso automatizado de un cambio a algo que no es la punta con la orden “hg backout” . . . . . 98

9.3. Retroceso usando la orden “hg backout” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

9.4. Fusion manual de un retroceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

10.1. Un gancho simple que se ejecuta al hacer la consignaci on de un conjunto de cambios . . . . . . . . . 112

10.2. Definicion de un segundo gancho commit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

10.3. Uso del gancho pretxncommit para controlar consignaciones . . . . . . . . . . . . . . . . . . . . . 114

10.4. Un gancho que prohıbe mensajes de consignacion demasiado cortos . . . . . . . . . . . . . . . . . . 116

10.5. Un gancho simple que revisa si hay espacios en blanco finales . . . . . . . . . . . . . . . . . . . . . 116

10.6. Un mejor gancho para espacios en blanco finales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

11.1. Template keywords in use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

11.2. Filtros de plantilla en accion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

12.1. Uso sencillo de las ordenes diff y patch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

12.2. Lıneas a anadir en ˜/.hgrc para habilitar la extension MQ . . . . . . . . . . . . . . . . . . . . . . . 143

12.3. Como verificar que MQ esta habilitado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

12.4. Preparar un repositorio para usar MQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

12.5. Crear un nuevo parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

IX

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 11/204

12.6. Refrescar un parche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

12.7. Refrescar un parche muchas veces para acumular cambios . . . . . . . . . . . . . . . . . . . . . . . 146

12.8. Aplicar un parche despues del primero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

12.9. Entender la pila de parches con “hg qseries” y “hg qapplied” . . . . . . . . . . . . . . . . . . . 148

12.10.Parches aplicados y no aplicados en la pila de parches de MQ . . . . . . . . . . . . . . . . . . . . . . 148

12.11.Modificar la pila de parches aplicados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

12.12.Pushing all unapplied patches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14912.13.Crear un parche a la fuerza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

12.14.Uso de las caracterısticas de etiquetamiento al trabajar con MQ . . . . . . . . . . . . . . . . . . . . . 154

12.15.Las ordenes diffstat, filterdiff, y lsdiff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156

1

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 12/204

Prefacio

El control distribuido de revisiones es un territorio relativamente nuevo, y ha crecido hasta ahora gracias a a la

voluntad que tiene la gente de salir y explorar territorios desconocidos.

Estoy escribiendo este libro acerca de control de revisiones distribuido porque creo que es un tema importante

que merece una guıa de campo. Escogı escribir acerca de Mercurial porque es la herramienta mas facil para explorar

el terreno, y sin embargo escala a las demandas de retadores ambientes reales donde muchas otras herramientas de

control de revisiones fallan.

0.1. Este libro es un trabajo en progresoEstoy liberando este libro mientras lo sigo escribiendo, con la esperanza de que pueda ser util a otros. Tambien

espero que los lectores contribuiran como consideren adecuado.

0.2. Acerca de los ejemplos en este libro

Este libro toma un enfoque inusual hacia las muestras de codigo. Cada ejemplo esta “en directo”—cada uno es

realmente el resultado de un script de shell que ejecuta los comandos de Mercurial que usted ve. Cada vez que una

copia del libro es construida desde su codigo fuente, todos los scripts de ejemplo son ejecutados automaticamente, y

sus resultados actuales son comparados contra los resultados esperados.

La ventaja de este enfoque es que los ejemplos siempre son precisos; ellos describen exactamente el compor-

tamiento de la version de Mercurial que es mencionada en la portada del libro. Si yo actualizo la version de Mercurialque estoy documentando, y la salida de algun comando cambia, la construccion falla.

Hay una pequena desventaja de este enfoque, que las fechas y horas que usted vera en los ejemplos tienden a

estar “aplastadas” juntas de una forma que no serıa posible si los mismos comandos fueran escritos por un humano.

Donde un humano puede emitir no mas de un comando cada pocos segundos, con cualquier marca de tiempo resultante

correspondientemente separada, mis scripts automatizados de ejemplos ejecutan muchos comandos en un segundo.

Como un ejemplo de esto, 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 seccion 9.5, por ejemplo.

Ası que cuando usted lea los ejemplos, no le d e mucha importancia a las fechas o horas que vea en las salidas de

los comandos. Pero tenga confianza en que el comportamiento que esta viendo es consistente y reproducible.

0.3. Colof on—este libro es Libre

Este libro esta licenciado bajo la Licencia de Publicacion Abierta, y es producido en su totalidad usando herramien-

tas de Software Libre. Es compuesto con LATEX; las ilustraciones son dibujadas y generadas con Inkscape.

Elcodigo fuente completo para este libro es publicado como un repositorio Mercurial, en http://hg.serpentine .

com/mercurial/book .

2

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 13/204

Capıtulo 1

Introduccion

1.1. Acerca del control de revisiones

El control de revisiones es el proceso de administrar diferentes versiones de una pieza de informaci on. En su forma

mas simple es algo que la mayorıa de gente hace a mano: cada vez que usted modifica un fichero, lo graba con un

nuevo nombre que contiene un numero, cada uno mayor que el anterior.Administrar manualmente muchas versiones de incluso solo un fichero es una tarea propensa a errores, a pesar de

que hace bastante tiempo hay herramientas que ayudan en este proceso. Las primeras herramientas para automatizar

el control de revisiones fueron pensadas para que un usuario administrara un solo fichero. En las decadas pasadas, el

alcance de las herramientas de control de revisiones ha ido aumentando considerablemente; ahora manejan muchos

ficheros y facilitan el trabajo en conjunto de varias personas. 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.1.1. ¿Por que usar control de revisiones?

Hay muchas razones por las cuales usted o su equipo desearıa usar una herramienta automatica de control de

revisiones para un proyecto.

Llevar registro del historial y la evolucion de su proyecto, para evitar hacer la tarea manualmente. Por cada

cambio, tendra una bitacora de qui´ en lo hizo; por qu´ e se hizo; cu´ ando se hizo; y de qu´ e se trataba el cambio.

Cuando trabaja con mas personas, los programas de control de revisiones facilitan la colaboraci on. Por ejemplo,

cuando varias personas hacen cambios potencialmente incompatibles de forma casi simult anea, el programa le

ayudara a identificar y resolver tales conflictos.

Puede ayudarle a recuperarse de equivocaciones. Si aplica un cambio que posteriormente se evidencia como

un error, puede revertirlo a una version previa a uno o muchos ficheros. De hecho, una herramienta realmente

buena, incluso puede ayudarle efectivamente a darse cuenta exactamente cuando se introdujo el error (para mas

detalles ver la seccion 9.5).

Le ayudara a trabajar simultaneamente, y a manejar las diferencias entre multiples versiones de su proyecto.

La mayorıa de estas razones son igualmente validas —por lo menos en teorıa— ası este trabajando en un proyecto

solo usted, o con mucha gente.

Algo fundamental acerca de lo practico de un sistema de control de revisiones en estas dos escalas (“un hacker

solitario” y “un equipo gigantesco”) es como se comparan los beneficios con los costos. Una herramienta de control

de revisiones que sea dif ıcil de entender o usar impondra un costo alto.

3

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 14/204

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. En este caso, el costo de usar control de revisiones ni siquiera se

tiene en cuenta, puesto que sin el, el fracaso esta casi garantizado.

Por otra parte, un “arreglo rapido” de una sola persona, excluirıa la necesidad de usar una herramienta de control

de revisiones, porque casi seguramente, el costo de usar una estarıa cerca del costo del proyecto. ¿No es ası?

Mercurial soporta ambas escalas de de desarrollo de manera unica. Puede aprender lo basico en pocos minutos, y

dado su bajo sobrecosto, puede aplicar el control de revisiones al proyecto mas pequeno con facilidad. Su simplicidadsignifica que no tendra que preocuparse por conceptos obtusos o secuencias de ordenes compitiendo por espacio

mental con lo que sea que realmente este tratando de hacer. Al mismo tiempo, Mercurial tiene alto desempeno y su

naturaleza peer-to-peer le permite escalar indoloramente para manejar grandes proyectos.

Ninguna herramienta de control de revisiones puede salvar un proyecto mal administrado, pero la elecci on de

herramientas puede hacer una gran diferencia en la fluidez con la cual usted puede trabajar en un proyecto.

1.1.2. La cantidad de nombres del control de revisiones

El control de revisiones es un campo amplio, tan amplio que no hay un acronimo o nombre unico. A continuacion

presentamos un listado de nombres comunes y acronimos que se podrıan encontrar:

Control de revisiones (RCS)

Manejo de Configuraciones de Programas (SCM), o administracon de configuraciones

Administracion de codigo fuente

Control de Codigo Fuente, o Control de Fuentes

Control de Versiones (VCS)

Algunas personas aducen que estos terminos tienen significados diversos, pero en la practica se sobreponen tanto que

no hay una forma acordada o incluso adecuada de separarlos.

1.2. Historia resumida del control de revisiones

La herramienta de control de revisiones mas antigua conocida es SCCS (Sistema de Control de Codigo), escrito

por Marc Rochkind en Bell Labs, a comienzos de los setentas (1970s). SCCS operaba sobre ficheros individuales, y

requerıa que cada persona que trabajara en el proyecto tuviera acceso a un espacio compartido en un solo sistema.

Solamente una persona podıa modificar un fichero en un momento dado; el arbitramiento del acceso a los ficheros

se hacıa con candados. Era comun que la gente pusiera los candados a los ficheros, y que posteriormente olvidara

quitarlos, impidiendo que otro pudiera modificar los ficheros en cuesti on sin la intervencion del administrador.

Walter Tichy desarrollo una alternativa gratuita a SCCS a comienzos de los ochentas (1980s); llamo a su programa

RCS (Sistema de Control de Revisiones). Al igual que SCCS, 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

simultaneamente.

Despues en los ochenta, Dick Grune uso RCS como un bloque de construccion para un conjunto de guiones de

lınea de comando, que inicialmente llamo cmt, pero que renombro a CVS (Sistema Concurrente de Versiones). La

gran innovacion de CVS era que permitıa a los desarrolladores trabajar simultaneamente de una forma mas o menos

independiente en sus propios espacios de trabajo. Los espacios de trabajo personales impedıan que los desarrolladoresse pisaran las mangueras todo el tiempo, situacion comun con SCCS y RCS. Cada desarrollador tenıa una copia de

todos los ficheros del proyecto y podıa modificar sus copias independientemente, Tenıan que fusionar sus ediciones

antes de consignar los cambios al repositorio central.

Brian Berliner tomo los scripts originales de Grune y los reescribio en C, publicando en 1989 el codigo sobre el

cual se ha desarrollado la version moderna de CVS. CVS adquirio posteriormente la habilidad de operar sobre una

conexion de red, dotandolo de una arquitectura, cliente/servidor. La arquitectura de CVS es centralizada; el historial

del proyecto esta unicamente en el repositorio central. Los espacios de trabajo de los clientes contienen unicamente

4

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 15/204

copias recientes de las versiones de los ficheros, y pocos metadatos para indicar donde esta el servidor. CVS ha tenido

un exito enorme; Es probablemente el sistema de control de revisiones mas extendido del planeta.

A comienzos de los noventa (1990s), Sun MicroSystems desarrollo un temprano sistema distribuido de control

de revisiones llamado TeamWare. Un espacio de trabajo TeamWare contiene una copia completa del historial del

proyecto. TeamWare no tiene la nocion de repositorio central. (CVS se basaba en RCS para el almacenamiento de su

historial; TeamWare usaba SCCS.)

A medida que avanzaba la decada de los noventa, se empezo a evidenciar los problemas de CVS. Almacenacambios simultaneos a muchos ficheros de forma individual, en lugar de agruparlos como una operacion unica y

atomica logicamente. No maneja bien su jerarquıa de ficheros; es f acil desordenar un repositorio al renombrar ficheros

y directorios. Peor aun, su codigo fuente es difıcil de leer y mantener, lo que hizo que su “umbral de dolor” para

arreglar sus problemas arquitecturales fuera algo prohibitivo.

En 2001, Jim Blandy y Karl Fogel, dos desarrolladores que hab ıan trabajado en CVS, comenzaron un proyecto

para reemplazarlo con una herramienta con mejor arquitectura y codigo mas limpio. El resultado, Subversion, no

se separo del modelo centralizado cliente/servidor de CVS, pero anadio consignaciones atomicas de varios ficheros,

mejor manejo de espacios de nombres , y otras caracterısticas que lo hacen mejor que CVS. Desde su version inicial,

ha ido creciendo en popularidad rapidamente.

Mas o menos en forma simultanea Graydon Hoare comenzo a trabajar en un ambicioso sistema distribuido de

control de versiones que llamo Monotone. Mientras que Monotone se enfocaba a evitar algunas fallas de dise no de

CVS con una arquitectura peer-to-peer, fue mucho mas alla de las herramientas anteriores (y posteriores) de control de

revisiones en varios aspectos innovadores. Usa hashes criptograficos como identificadores, y tiene una nocion integralde “confianza” para codigo de diversas fuentes.

Mercurial nacio en el 2005. Algunos de sus aspectos de de diseno fueron influenciados por Monotone, pero Mer-

curial se enfoca en la facilidad de uso, gran rendimiento y escalabilidad para proyectos muy grandes.

1.3. 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 decadas pasadas, mientras la gente se ha hecho familiar con las capacidades de sus herramientas y se ha visto

restringida por sus limitaciones.

La primera generacion comenzo administrando ficheros individuales en computadores por persona. A pesar de que

tales herramientas representaron un avance importante frente al control de revisiones manual, su modelo de candados

y la dependencia a un solo computador los limito a equipos de trabajo pequenos y acoplados.La segunda generacion dejo atras esas limitaciones moviendose a arquitecturas centradas en redes, y administrando

proyectos completos a la vez. A medida que los proyectos crecıan, nacieron nuevos problemas. Con la necesidad de

comunicacion frecuente con los servidores, escalar estas maquinas se convirtio en un problema en proyectos realmente

grandes. Las redes con poca estabilidad podrıan impedir que usuarios remotos se conectaran al servidor. A medida que

los proyectos de codigo abierto comenzaron a ofrecer acceso de solo lectura de forma anonima a cualquiera, la gente

sin permiso para consignar vio que no podıan usar tales herramientas para interactuar en un proyecto de forma natural,

puesto que no podıan guardar sus cambios.

La generacion actual de herramientas de control de revisiones es peer-to-peer por naturaleza. Todos estos sistemas

han eliminado la dependencia de un unico servidor central, y han permitido que la gente distribuya sus datos de control

de revisiones donde realmente se necesita. La colaboracion a traves de Internet ha cambiado las limitantes tecnologicas

por la cuestion de eleccion y consenso. Las herramientas modernas pueden operar sin conexi on indefinidamente y

autonomamente, necesitando una conexion de red solamente para sincronizar los cambios con otro repositorio.

1.4. Algunas ventajas del control distribuido de revisiones

A pesar de que las herramientas para el control distribuido de revisiones lleva varios anos siendo tan robustas y

usables como la generacion previa de sus contrapartes, algunas personas que usan las herramientas mas antiguas no

se han percatado de sus ventajas. Hay gran cantidad de situaciones en las cuales las herramientas distribuidas brillan

frente a las centralizadas.

5

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 16/204

Para un desarrollador individual, las herramientas distribuidas casi siempre son mas rapidas que las centralizadas.

Por una razon sencilla: Una herramienta centralizada necesita comunicarse por red para las operaciones m as usuales,

debido a que los metadatos se almacenan en una sola copia en el servidor central. Una herramienta distribuida almacena

todos sus metadatos localmente. Con todo lo demas de la misma forma, comunicarse por red tiene un sobrecosto en

una herramienta centralizada. No subestime el valor de una herramienta de respuesta rapida: Usted empleara mucho

tiempo interactuando con su programa de control de revisiones.

Las herramientas distribuidas son indiferentes a los caprichos de su infraestructura de servidores, de nuevo, debidoa la replicacion de metadatos en tantos lugares. Si usa un sistema centralizado y su servidor explota, ojala los medios

f ısicos de su copia de seguridad sean confiables, y que su ultima copia sea reciente y ademas funcione. Con una

herramienta distribuida tiene tantas copias de seguridad disponibles como computadores de contribuidores.

La confiabilidad de su red afectara las herramientas distribuidas de una forma mucho menor que a las herramientas

centralizadas. Usted no puede siquiera usar una herramienta centralizada sin conexion de red, excepto por algunas

ordenes muy limitadas. Con herramientas distribuidas, si sus conexion cae mientras usted esta trabajando, podrıa

nisiquiera darse cuenta. Lo unico que que no podra hacer es comunicarse con repositorios en otros computadores, algo

que es relativamente raro comparado con las operaciones locales. Si tiene colaboradores remotos en su equipo, puede

ser importante.

1.4.1. Ventajas para proyectos de codigo abierto

Si descubre un proyecto de codigo abierto y decide que desea comenzar a trabajar en el, y ese proyecto usa unaherramienta de control distribuido de revisiones, usted es de inmediato un par con la gente que se considera el “alma”

del proyecto. Si ellos publican sus repositorios, usted puede copiar inmediatamente el historial del proyecto, hacer

cambios y guardar su trabajo, usando las mismas herramientas de la misma forma que ellos. En contraste, con una

herramienta centralizada, usted debe usar el programa en un modo “s olo lectura” a menos que alguien le otorgue

permisos para consignar cambios en el repositorio central. Hasta entonces, no podra almacenar sus cambios y sus

modificaciones locales correran el riesgo de danarse cuando trate de actualizar su vista del repositorio.

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 codigo abierto, puesto que se vuelve muy sencillo hacer una “bifurcacion”1 del desarrollo del proyecto. Una bi-

furcacion sucede cuando hay diferencias de opinion o actitud entre grupos de desarrolladores que desemboca en la

decision de la imposibilidad de continuar trabajando juntos. Cada parte toma una copia m as o menos completa delcodigo fuente del proyecto y toma su propio rumbo.

En algunas ocasiones los lıderes de las bifurcaciones reconcilian sus diferencias. Con un sistema centralizado de

control de revisiones, el proceso t´ ecnico de reconciliarse es doloroso, y se hace de forma muy manual. Usted tiene que

decidir que historial de revisiones va a “ganar”, e injertar los cambios del otro equipo en el arbol de alguna manera.

Con esto usualmente se pierde algo o todo del historial de la revision de alguna de las partes.

Lo que las herramientas distribuidas hacen con respecto a las bifurcaciones, es que las bifurcaciones son la ´ unica

forma de desarrollar un proyecto. Cada cambio que usted hace es potencialmente un punto de bifurcaci on. La gran

fortaleza de esta aproximacion es que las herramientas distribuidas de control de revisiones tiene que ser bueno al

 fusionar las bifurcaciones, porque las bifurcaciones son absolutamente fundamentales: pasan todo el tiempo.

Si todas las porciones de trabajo que todos hacen, todo el tiempo, se enmarcan en terminos de bifurcaciones

y fusiones, entonces a aquello a lo que se refiere en el mundo del codigo abierto a una “bifurcacion” se convierte

 puramente en una cuestion social. Lo que hacen las herramientas distribuidas es disminuir  la posibilidad de una

bifurcacion porque:

Eliminan la distincion social que imponen las herramientas centralizadas: aquella entre miembros (personas con

permiso de consignar) y forasteros (los que no tienen el permiso).

Facilitan la reconciliacion despues de una bifurcacion social, porque todo lo que concierne al programa de

control de revisiones es una fusion.

1N. del T. fork.

6

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 17/204

Algunas personas se resisten a las herramientas distribuidas porque desean mantener control completo sobre sus

proyectos, y creen que las herramientas centralizadas les dan tal control. En todo caso, si este es su parecer, y usted

publica sus repositorios de CVS o Subversion, hay muchas herramientas disponibles que pueden obtener el historial

completo (aunque sea lentamente) y recrearlo en otro sitio que usted no controla. Siendo ası un control ilusorio, puesto

que esta impidiendo la fluidez de colaboracion en lugar de prevenir que alguien se sienta impulsado a obtener una

copia y hacer una bifurcacion con su historial.

1.4.2. Ventajas para proyectos comerciales

Muchos proyectos comerciales tienen grupos de trabajo distribuidos alrededor del globo. Quienes contribuyen y

estan lejos de un repositorio central veran una ejecucion mas lenta de los comandos y tal vez menos confiabilidad.

Los sistemas de control de revision comerciales intentan amortiguar estos problemas con adiciones de replicacion

remota que usualmente son muy costosos y complicados de administrar. Un sistema distribuido no padece estos prob-

lemas. Mejor aun, puede colocar varios servidores autorizados, por ejemplo, uno por sitio, de tal forma que no haya

comunicacion redundante entre repositorios sobre enlaces de conexion costosos.

Los sistemas de control de revisiones distribuidos tienden a ser poco escalables. No es inusual que costosos sis-

temas centralizados caigan ante la carga combinada de unas cuantas docenas de usuarios concurrentes. De nuevo, las

respuestas tıpicas de replicacion tienden a ser costosas y complejas de instalar y administrar. Dado que la carga en

un servidor central—si es que tiene uno—es muchas veces menor con una herramienta distribuida (debido a que los

datos estan replicados en todas partes), un solo servidor economico puede tratar las necesidades de equipos muchomas grandes, y la replicacion para balancear la carga se vuelve cosa de guiones.

Si tiene un empleado en el campo, se beneficiara grandemente de un sistema distribuido de control de versiones

al resolver problemas en el sitio del cliente. La herramienta le permitir a generar construcciones a la medida, probar

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, todo sin necesidad de conectarse al servidor de su companıa.

1.5. ¿Por que elegir Mercurial?

Mercurial cuenta con un conjunto unico de propiedades que lo hacen una eleccion particularmente buena como

sistema de control de revisiones, puesto que:

Es f acil de aprender y usar.

Es liviano.

Escala de forma excelente.

Es f acil de acondicionar.

Si los sistemas de control de revisiones le son familiares, deberıa estar listo para usar Mercurial en menos de cinco

minutos. Si no, solo va a tomar unos pocos minutos mas. Las ordenes de Mercurial y su conjunto de caracterısticas

son uniformes y consistentes generalmente, y basta con que siga unas pocas reglas generales en lugar de un monton

de excepciones.

En un proyecto pequeno, usted puede comenzar a trabajar con Mercurial en pocos momentos. Crear nuevos cam-

bios y ramas, transferir cambios (localmente o por la red); y las operaciones relacionadas con el estado y el historial

son rapidas. Mercurial buscar ser ligero y no incomodar en su camino combinando poca sobrecarga cognitiva con

operaciones asombrosamente rapidas.

La utilidad de Mercurial no se limita a proyectos pequenos: esta siendo usado por proyectos con centenas de miles

de contribuyentes, cada uno conteniendo decenas de miles de ficheros y centenas de megabytes de codigo fuente

Si la funcionalidad basica de Mercurial no es suficiente para usted, es muy facil extenderlo. Mercurial se comporta

muy bien con tareas de scripting y su limpieza interna junto con su implementacion en Python permiten anadir carac-

terısticas f acilmente en forma de extensiones. Hay un buen numero de extensiones utiles y populares en este momento,

desde ayudar a identificar fallos hasta mejorar su desempeno.

7

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 18/204

1.6. Comparacion de Mercurial con otras herramientas

Antes de leer, por favor tenga en cuenta que esta seccion necesariamente refleja mis propias experiencias, intereses

y (tengo que decirlo) mis preferencias. He usado cada una de las herramientas de control de versiones listadas a

continuacion, y en muchos casos por varios anos.

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, sera sencillo aprender a usar la otra. Ambas herramientas son portables en todos los sistemas

operativos populares.

Antes de la version 1.5, Subversion no tenıa soporte para fusiones. En el momento de la escritura, sus capcidades

para llevar cuenta de las funciones son nuevas, complicadas y poco estables2.

Mercurial tiene una ventaja considerable en desempeno sobre Subversion en cualquier operacion de control de

revisiones que yo haya medido. He medido sus ventajas con factores desde dos hasta seis veces comparando con al-

macenamiento de ficheros ra local Subversion 1.4.3, el cual es el metodo de acceso mas rapido. En los escenarios

mas realistas incluyendo almacenamiento con la red de por medio, Subversion se encuentra en desventaja aun mayor.

Dado que casi todas las ordenes de Subversion deben tratar con el servidor y Subversion no tiene utilidades de repli-cacion adecuadas, la capacidad del servidor y el ancho de banda se convierten en cuellos de botella para proyectos

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 informacion frente a la

revision actual (diff). Como resultado, la copia de trabajo de Subversion termina siendo del mismo tamano o mas

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 a bastante atras en este aspecto.

Esta diferencia esta disminuyendo, y algunas de las herramientas GUI3, eclipsan sus equivalentes de Subversion. Al

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 a constante mientras que el espacio usadopor cualquier Sistema Distribuido de Control de Revisiones crecera rapidamente en proporcion con el numero de

revisiones, debido a que las diferencias entre cada revision es grande.

Adicionalmente, generalmente es dif ıcil o mas bien, imposible mezclar diferentes versiones de un fichero binario.

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. Tambien puede exportar el

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 conversion del historial es incremental, de modo que

puede aplicar una conversion inicial, y despues conversiones pequenas y adicionales posteriormente para traer nuevos

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 diseno fueron influenciados por Monotone.

2N. del T. buggy3N. del T. Interfaz de Usuario Grafica

8

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 19/204

Git tiene un conjunto de ordenes muy grande; en la version 1.5.0 ofrece 139 ordenes individuales. Tiene cierta

reputacion de ser dif ıcil de aprender. Comparado con Git, Mercurial tiene un fuerte enfoque hacia la facilidad.

En terminos de rendimiento, Git es extremadamente rapido. En muchos casos, es mas rapido que Mercurial, por lo

menos en Linux, mientras que Mercurial se comporta mejor en otras operaciones. De todas maneras en Windows, el

desempeno y el nivel general de soporte que ofrece Git, al momento de la escritura, est a bastante atras de Mercurial.

Mientras que el repositorio de Mercurial no requiere mantenimiento, el repositorio de Git requiere frecuentes

“reempaquetados” de sus metadatos. Sin estos, el desempeno se degrada y el uso de espacio crece rapidamente. Unservidor que contenga repositorios de Git que no sean reempacados rigurosa y frecuentemente requerir a trabajo in-

tenso de disco durante las copias de seguridad, y ha habido situaciones en copias de seguridad diaria que toman m as

de 24 horas como resultado. Un repositorio recien reempacado de Git es un poco mas pequeno que un repositorio de

Mercurial, pero un repositorio sin reempacar es varios ordenes de magnitud mas grande.

El corazon de Git esta escrito en C. Muchas ordenes de Git estan implementadas como guiones de lınea de co-

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 mas ampliamente usada en el planeta. Debido a su

edad y su poca pulcritud interna, ha sido ligeramente mantenida en muchos anos.Tiene una arquitectura centralizada cliente/servidor. No agrupa cambios relacionados en consignaciones atomicas,

pemitiendo que con facilidad la gente “rompa la construccion”: una persona puede consignar exitosamente parte del

cambio y estar bloqueada por la necesidad de una mezcla, forzando a otras personas a ver solamente una porci on del

trabajo que estaban buscando hacer. Esto afecta tambien la forma como usted trabaja con el historial del proyecto. Si

quiere ver todas las modificaciones que alguien hizo como parte de una tarea, necesitara inspeccionar manualmente

las descripciones y las marcas de tiempo de cambio de cada fichero involucrado (esto, si usted saber cuales eran tales

ficheros).

CVS tiene una nocion confusa de etiquetas y ramas que yo no tratar ıa incluso de describir. No soporta renom-

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 omo se corrompio un repositorio. Yo no

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 apli-

can; las cuales tambien son necesarias para cualquier herramienta importadora de historial de CVS. Debido a la faltade atomicidad de cambios y el no versionamiento de la jerarqu ıa del sistema de ficheros, es imposible reconstruir

completamente el historial de CVS con precision; hay cierto trabajo de conjetura involucrado y los renombramientos

tampoco se mostraran. Debido a que gran parte de la administracion avanzada de CVS tiene que hacerse manualmente

y por lo tanto es proclive al error, es comun que los importadores de CVS encuentren muchos problemas con reposi-

torios corruptos (marcas de tiempo totalmente desubicadas y ficheros que han permanecido con candados por m as de

una decada son dos de los problemas menos interesantes de los que puedo retomar de mi experiencia personal).

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 cache en el

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 pequenos, pero se degrada rapidamente cuando el numero

de usuarios va mas alla de pocas docenas. Instalaciones modestamente grandes de Perforce requiere la organizaci on

de proxies para soportar la carga que sus usuarios generan.

9

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 20/204

1.6.5. Elegir una herramienta de control de revisiones

Con la excepcion de CVS, toda las herramientas que se han listado anteriormente tienen fortalezas unicas que las

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 eleccion para trabajar con edicion frecuente de ficheros binarios, debido a

su naturaleza centralizada y soporte para poner candados a ficheros.

Personalmente encuentro las propiedades de simplicidad, desempeno, y buen soporte de fusiones de Mercurial una

combinacion llamativa que ha dado buenos frutos por varios anos.

1.7. Migrar de otra herramienta hacia Mercurial

Mercurial viene con una extension llamada convert, que puede importar historiales de revisiones de forma incre-

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 despues volver a ejecutar la migracion posteriormente para obtener

los nuevos cambios que han sucedido despues de la migracion inicial.

A continuacion presentamos las herramientas de revisiones que soporta el comando convert:

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 on total, sin arriesgarse a perder trabajo alguno.

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 comenzara a hacer su trabajo. Despues de la

conversion inicial, basta con invocar de nuevo el comando para importar cambios nuevos.

10

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 21/204

Capıtulo 2

Una gira de Mercurial: lo basico

2.1. Instalar Mercurial en su sistema

Hay paquetes binarios precompilados de Mercurial disponibles para cada sistema operativo popular. Esto hace

f acil empezar a usar Mercurial en su computador inmediatamente.

2.1.1. Linux

Dado que cada distribucion de Linux tiene sus propias herramientas de manejo de paquetes, polıticas, y ritmos

de desarrollo, es dif ıcil dar un conjunto exhaustivo de instrucciones sobre como instalar el paquete de Mercurial. La

version de Mercurial que usted tenga a disposicion puede variar dependiendo de que tan activa sea la persona que

mantiene el paquete para su distribucion.

Para mantener las cosas simples, me enfocare en instalar Mercurial desde la lınea de comandos en las distribuciones

de Linux mas populares. La mayorıa de estas distribuciones proveen administradores de paquetes graficos que le

permitiran instalar Mercurial con un solo clic; el nombre de paquete a buscar es mercurial.

Debian1 apt-get install mercurial

Fedora Core1 yum install mercurial

Gentoo1 emerge mercurial

OpenSUSE1 yum install mercurial

Ubuntu El paquete de Mercurial de Ubuntu esta basado en el de Debian. Para instalarlo, ejecute el siguiente comando.

1 apt-get install mercurial

El paquete de Mercurial para Ubuntu tiende a atrasarse con respecto a la version de Debian por un margen de

tiempo considerable (al momento de escribir esto, 7 meses), lo que en algunos casos significar a que usted puedeencontrarse con problemas que ya habran sido resueltos en el paquete de Debian.

2.1.2. Solaris

SunFreeWare, en http://www.sunfreeware.com , es una buena fuente para un gran numero de paquetes compi-

lados para Solaris para las arquitecturas Intel y Sparc de 32 y 64 bits, incluyendo versiones actuales de Mercurial.

11

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 22/204

2.1.3. Mac OS X

Lee Cantey publica un instalador de Mercurial para Mac OS X en http://mercurial.berkwood.com . Este

paquete funciona en tanto en Macs basados en Intel como basados en PowerPC. Antes de que pueda usarlo, usted

debe instalar una version compatible de Universal MacPython [BI]. Esto es f acil de hacer; simplemente siga las

instrucciones del sitio de Lee.

Tambien es posible instalar Mercurial usando Fink o MacPorts, dos administradores de paquetes gratuitos y pop-

ulares para Mac OS X. Si usted tiene Fink, use sudo apt-get install mercurial-py25. Si usa MacPorts, sudo

port install mercurial.

2.1.4. Windows

Lee Cantey publica un instalador de Mercurial para Windows en http://mercurial.berkwood.com . Este pa-

quete no tiene dependencias externas; “simplemente funciona”.

Nota: La version de Windows de Mercurial no convierte automaticamente los fines

de lınea entre estilos Windows y Unix. Si usted desea compartir trabajo con usuar-

ios de Unix, debera hacer un trabajo adicional de configuracion. XXX Terminar

esto.

2.2. Arrancando

Para empezar, usaremos el comando “hg version” para revisar si Mercurial esta instalado adecuadamente. La

informacion de la version que es impresa no es tan importante; lo que nos importa es si imprime algo en absoluto.

1 $ hg version

2 Mercurial Distributed SCM (version 1.0.1)

3

4 Copyright (C) 2005-2008 Matt Mackall <[email protected]> and others

5 This is free software; see the source for copying conditions. There is NO

6 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

2.2.1. Ayuda integrada

Mercurial provee un sistema de ayuda integrada. Esto es invaluable para esas ocasiones en la que usted esta atorado

tratando de recordar como ejecutar un comando. Si esta completamente atorado, simplemente ejecute “hg help”; esto

imprimira una breve lista de comandos, junto con una descripci on de que hace cada uno. Si usted solicita ayuda sobre

un comando especıfico (como abajo), se imprime informacion mas detallada.

1 $ hg help init

2 hg init [-e CMD] [--remotecmd CMD] [DEST]

3

4 create a new repository in the given directory

5

6 Initialize a new repository in the given directory. If the given

7 directory does not exist, it is created.8

9 If no directory is given, the current directory is used.

10

11 It is possible to specify an ssh:// URL as the destination.

12 Look at the help text for the pull command for important details

13 about ssh:// URLs.

14

12

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 23/204

15 options:

16

17 -e --ssh specify ssh command to use

18 --remotecmd specify hg command to run on the remote side

19

20 use "hg -v help init" to show global options

Para un nivel mas impresionante de detalle (que usted no va a necesitar usualmente) ejecute “hg help -v”. La opcion

-v es la abreviacion para --verbose, y le indica a Mercurial que imprima mas informacion de lo que harıa usualmente.

2.3. Trabajar con un repositorio

En Mercurial, todo sucede dentro de un repositorio. El repositorio para un proyecto contiene todos los ficheros que

“pertenecen a” ese proyecto, junto con un registro historico de los ficheros de ese proyecto.

No hay nada particularmente magico acerca de un repositorio; es simplemente un arbol de directorios en su sistema

de ficheros que Mercurial trata como especial. Usted puede renombrar o borrar un repositorio en el momento que lo

desee, usando bien sea la lınea de comandos o su explorador de ficheros.

2.3.1. Hacer una copia local de un repositorio

Copiar  un repositorio es solo ligeramente especial. Aunque usted podrıa usar un programa normal de copia de

ficheros para hacer una copia del repositorio, es mejor usar el comando integrado que Mercurial ofrece. Este comando

se llama “hg clone”1, porque crea una copia identica de un repositorio existente.

1 $ hg clone http://hg.serpentine.com/tutorial/hello

2 destination directory: hello

3 requesting all changes

4 adding changesets

5 adding manifests

6 adding file changes

7 added 5 changesets with 5 changes to 2 files

8 updating working directory9 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

Si nuestro clonado tiene exito, deberıamos tener un directorio local llamado hello. Este directorio contendra algunos

ficheros.

1 $ ls -l

2 total 0

3 drwxr-xr-x 3 jerojasro jerojasro 120 Feb 10 18:23 hello

4 $ ls hello

5 Makefile hello.c

Estos ficheros tienen el mismo contenido e historial en nuestro repositorio y en el repositorio que clonamos.

Cada repositorio Mercurial esta completo, es autocontenido e independiente. Contiene su propia copia de los

ficheros y el historial de un proyecto. Un repositorio clonado recuerda la ubicaci on de la que fue clonado, pero no se

comunica con ese repositorio, ni con ningun otro, a menos que usted le indique que lo haga.

Lo que esto significa por ahora es que somos libres de experimentar con nuestro repositorio, con la tranquilidad de

saber que es una “caja de arena” privada que no afectara a nadie mas.

1N. del T. Del termino “clonar” en ingles.

13

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 24/204

2.3.2. Que hay en un repositorio?

Cuando miramos en detalle dentro de un repositorio, podemos ver que contiene un directorio llamado .hg. Aquı es

donde Mercurial mantiene todos los metadatos del repositorio.

1 $ cd hello

2 $ ls -a

3 . .. .hg Makefile hello.c

Los contenidos del directorio .hg y sus subdirectorios son exclusivos de Mercurial. Usted es libre de hacer lo que

desee con cualquier otro fichero o directorio en el repositorio.

Para introducir algo de terminologıa, el directorio .hg es el repositorio “real”, y todos los ficheros y directorios que

coexisten con el estan en el directorio de trabajo. Una forma sencilla de recordar esta distincion es que el repositorio

contiene el historial de su proyecto, mientras que el directorio de trabajo contiene una instant   anea de su proyecto en

un punto particular del historial.

2.4. Vistazo rapido al historial

Una de las primeras cosas que se desea hacer con un repositorio nuevo, poco conocido, es conocer su historial. El

comando “hg log” nos permite ver el mismo.

1 $ hg log

2 changeset: 4:2278160e78d4

3 tag: tip

4 user: Bryan O’Sullivan <[email protected]>

5 date: Sat Aug 16 22:16:53 2008 +0200

6 summary: Trim comments.

7

8 changeset: 3:0272e0d5a517

9 user: Bryan O’Sullivan <[email protected]>

10 date: Sat Aug 16 22:08:02 2008 +0200

11 summary: Get make to generate the final binary from a .o file.

12

13 changeset: 2:fef857204a0c

14 user: Bryan O’Sullivan <[email protected]>

15 date: Sat Aug 16 22:05:04 2008 +0200

16 summary: Introduce a typo into hello.c.

17

18 changeset: 1:82e55d328c8c

19 user: [email protected]

20 date: Fri Aug 26 01:21:28 2005 -0700

21 summary: Create a makefile

22

23 changeset: 0:0a04b987be5a

24 user: [email protected]

25 date: Fri Aug 26 01:20:50 2005 -0700

26 summary: Create a standard "hello, world" program

27

Por defecto este programa imprime un parrafo breve por cada cambio al proyecto que haya sido grabado. Dentro de

la terminologıa de Mercurial, cada uno de estos eventos es llamado conjunto de cambios, porque pueden contener un

registro de cambios a varios ficheros.

14

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 25/204

Los campos de la salida de “hg log” son los siguientes.

changeset2 Este campo tiene un numero, seguido por un :, seguido por una cadena hexadecimal. Ambos son identificadores

para el conjunto de cambios. Hay dos identificadores porque el numero es mas corto y mas facil de recordar que

la cadena hexadecimal.

user3 La identidad de la persona que creo el conjunto de cambios. Este es un campo en el que se puede almacenar

cualquier valor, pero en la mayorıa de los casos contiene el nombre de una persona y su direccion de correoelectronico.

date4 La fecha y hora en la que el conjunto de cambios fue creado, y la zona horaria en la que fue creado. (La fecha

y hora son locales a dicha zona horaria; ambos muestran la fecha y hora para la persona que creo el conjunto de

cambios).

summary5 La primera lınea del texto que uso la persona que creo el conjunto de cambios para describir el mismo.

El texto impreso por “hg log” es solo un sumario; omite una gran cantidad de detalles.

La figura 2.1 es una representacion grafica del historial del repositorio hello, para hacer mas facil ver en que di-

reccion esta “fluyendo” el historial. Volveremos a esto varias veces en este capıtulo y en los siguientes.

0: 0a04

1: 82e5

2: fef8

3: 0272

4: 2278 (la más nueva)

(la más antigua)

4: 2278

número de

revisión

identificador del

conjunto de cambios

Figura 2.1: Historial grafico del repositorio hello

2.4.1. Conjuntos de cambios, revisiones, y comunicandose con otras personas

Ya que el ingles es un lenguaje notablemente desordenado, y el area de ciencias de la computacion tiene una

notable historia de confusion de terminos (porque usar solo un termino cuando cuatro pueden servir?), el control de

revisiones tiene una variedad de frases y palabras que tienen el mismo significado. Si usted habla acerca del historial

de Mercurial con alguien, encontrara que la expresion “conjunto de cambios” es abreviada a menudo como “cambio”

o (por escrito) “cset”6, y algunas veces un se hace referencia a un conjunto de cambios como una “revision” o “rev”7.

Si bien no es relevante que palabra use usted para referirse al concepto “conjunto de cambios”, el identificador que

usted use para referise a “un conjunto de cambios particular” es muy importante. Recuerde que el campo changeseten la salida de “hg log” identifica un conjunto de cambios usando tanto un numero como una cadena hexadecimal.

2N. del T. Conjunto de cambios.3N. del T. Usuario.4N. del T. Fecha.5N. del T. Sumario.6N. del T. Abreviatura para la expresion “changeset” en ingles.7N. del T. De nuevo, como abreviacion para el termino en ingles para “revision” (“revision”).

15

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 26/204

El numero de revision s´ olo es v´ alido dentro del repositorio.

Por otro lado, la cadena hexadecimal es el identificador permanente e inmutable que siempre identificara ese

conjunto de cambios en todas las copias del repositorio.

La diferencia es importante. Si usted le envıa a alguien un correo electronico hablando acerca de la “revision 33”, hay

una probabilidad alta de que la revision 33 de esa persona no sea la misma suya. Esto sucede porque el numero de

revision depende del orden en que llegan los cambios al repositorio, y no hay ninguna garant ıa de que los mismoscambios llegaran en el mismo orden en diferentes repositorios. Tres cambios dados a,b, c pueden aparecer en un

repositorio como 0,1,2, mientras que en otro aparecen como 1, 0, 2.

Mercurial usa los numeros de revision simplemente como una abreviacion conveniente. Si usted necesita hablar

con alguien acerca de un conjunto de cambios, o llevar el registro de un conjunto de cambios por alguna otra raz on

(por ejemplo, en un reporte de fallo), use el identificador hexadecimal.

2.4.2. Ver revisiones especıficas

Para reducir la salida de “hg log” a una sola revision, use la opcion -r (o --rev). Puede usar un numero de

revision o un identificador hexadecimal de conjunto de cambios, y puede pasar tantas revisiones como desee.

1 $ hg log -r 3

2 changeset: 3:0272e0d5a517

3 user: Bryan O’Sullivan <[email protected]>

4 date: Sat Aug 16 22:08:02 2008 +0200

5 summary: Get make to generate the final binary from a .o file.

6

7 $ hg log -r 0272e0d5a517

8 changeset: 3:0272e0d5a517

9 user: Bryan O’Sullivan <[email protected]>

10 date: Sat Aug 16 22:08:02 2008 +0200

11 summary: Get make to generate the final binary from a .o file.

12

13 $ h g l o g - r 1 - r 4

14 changeset: 1:82e55d328c8c

15 user: [email protected]

16 date: Fri Aug 26 01:21:28 2005 -0700

17 summary: Create a makefile

18

19 changeset: 4:2278160e78d4

20 tag: tip

21 user: Bryan O’Sullivan <[email protected]>

22 date: Sat Aug 16 22:16:53 2008 +0200

23 summary: Trim comments.

24

Si desea ver el historial de varias revisiones sin tener que mencionar cada una de ellas, puede usar la notaci´ on de

rango; esto le permite expresar el concepto “quiero ver todas las revisiones entre a y b, inclusive”.

1 $ hg log -r 2:4

2 changeset: 2:fef857204a0c

3 user: Bryan O’Sullivan <[email protected]>

4 date: Sat Aug 16 22:05:04 2008 +0200

5 summary: Introduce a typo into hello.c.

6

16

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 27/204

7 changeset: 3:0272e0d5a517

8 user: Bryan O’Sullivan <[email protected]>

9 date: Sat Aug 16 22:08:02 2008 +0200

10 summary: Get make to generate the final binary from a .o file.

11

12 changeset: 4:2278160e78d4

13 tag: tip14 user: Bryan O’Sullivan <[email protected]>

15 date: Sat Aug 16 22:16:53 2008 +0200

16 summary: Trim comments.

17

Mercurial tambien respeta el orden en que usted especifica las revisiones, ası que “hg log -r 2:4” muestra 2,3,4

mientras que “hg log -r 4:2” muestra 4, 3,2.

2.4.3. Informacion mas detallada

Aunque la informacion presentada por “hg log” es util si usted sabe de antemano que esta buscando, puede

que necesite ver una descripcion completa del cambio, o una lista de los ficheros que cambiaron, si est a tratando de

averiguar si un conjunto de cambios dado es el que usted est a buscando. La opcion -v (or --verbose) del comando“hg log” le da este nivel extra de detalle.

1 $ hg log -v -r 3

2 changeset: 3:0272e0d5a517

3 user: Bryan O’Sullivan <[email protected]>

4 date: Sat Aug 16 22:08:02 2008 +0200

5 files: Makefile

6 description:

7 Get make to generate the final binary from a .o file.

8

9

Si desea ver tanto la descripcion como el contenido de un cambio, anada la opcion -p (o --patch). Esto muestra

el contenido de un cambio como un diff unificado (si usted nunca ha visto un diff unificado antes, vea la seccion 12.4

para un vistazo global).

1 $ h g l o g - v - p - r 2

2 changeset: 2:fef857204a0c

3 user: Bryan O’Sullivan <[email protected]>

4 date: Sat Aug 16 22:05:04 2008 +0200

5 files: hello.c

6 description:

7 Introduce a typo into hello.c.

8

9

10 diff -r 82e55d328c8c -r fef857204a0c hello.c

11 --- a/hello.c Fri Aug 26 01:21:28 2005 -0700

12 +++ b/hello.c Sat Aug 16 22:05:04 2008 +0200

13 @@ -11,6 +11,6 @@

14

15 int main(int argc, char **argv)

16 {

17

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 28/204

17 - printf("hello, world!\n");

18 + printf("hello, world!\");

19 return 0;

20 }21

2.5. 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 on en la

manera en que trabajan; sera util tener esto en mente a medida que avanza nuestra gira.

Mercurial tiene un enfoque directo y consistente en el manejo de las opciones que usted le puede pasar a los

comandos. Se siguen las convenciones para opciones que son comunes en sistemas Linux y Unix modernos.

Cada opcion tiene un nombre largo. Por ejemplo, el comando “ hg log” acepta la opcion --rev, como ya hemos

visto.

Muchas opciones tienen tambien un nombre corto. En vez de --rev, podemos usar -r. (El motivo para que

algunas opciones no tengan nombres cortos es que dichas opciones se usan rara vez.)

Las opciones largas empiezan con dos guiones (p.ej. --rev), mientras que las opciones cortas empiezan conuno (e.g. -r).

El nombre y uso de las opciones es consistente en todos los comandos. Por ejemplo, cada comando que le

permite pasar un ID de conjunto de cambios o un n umero de revision acepta tanto la opcion -r como la --rev.

En los ejemplos en este libro, uso las opciones cortas en vez de las largas. Esto s olo muestra mis preferencias, ası que

no le de significado especial a eso.

Muchos de los comandos que generan salida de algun tipo mostraran mas salida cuando se les pase la opcion -v

(o --verbose8), y menos cuando se les pase la opcion -q (o --quiet9).

2.6. Hacer y repasar cambios

Ahora que tenemos una comprension adecuada sobre como revisar el historial en Mercurial, hagamos algunoscambios y veamos como examinarlos.

Lo primero que haremos sera aislar nuestro experimento en un repositorio propio. Usaremos el comando “hg

clone”, pero no hace falta clonar una copia del repositorio remoto. Como ya contamos con una copia local del mismo,

podemos clonar esa. Esto es mucho mas rapido que clonar a traves de la red, y en la mayorıa de los casos clonar un

repositorio local usa menos espacio en disco tambien.

1 $ cd ..

2 $ hg clone hello my-hello

3 updating working directory

4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 $ cd my-hello

A manera de recomendacion, es considerado buena practica mantener una copia “prıstina” de un repositorio remoto a

mano, del cual usted puede hacer clones temporales para crear cajas de arena para cada tarea en la que desee trabajar.

Esto le permite trabajar en multiples tareas en paralelo, teniendo cada una de ellas aislada de las otras hasta que est en

completas y usted este listo para integrar los cambios de vuelta. Como los clones locales son tan baratos, clonar y

destruir repositorios no consume demasiados recursos, lo que facilita hacerlo en cualquier momento.

8N. del T. Prolijo.9N. del T. Silencioso.

18

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 29/204

En nuestro repositorio my-hello, hay un fichero hello.c que contiene el clasico programa “hello, world”10.

Usaremos el clasico y venerado comando sed para editar este fichero y hacer que imprima una segunda l ınea de

salida. (Estoy usando el comando sed para hacer esto solo porque es f acil escribir un ejemplo automatizado con el.

Dado que usted no tiene esta restriccion, probablemente no querra usar sed; use su editor de texto preferido para hacer

lo mismo).

1 $ sed -i ’/printf/a\\tprintf("hello again!\\n");’ hello.c

El comando “hg status” de Mercurial nos dice lo que Mercurial sabe acerca de los ficheros en el repositorio.

1 $ ls

2 Makefile hello.c

3 $ hg status

4 M hello.c

El comando “hg status” no imprime nada para algunos ficheros, solo una lınea empezando con “M” para el fichero

hello.c. A menos que usted lo indique explıcitamente, “hg status” no imprimira nada respecto a los ficheros que

no han sido modificados.

La “M” indica que Mercurial se dio cuenta de que nosotros modificamos hello.c. No tuvimos que decirle a

Mercurial que ıbamos a modificar ese fichero antes de hacerlo, o que lo modificamos una vez terminamos de hacerlo;

el fue capaz de darse cuenta de esto por s ı mismo.

Es algo util saber que hemos modificado el fichero hello.c, pero preferirıamos saber exactamente qu´ e cambios

hicimos. Para averiguar esto, usamos el comando “hg diff”.

1 $ hg diff

2 diff -r 2278160e78d4 hello.c

3 --- a/hello.c Sat Aug 16 22:16:53 2008 +0200

4 +++ b/hello.c Tue Feb 10 18:23:34 2009 +0000

5 @@ -8,5 +8,6 @@

6 int main(int argc, char **argv)

7 {8 printf("hello, world!\");

9 + printf("hello again!\n");

10 return 0;11 }

2.7. Grabar cambios en un nuevo conjunto de cambios

Podemos modificar, compilar y probar nuestros cambios, y usar “hg status” y “hg diff” para revisar los mis-

mos, 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.

El comando “hg commit” nos permite crear un nuevo conjunto de cambios. Nos referiremos usualmente a esto

como “hacer una consigna” o consignar.

2.7.1. Definir un nombre de usuarioCuando usted trata de ejecutar “hg commit”11 por primera vez, no esta garantizado que lo logre. Mercurial registra

su nombre y direccion en cada cambio que usted consigna, para que mas adelante otros puedan saber quien es el

responsable de cada cambio. Mercurial trata de encontrar un nombre de usuario adecuado con el cual registrar la

consignacion. Se intenta con cada uno de los siguientes m etodos, en el orden presentado.

10N. del T. Hola, mundo.11N. del T. Hacer una consignacion

19

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 30/204

1. Si usted pasa la opcion -u al comando “hg commit” en la lınea de comandos, seguido de un nombre de usuario,

se le da a esto la maxima precedencia.

2. A continuacion se revisa si usted ha definido la variable de entorno HGUSER.

3. Si usted crea un fichero en su directorio personal llamado .hgrc, con una entrada username, se usa luego. Para

revisar como debe verse este fichero, refierase a la seccion 2.7.1 mas abajo.

4. Si usted ha definido la variable de entorno EMAIL, sera usada a continuacion.

5. Mercurial le pedira a su sistema buscar su nombre de usuario local, y el nombre de m aquina, y construira un

nombre de usuario a partir de estos componentes. Ya que esto generalmente termina generando un nombre de

usuario no muy util, se imprimira una advertencia si es necesario hacerlo.

Si todos estos procedimientos fallan, Mercurial fallara, e imprimira un mensaje de error. En este caso, no le permi-

tira hacer la consignacion hasta que usted defina un nombre de usuario.

Trate de ver la variable de entorno HGUSER y la opcion -u del comando “hg commit” como formas de hacer caso

omiso de la seleccion de nombre de usuario que Mercurial hace normalmente. Para uso normal, la manera mas simple y

sencilla de definir un nombre de usuario para usted es crear un fichero .hgrc; los detalles se encuentran mas adelante.

Crear el fichero de configuracion de Mercurial

Para definir un nombre de usuario, use su editor de texto favorito para crear un fichero llamado .hgrc en su

directorio personal. Mercurial usara este fichero para obtener las configuraciones personalizadas que usted haya hecho.

El contenido inicial de su fichero .hgrc deberıa verse ası.

1 # Este es un fichero de configuracion de Mercurial.

2 [ui]

3 username = Primernombre Apellido <[email protected]>

La l ınea “[ui]” define una section del fichero de configuracion, ası que usted puede leer la lınea “username = ...”

como “defina el valor del elemento username en la seccion ui”. Una seccion continua hasta que empieza otra nueva,

o se llega al final del fichero. Mercurial ignora las lıneas vacıas y considera cualquier texto desde el caracter “#” hasta

el final de la l ınea como un comentario.

Escoger un nombre de usuario

Usted puede usar el texto que desee como el valor del campo de configuracion username, ya que esta informacion

sera leıda por otras personas, e interpretada por Mercurial. La convencion que sigue la mayorıa de la gente es usar su

nombre y direccion de correo, como en el ejemplo anterior.

Nota: El servidor web integrado de Mercurial ofusca las direcciones de correo,

para dificultar la tarea de las herramientas de recoleccion de direcciones de correo

que usan los spammersa. Esto reduce la probabilidad de que usted empiece a recibir

mas correo basura si publica un repositorio en la red.

aN. del T. Personas que envıan correo no solicitado, t ambien conocido como correo basura

2.7.2. Escribir un mensaje de consignacionCuando consignamos un cambio, Mercurial nos ubica dentro de un editor de texto, para ingresar un mensaje que

describa las modificaciones que hemos introducido en este conjunto de cambios. Esto es conocido como un mensaje de

consignaci´ on. Sera un registro de lo que hicimos y porque lo hicimos, y sera impreso por “hg log” una vez hayamos

hecho la consignacion.

1 $ hg commit

20

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 31/204

El editor en que “hg commit” nos ubica contendra una lınea vacıa, seguida de varias lıneas que empiezan con la

cadena “HG:”.

1 lınea vacıa

2 HG: changed hello.c

Mercurial ignora las lıneas que empiezan con “HG:”; solo las usa para indicarnos para cuales ficheros esta registrandolos cambios. Modificar o borrar estas lıneas no tiene ningun efecto.

2.7.3. Escribir un buen mensaje de consignacion

Ya que por defecto “hg log” solo muestra la primera lınea de un mensaje de consignacion, lo mejor es escribir un

mensaje cuya primera lınea tenga significado por sı misma. A continuacion se encuentra un ejemplo de un mensaje de

consignacion que no sigue esta pauta, y debido a ello tiene un sumario que no es legible.

1 changeset: 73:584af0e231be

2 user: Persona Censurada <[email protected]>

3 date: Tue Sep 26 21:37:07 2006 -0700

4 summary: se incluye buildmeister/commondefs. Anade un modulo

Con respecto al resto del contenido del mensaje de consignaci on, no hay reglas estrictas-y-rapidas. Mercurial no

interpreta ni le da importancia a los contenidos del mensaje de consignacion, aunque es posible que su proyecto tenga

polıticas que definan una manera particular de escribirlo.

Mi preferencia personal es usar mensajes de consignacion cortos pero informativos, que me digan algo que no

puedo inferir con una mirada rapida a la salida de “hg log --patch”.

2.7.4. Cancelar una consignacion

Si usted decide que no desea hacer la consignacion mientras esta editando el mensaje de la misma, simplemente

cierre su editor sin guardar los cambios al fichero que esta editando. Esto hara que no pase nada ni en el repositorio ni

en el directorio de trabajo.

Si ejecutamos el comando “hg commit” sin ningun argumento, se registran todos los cambios que hemos hecho,

como lo indican “hg status” y “hg diff”.

2.7.5. Admirar nuestro trabajo

Una vez hemos terminado la consignacion, podemos usar el comando “hg tip”12 para mostrar el conjunto de

cambios que acabamos de crear. La salida de este comando es identica a la de “hg log”, pero solo muestra la revision

mas reciente en el repositorio.

1 $ hg tip -vp

2 changeset: 5:fccff93807a3

3 tag: tip

4 user: Bryan O’Sullivan <[email protected]>

5 date: Tue Feb 10 18:23:34 2009 +0000

6 files: hello.c7 description:

8 Added an extra line of output

9

10

11 diff -r 2278160e78d4 -r fccff93807a3 hello.c

12N. del T. Punta.

21

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 32/204

12 --- a/hello.c Sat Aug 16 22:16:53 2008 +0200

13 +++ b/hello.c Tue Feb 10 18:23:34 2009 +0000

14 @@ -8,5 +8,6 @@

15 int main(int argc, char **argv)

16 {17 printf("hello, world!\");

18 + printf("hello again!\n");19 return 0;

20 }21

Nos referimos a la revision mas reciente en el repositorio como la revision de punta, o simplemente la punta.

2.8. Compartir cambios

Anteriormente mencionamos que los repositorios en Mercurial estan auto contenidos. Esto quiere decir que el

conjunto de cambios que acabamos de crear solo existe en nuestro repositorio my-hello. Veamos unas cuantas formas

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 $ cd ..

2 $ hg clone hello hello-pull

3 updating working directory

4 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 que cambios jalarıa el comando “hg pull” al repositorio,sin jalarlos.

1 $ cd hello-pull

2 $ hg incoming ../my-hello

3 comparing with ../my-hello

4 searching for changes

5 changeset: 5:fccff93807a3

6 tag: tip

7 user: Bryan O’Sullivan <[email protected]>

8 date: Tue Feb 10 18:23:34 2009 +0000

9 summary: Added an extra line of output

10

(Por supuesto, alguien podrıa enviar mas conjuntos de cambios al repositorio en el tiempo que pasa entre la ejecucion

de “hg incoming” y la ejecucion de “hg pull” para jalar los cambios, ası que es posible que terminemos jalando

cambios que no esperabamos.)

Traer cambios al repositorio simplemente es cuestion de ejecutar el comando “hg pull”, indicandole de que repos-

itorio debe jalarlos.

13N. del T. Entrante, o cambios entrantes.

22

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 33/204

1 $ hg tip

2 changeset: 4:2278160e78d4

3 tag: tip

4 user: Bryan O’Sullivan <[email protected]>

5 date: Sat Aug 16 22:16:53 2008 +0200

6 summary: Trim comments.7

8 $ hg pull ../my-hello

9 pulling from ../my-hello

10 searching for changes

11 adding changesets

12 adding manifests

13 adding file changes

14 added 1 changesets with 1 changes to 1 files

15 (run ’hg update’ to get a working copy)

16 $ hg tip

17 changeset: 5:fccff93807a3

18 tag: tip

19 user: Bryan O’Sullivan <[email protected]>20 date: Tue Feb 10 18:23:34 2009 +0000

21 summary: Added an extra line of output

22

Como puede verse por las salidas antes-y-despues de “hg tip”, hemos jalado exitosamente los cambios en nuestro

repositorio. Aun falta un paso para que podamos ver estos cambios en nuestro directorio de trabajo.

2.8.2. Actualizar el directorio de trabajo

Hasta ahora hemos pasado por alto la relacion entre un repositorio y su directorio de trabajo. El comando “ hg

pull” que ejecutamos en la seccion 2.8.1 trajo los cambios al repositorio, pero si revisamos, no hay rastro de esos

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 $ grep printf hello.c

2 printf("hello, world!\");

3 $ hg update tip

4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 $ grep printf hello.c

6 printf("hello, world!\");

7 printf("hello again!\n");

Puede parecer algo raro que “hg pull” no actualice el directorio de trabajo automaticamente. De hecho, hay

una buena razon para esto: usted puede usar “hg update” para actualizar el directorio de trabajo al estado en que se

encontraba en cualquier revisi´ on del historial del repositorio. Si usted hubiera actualizado el directorio de trabajo a una

revision anterior—digamos, para buscar el origen de un fallo—y hubiera corrido un “hg pull” que hubiera actualizadoel directorio de trabajo automaticamente a la nueva revision, puede que no estuviera particularmente contento.

Sin embargo, como jalar-y-actualizar es una secuencia de operaciones muy comun, Mercurial le permite combina-

rlas al pasar la opcion -u a “hg pull”.

1 hg pull -u

14N. del T. Actualizar.

23

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 34/204

Si mira de vuelta la salida de “hg pull” en la seccion 2.8.1 cuando lo ejecutamos sin la opcion -u, vera que el

comando imprimio un amable recordatorio de que tenemos que encargarnos explıcitamente de actualizar el directorio

de trabajo:

1 (run ’hg update’ to get a working copy)

Para averiguar en que revision se encuentra el directorio de trabajo, use el comando “hg parents”.

1 $ hg parents

2 changeset: 5:fccff93807a3

3 tag: tip

4 user: Bryan O’Sullivan <[email protected]>

5 date: Tue Feb 10 18:23:34 2009 +0000

6 summary: Added an extra line of output

7

Si mira de nuevo la figura 2.1, vera flechas conectando cada conjunto de cambios. En cada caso, el nodo del que la

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 revision particular, pase un numero de revision o un ID de conjunto decambios al comando “hg update”.

1 $ hg update 2

2 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

3 $ hg parents

4 changeset: 2:fef857204a0c

5 user: Bryan O’Sullivan <[email protected]>

6 date: Sat Aug 16 22:05:04 2008 +0200

7 summary: Introduce a typo into hello.c.

8

9 $ hg update

10 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

Si no indica explıcitamente una revision, “hg update” actualizara hasta la revision depunta, comose vio enla segunda

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 $ cd ..

2 $ hg clone hello hello-push

3 updating working directory

4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

El comando “hg outgoing”15 nos dice que cambios serıan empujados en el otro repositorio.

1 $ cd my-hello

2 $ hg outgoing ../hello-push

15N. del T. Saliente. Cambios salientes.

24

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 35/204

3 comparing with ../hello-push

4 searching for changes

5 changeset: 5:fccff93807a3

6 tag: tip

7 user: Bryan O’Sullivan <[email protected]>

8 date: Tue Feb 10 18:23:34 2009 +0000

9 summary: Added an extra line of output10

Y el comando “hg push” se encarga de empujar dichos cambios.

1 $ hg push ../hello-push

2 pushing to ../hello-push

3 searching for changes

4 adding changesets

5 adding manifests

6 adding file changes

7 added 1 changesets with 1 changes to 1 files

Al igual que “hg pull”, el comando “hg push” no actualiza el directorio de trabajo del repositorio en el que estamos

empujando los cambios. (A diferencia de “hg pull”, “hg push” no ofrece la opcion -u para actualizar el directorio

de trabajo del otro repositorio.)

Que pasa si tratamos de jalar o empujar cambios y el repositorio receptor ya tiene esos cambios? Nada emocio-

nante.

1 $ hg push ../hello-push

2 pushing to ../hello-push

3 searching for changes

4 no changes found

2.8.4. Compartir cambios a traves de una red

Los comandos que hemos presentando en las pocas secciones anteriores no estan limitados a trabajar con reposito-

rios locales. Cada uno de ellos funciona exactamente de la misma manera a traves de una conexion de red. Simplemente

pase una URL en vez de una ruta local.

1 $ hg outgoing http://hg.serpentine.com/tutorial/hello

2 comparing with http://hg.serpentine.com/tutorial/hello

3 searching for changes

4 changeset: 5:fccff93807a3

5 tag: tip

6 user: Bryan O’Sullivan <[email protected]>

7 date: Tue Feb 10 18:23:34 2009 +0000

8 summary: Added an extra line of output

9

En este ejemplo, podemos ver que cambios empujarıamos al repositorio remoto, aunque, de manera entendible, elrepositorio remoto esta configurado para no permitir a usuarios anonimos empujar cambios a el.

1 $ hg push http://hg.serpentine.com/tutorial/hello

2 pushing to http://hg.serpentine.com/tutorial/hello

3 searching for changes

4 ssl required

25

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 36/204

Capıtulo 3

Una gira de Mercurial: fusionar trabajo

Hasta ahora hemos cubierto como clonar un repositorio, hacer cambios, y jalar o empujar dichos cambios de un

repositorio a otro. Nuestro siguiente paso es fusionar cambios de repositorios separados.

3.1. Fusionar lıneas de trabajoFusionar es una parte fundamental de trabajar con una herramienta de control distribuido de versiones.

Alicia y Roberto tienen cada uno una copia personal del repositorio de un proyecto en el que estan trabajando.

Alicia arregla un fallo en su repositorio; Roberto anade una nueva caracterıstica en el suyo. Ambos desean que

el repositorio compartido contenga el arreglo del fallo y la nueva caracterıstica.

Frecuentemente trabajo en varias tareas diferentes en un mismo proyecto al mismo tiempo, cada una aislada

convenientemente de las otras en su propio repositorio. Trabajar de esta manera significa que a menudo debo

fusionar una parte de mi propio trabajo con otra.

Como fusionar es una operacion tan necesaria y comun, Mercurial la facilita. Revisemos el proceso. Empezaremos

clonando (otro) repositorio (ve lo seguido que aparecen?) y haciendo un cambio en el.

1 $ cd ..

2 $ hg clone hello my-new-hello

3 updating working directory

4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 $ cd my-new-hello

6 $ sed -i ’/printf/i\\tprintf("once more, hello.\\n");’ hello.c

7 $ hg commit -m ’A new hello for a new day.’

Ahora deberıamos tener dos copias de hello.c con contenidos diferentes. El historial de los dos repositorios diverge

ahora, como se ilustra en la figura 3.1.

1 $ cat hello.c

2 /*3 * Placed in the public domain by Bryan O’Sullivan. This program is

4 * not covered by patents in the United States or other countries.

5 */

6

7 #include <stdio.h>

8

9 int main(int argc, char **argv)

26

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 37/204

10 {11 printf("once more, hello.\n");

12 printf("hello, world!\");

13 return 0;

14 }15 $ cat ../my-hello/hello.c

16 /*17 * Placed in the public domain by Bryan O’Sullivan. This program is

18 * not covered by patents in the United States or other countries.

19 */

20

21 #include <stdio.h>

22

23 int main(int argc, char **argv)

24 {25 printf("hello, world!\");

26 printf("hello again!\n");

27 return 0;

28 }

0: 0a04

1: 82e5

2: fef8

3: 0272

4: 2278

5: fccf

my−hello

0: 0a04

1: 82e5

2: fef8

3: 0272

4: 2278

5: 05b9

my−new−hello

Los cambios

más recientes

difieren

historia común

revisión principal

(sin hijos)

Figura 3.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 tendra efecto en el directorio de trabajo.

1 $ hg pull ../my-hello2 pulling from ../my-hello

3 searching for changes

4 adding changesets

5 adding manifests

6 adding file changes

7 added 1 changesets with 1 changes to 1 files (+1 heads)

27

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 38/204

8 (run ’hg heads’ to see heads, ’hg merge’ to merge)

Sin embargo, el comando “hg pull” dice algo acerca de “frentes”1.

3.1.1. Conjuntos de cambios de frentes

Un frente es un cambio que no tiene descendientes, o hijos, como tambien se les conoce. La revision de punta es,por tanto, un frente, porque la revision mas reciente en un repositorio no tiene ningun hijo. Sin embargo, un repositorio

puede contener mas de un frente.

0: 0a04

1: 82e5

2: fef8

3: 0272

4: 2278

5: 05b9

6: fccf

tip (y principal)

principal

Figura 3.2: Contenidos del repositorio despues de jalar my-hello a my-new-hello

En la figura 3.2 usted puede ver el efecto que tiene jalar los cambios de my-hello a my-new-hello. El historial que

ya existıa en my-new-hello se mantiene intacto, pero fue anadida una nueva revision. Refiriendonos a la figura 3.1,

podemos ver que el ID del conjunto de cambios se mantiene igual en el nuevo repositorio, pero el n´ umero de revisi´ on

ha cambiado. (Incidentalmente, este es un buen ejemplo de porque no es seguro usar numeros de revision cuando se

habla de conjuntos de cambios). Podemos ver los frentes en un repositorio usando el comando “hg heads”2.

1 $ hg heads

2 changeset: 6:fccff93807a3

3 tag: tip

4 parent: 4:2278160e78d4

5 user: Bryan O’Sullivan <[email protected]>

6 date: Tue Feb 10 18:23:34 2009 +00007 summary: Added an extra line of output

8

9 changeset: 5:05b9c1e50b3c

10 user: Bryan O’Sullivan <[email protected]>

1N. del T. El autor se refiere a heads aquı.2N. del T. Frentes.

28

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 39/204

11 date: Tue Feb 10 18:23:36 2009 +0000

12 summary: A new hello for a new day.

13

3.1.2. Hacer la fusion

Que pasa si tratamos de usar el comando usual, “hg update”, para actualizar el nuevo frente?

1 $ hg update

2 abort: crosses branches (use ’hg merge’ or ’hg update -C’)

Mercurial nos indica que el comando “hg update” no hara la fusion; no actualizara el directorio de trabajo cuando

considera que lo que deseamos hacer es una fusion, a menos que lo obliguemos a hacerlo. En vez de “ hg update”,

usamos el comando “hg merge” para hacer la fusion entre los dos frentes.

1 $ hg merge

2 merging hello.c

3 0 files updated, 1 files merged, 0 files removed, 0 files unresolved

4 (branch merge, don’t forget to commit)

4: 2278

5: 05b9

6: fccf punta (y frente)

frente

fusióndirectorio de trabajo

durante la fusión

4: 2278

5: 05b9

6: fccf

punta 7: 22a5

Directorio de trabajo durante la fusión Repositorio después de consignar la fusión

Figura 3.3: Directorio de trabajo y repositorio durante la fusi on, y consignacion consecuente

Esto actualiza el directorio de trabajo, de tal forma que contenga los cambios de ambos frentes, lo que se ve

reflejado tanto en la salida de “hg parents” como en los contenidos de hello.c.

1 $ hg parents

2

changeset: 5:05b9c1e50b3c3 user: Bryan O’Sullivan <[email protected]>

4 date: Tue Feb 10 18:23:36 2009 +0000

5 summary: A new hello for a new day.

6

7 changeset: 6:fccff93807a3

8 tag: tip

9 parent: 4:2278160e78d4

29

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 40/204

10 user: Bryan O’Sullivan <[email protected]>

11 date: Tue Feb 10 18:23:34 2009 +0000

12 summary: Added an extra line of output

13

14 $ cat hello.c

15 /*

16 * Placed in the public domain by Bryan O’Sullivan. This program is17 * not covered by patents in the United States or other countries.

18 */

19

20 #include <stdio.h>

21

22 int main(int argc, char **argv)

23 {24 printf("once more, hello.\n");

25 printf("hello, world!\");

26 printf("hello again!\n");

27 return 0;

28 }

3.1.3. Consignar los resultados de la fusion

Siempre que hacemos una fusion, “hg parents” mostrara dos padres hasta que consignemos (“hg commit”) los

resultados de la fusion.

1 $ hg commit -m ’Merged changes’

Ahora tenemos una nueva revision de punta; note que tiene los dos frentes anteriores como sus padres. Estos son las

mismas revisiones que mostro previamente el comando “hg parents”.

1 $ hg tip

2 changeset: 7:22a572779faf

3 tag: tip

4 parent: 5:05b9c1e50b3c

5 parent: 6:fccff93807a3

6 user: Bryan O’Sullivan <[email protected]>

7 date: Tue Feb 10 18:23:36 2009 +0000

8 summary: Merged changes

9

En la figura 3.3 usted puede apreciar una representacion de lo que pasa en el directorio de trabajo durante la fusion

cuando se hace la consignacion. Durante la fusion, el directorio de trabajo tiene dos conjuntos de cambios como sus

padres, y estos se vuelven los padres del nuevo conjunto de cambios.

3.2. Fusionar cambios con conflictos

La mayorıa de las fusiones son algo simple, pero a veces usted se encontrara fusionando cambios donde mas de

uno de ellos afecta las mismas secciones de los mismos ficheros. A menos que ambas modificaciones sean id enticas,

el resultado es un conflicto, en donde usted debe decidir como reconciliar ambos cambios y producir un resultado

coherente.

30

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 41/204

Saludos!

Soy Mariam Abacha, la

esposa del anterior

dictador de Nigeria

Sani Abacha. Le

contacto en secreto,

buscando los medios

para desarrollar

Saludos!

Soy Shehu Musa

 Abacha, sobrina del 

anterior dictador de

Nigeria Sani Abacha.

Le contacto en secreto,

buscando los medios

para desarrollar

Saludos!

Soy Alhaji Abba

 Abacha, hijo del 

anterior dictador de

Nigeria Sani Abacha.

Le contacto en secreto,

buscando los medios

para desarrollar

Versión inicial

Nuestros cambios Sus cambios

Figura 3.4: Cambios con conflictos a un documento

La figura 3.4 ilustra un ejemplo con dos cambios generando conflictos en un documento. Empezamos con una sola

version del fichero; luego hicimos algunos cambios; mientras tanto, alguien mas hizo cambios diferentes en el mismo

texto. Lo que debemos hacer para resolver el conflicto causado por ambos cambios es decidir como debe quedar

finalmente el fichero.

Mercurial no tiene ninguna utilidad integrada para manejar conflictos. En vez de eso, ejecuta un programa externo

llamado hgmerge. Es un guion de lınea de comandos que es instalado junto con Mercurial; usted puede modificarlo

para que se comporte como usted lo desee. Por defecto, lo que hace es tratar de encontrar una de varias herramientas

para fusionar que es probable que esten instaladas en su sistema. Primero se intenta con unas herramientas para fusionar

cambios automaticamente; si esto no tiene exito (porque la fusion demanda una guıa humana) o dichas herramientas

no estan presentes, el guion intenta con herramientas graficas para fusionar.

Tambien es posible hacer que Mercurial ejecute otro programa o guion en vez de hgmerge, definiendo la variable

de entorno HGMERGE con el nombre del programa de su preferencia.

3.2.1. Usar una herramienta grafica para fusion

Mi herramienta favorita para hacer fusiones es kdiff3, y la usare para describir las caracterısticas comunes de las

herramientas graficas para hacer fusiones. Puede ver una captura de pantalla de kdiff3 ejecutandose, en la figura 3.5.

El tipo de fusion que la herramienta hace se conoce como fusi´ on de tres vıas, porque hay tres versiones diferentes del

fichero en que estamos interesados. Debido a esto la herramienta divide la parte superior de la ventana en tres paneles.

A la izquierda esta la revision base del fichero, p.ej. la version mas reciente de la que descienden las dos

versiones que estamos tratando de fusionar.

En la mitad esta “nuestra” version del fichero, con las modificaciones que hemos hecho.

A la derecha esta la version del fichero de “ellos”, la que forma parte del conjunto de cambios que estamostratando de fusionar.

En el panel inferior se encuentra el resultado actual de la fusion. Nuestra tarea es reemplazar todo el texto rojo, que

muestra los conflictos sin resolver, con una fusion adecuada de “nuestra” version del fichero y la de “ellos”.

Los cuatro paneles estan enlazados; si avanzamos vertical o horizontalmente en cualquiera de ellos, los otros son

actualizados para mostrar las secciones correspondientes del fichero que tengan asociado.

31

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 42/204

Figura 3.5: Usando kdiff3 para fusionar versiones de un fichero

En cada conflicto del fichero podemos escoger resolverlo usando cualquier combinacion del texto de la revision

base, la nuestra, o la de ellos. Tambien podemos editar manualmente el fichero en que queda la fusion, si es necesario

hacer cambios adicionales.

Hay muchas herramientas para fusionar ficheros disponibles. Se diferencian en las plataformas para las que estan

disponibles, y en sus fortalezas y debilidades particulares. La mayorıa estan afinadas para fusionar texto plano, mien-

tras que otras estan pensadas para formatos de ficheros especializados (generalmente XML).

3.2.2. Un ejemplo real

En este ejemplo, reproduciremos el historial de modificaciones al fichero de la figura 3.4 mostrada anteriormente.

Empecemos creando un repositorio con la version base de nuestro documento.

1 $ cat > letter.txt <<EOF

2 > Greetings!

3 > I am Mariam Abacha, the wife of former

4 > Nigerian dictator Sani Abacha.

5 > EOF

6 $ hg add letter.txt

7 $ hg commit -m ’419 scam, first draft’

Clonaremos el repositorio y haremos un cambio al fichero.

1 $ cd ..

2 $ hg clone scam scam-cousin

3 updating working directory

4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

32

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 43/204

5 $ cd scam-cousin

6 $ cat > letter.txt <<EOF

7 > Greetings!

8 > I am Shehu Musa Abacha, cousin to the former

9 > Nigerian dictator Sani Abacha.

10 > EOF

11 $ hg commit -m ’419 scam, with cousin’

Y haremos otro clon, para simular a alguien mas haciendo un cambio al mismo fichero. (Esto introduce la idea de

que no es tan inusual hacer fusiones consigo mismo, cuando usted aısla tareas en repositorios separados, y de hecho

encuentra conflictos al hacerlo.)

1 $ cd ..

2 $ hg clone scam scam-son

3 updating working directory

4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 $ cd scam-son

6 $ cat > letter.txt <<EOF

7 > Greetings!

8 > I am Alhaji Abba Abacha, son of the former9 > Nigerian dictator Sani Abacha.

10 > EOF

11 $ hg commit -m ’419 scam, with son’

Ahora que tenemos dos versiones diferentes de nuestro fichero, crearemos un entorno adecuado para hacer la fusion.

1 $ cd ..

2 $ hg clone scam-cousin scam-merge

3 updating working directory

4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 $ cd scam-merge

6 $ hg pull -u ../scam-son

7 pulling from ../scam-son

8 searching for changes

9 adding changesets

10 adding manifests

11 adding file changes

12 added 1 changesets with 1 changes to 1 files (+1 heads)

13 not updating, since new heads added

14 (run ’hg heads’ to see heads, ’hg merge’ to merge)

En este ejemplo, no usare el comando normal de Mercurial para hacer la fusion (hgmerge), porque lanzarıa mi linda

herramienta automatizada para correr ejemplos dentro de una interfaz grafica de usuario. En vez de eso, definire la

variable de entorno HGMERGE para indicarle a Mercurial que use el comando merge. Este comando forma parte de la

instalacion base de muchos sistemas Unix y similares. Si usted est a ejecutando este ejemplo en su computador, no semoleste en definir HGMERGE.

1 $ export HGMERGE=merge

2 $ hg merge

3 merging letter.txt

4 merge: warning: conflicts during merge

5 merging letter.txt failed!

33

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 44/204

6 0 files updated, 0 files merged, 0 files removed, 1 files unresolved

7 There are unresolved merges, you can redo the full merge using:

8 hg update -C 1

9 hg merge 2

10 $ cat letter.txt

11 Greetings!

12 <<<<<<< /tmp/tour-merge-conflictsNZwSt/scam-merge/letter.txt13 I am Shehu Musa Abacha, cousin to the former

14 =======

15 I am Alhaji Abba Abacha, son of the former

16 >>>>>>> /tmp/letter.txt˜other.749P-k

17 Nigerian dictator Sani Abacha.

Debido a que merge no puede resolver los conflictos que aparecen, el deja marcadores de fusi´ on en el fichero con

conflictos, indicando si provienen de nuestra version o de la de ellos.

Mercurial puede saber —por el codigo de salida del comando merge— que no fue posible hacer la fusion exitosa-

mente, ası que nos indica que comandos debemos ejecutar si queremos rehacer la fusion. Esto puede ser util si, por

ejemplo, estamos ejecutando una herramienta grafica de fusion y salimos de ella porque nos confundimos o cometimos

un error.

Si la fusion —automatica o manual— falla, no hay nada que nos impida “arreglar” los ficheros afectados por

nosotros mismos, y consignar los resultados de nuestra fusion:

1 $ cat > letter.txt <<EOF

2 > Greetings!

3 > I am Bryan O’Sullivan, no relation of the former

4 > Nigerian dictator Sani Abacha.

5 > EOF

6 $ hg resolve -m letter.txt

7 hg: unknown command ’resolve’

8 Mercurial Distributed SCM

9

10 basic commands:

11

12 add add the specified files on the next commit

13 annotate show changeset information per file line

14 clone make a copy of an existing repository

15 commit commit the specified files or all outstanding changes

16 diff diff repository (or selected files)

17 export dump the header and diffs for one or more changesets

18 init create a new repository in the given directory

19 log show revision history of entire repository or files

20 merge merge working directory with another revision

21 parents show the parents of the working dir or revision

22 pull pull changes from the specified source

23 push push changes to the specified destination

24 remove remove the specified files on the next commit

25 serve export the repository via HTTP

26 status show changed files in the working directory

27 update update working directory

28

29 use "hg help" for the full list of commands or "hg -v" for details

30 $ hg commit -m ’Send me your money’

34

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 45/204

31 $ hg tip

32 changeset: 3:e29827f5cf51

33 tag: tip

34 parent: 1:eac603d73208

35 parent: 2:78b0a9e9cf1b

36 user: Bryan O’Sullivan <[email protected]>

37 date: Tue Feb 10 18:23:37 2009 +000038 summary: Send me your money

39

3.3. Simplificar el ciclo jalar-fusionar-consignar

El proceso de fusionar cambios delineado anteriomente es directo, pero requiere la ejecucion de tres comandos en

sucesion.

1 hg pull

2 hg merge

3 hg commit -m ’Fusionados cambios remotos’

En la consignacion final usted debe proveer un mensaje adecuado, que casi siempre es un fragmento de texto “de

relleno” carente de valor particular.

Serıa agradable reducir la cantidad de pasos necesarios, si fuera posible. De hecho, Mercurial es distribuido junto

con una extension llamada fetch3 que hace precisamente esto.

Mercurial cuenta con un mecanismo de extension flexible que le permite a sus usuarios extender su funcionalidad,

manteniendo el nucleo de Mercurial pequeno y f acil de manejar. Algunas extensiones anaden nuevos comandos que

usted puede usar desde la l ınea de comandos, mientras que otros funcionan “tras bambalinas”, por ejemplo, anadiendo

funcionalidad al servidor.

La extension fetch anade un comando llamado, no sorpresivamente, “hg fetch”. Esta extension actua como una

combinacion de “hg pull”, “hg update” y “hg merge”. Empieza jalando cambios de otro repositorio al repositorio

actual. Si encuentra que los cambios anaden un nuevo frente en el repositorio actual, inicia una fusion, y luego consigna

el resultado de la misma con un mensaje generado automaticamente. Si no se anadieron nuevos frentes, actualiza el

directorio de trabajo con el nuevo conjunto de cambios de punta.

Activar la extension fetch es f acil. Edite su .hgrc, y vaya a (o cree) la seccion [extensions]. Luego anada una

lınea que diga simplemente “fetch ”.

1 [extensions]

2 fetch =

(Normalmente, a la derecha del “=” deberıa aparecer la ubicacion de la extension, pero como el comando fetch es

parte de la distribucion estandar, Mercurial sabe donde buscarla.)

3N. del T. Descargar, traer.

35

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 46/204

Capıtulo 4

Tras bambalinas

A diferencia de varios sistemas de control de revisiones, los conceptos en los que se fundamenta Mercurial son lo

suficientemente simples como para entender f acilmente como funciona el software. Saber esto no es necesario, pero

considero util tener un “modelo mental” de que es lo que sucede.

Comprender esto me da la confianza de que Mercurial ha sido cuidadosamente disenado para ser tanto seguro como

eficiente. Y tal vez con la misma importancia, si es facil para mı hacerme a una idea adecuada de que esta haciendo elsoftware cuando llevo a cabo una tarea relacionada con control de revisiones, es menos probable que me sosprenda su

comportamiento.

En este capıtulo, cubriremos inicialmente los conceptos centrales del diseno de Mercurial, y luego discutiremos

algunos detalles interesantes de su implementacion.

4.1. Registro del historial de Mercurial

4.1.1. Seguir el historial de un unico fichero

Cuando Mercurial sigue las modificaciones a un fichero, guarda el historial de dicho fichero en un objeto de

metadatos llamado filelog1. Cada entrada en el fichero de registro contiene suficiente informacion para reconstruir una

revision del fichero que se esta siguiendo. Los ficheros de registro son almacenados como ficheros el el directorio

.hg/store/data. Un fichero de registro contiene dos tipos de informacion: datos de revisiones, y un ındice para

ayudar a Mercurial a buscar revisiones eficientemente.

El fichero de registro de un fichero grande, o con un historial muy largo, es guardado como ficheros separados

para datos (sufijo “.d”) y para el ındice (sufijo “.i”). Para ficheros pequenos con un historial pequeno, los datos de

revisiones y el ındice son combinados en un unico fichero “.i”. 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.1.

4.1.2. Administracion de ficheros monitoreados

Mercurial usa una estructura llamada manifiesto para centralizar la informacion que maneja acerca de los ficheros

que monitorea. Cada entrada en el manifiesto contiene informacion acerca de los ficheros involucrados en un unico

conjunto de cambios. Una entrada registra que ficheros estan presentes en el conjunto de cambios, la revision de cada

fichero, y otros cuantos metadatos del mismo.

4.1.3. Registro de informacion del conjunto de cambios

La bit   acora de cambios contiene informacion acerca de cada conjunto de cambios. Cada revision indica quien

consigno un cambio, el comentario para el conjunto de cambios, otros datos relacionados con el conjunto de cambios,

y la revision del manifiesto a usar.

1N. del T. Fichero de registro

36

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 47/204

.hg/store/data/README.iREADME

.hg/store/data/src/hello.c.d

.hg/store/data/src/hello.c.isrc/hello.c

Directorio de trabajo Repositorio

Figura 4.1: Relacion entre ficheros en el directorio de trabajo y ficheros de registro en el repositorio

4.1.4. Relaciones entre revisiones

Dentro de una bitacora de cambios, un manifiesto, o un fichero de registro, cada revisi on conserva un apuntadora su padre inmediato (o sus dos padres, si es la revision de una fusion). Como mencione anteriormente, tambien hay

relaciones entre revisiones a trav´ es de estas estructuras, y tienen naturaleza jerarquica.

Por cada conjunto de cambios en un repositorio, hay exactamente una revisi on almacenada en la bitacora de

cambios. Cada revision de la bitacora de cambios contiene un apuntador a una unica revision del manifiesto. Una

revision del manifiesto almacena un apuntador a una unica revision de cada fichero de registro al que se le hacıa

seguimiento cuando fue creado el conjunto de cambios. Estas relaciones se ilustran en la figura 4.2.

Bitácora de cambios

Manifiesto

Bitácora de archivos

Figura 4.2: Relaciones entre metadatos

Como lo muestra la figura, no hay una relacion “uno a uno” entre las revisiones en el conjunto de cambios, el

manifiesto, o el fichero de registro. Si el manifiesto no ha sido modificado de un conjunto de cambios a otro, las

entradas en la bitacora de cambios para esos conjuntos de cambios apuntaran a la misma revision del manifiesto. Si

un fichero monitoreado por Mercurial no sufre ningun cambio de un conjunto de cambios a otro, la entrada para dicho

fichero en las dos revisiones del manifiesto apuntara a la misma revision de su fichero de registro.

37

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 48/204

4.2. Almacenamiento seguro y eficiente

La base comun de las bitacoras de cambios, los manifiestos, y los ficheros de registros es provista por una unica

estructura llamada el revlog2.

4.2.1. Almacenamiento eficiente

El revlog provee almacenamiento eficiente de revisiones por medio del mecanismo de deltas3. En vez de almacenar

una copia completa del fichero por cada revision, almacena los cambios necesarios para transformar una revision

anterior en la nueva revision. Para muchos tipos de fichero, estos deltas son tıpicamente de una fraccion porcentual del

tamano de una copia completa del fichero.

Algunos sistemas de control de revisiones obsoletos solo pueden manipular deltas de ficheros de texto plano. Ellos

o bien almacenan los ficheros binarios como instantaneas completas, o codificados en alguna representacion de texto

plano adecuada, y ambas alternativas son enfoques que desperdician bastantes recursos. Mercurial puede manejar

deltas de ficheros con contenido binario arbitrario; no necesita tratar el texto plano como un caso especial.

4.2.2. Operacion segura

Mercurial solo a˜ nade datos al final de los ficheros de revlog. Nunca modifica ninguna seccion de un fichero una

vez ha sido escrita. Esto es mas robusto y eficiente que otros esquemas que requieren modificar o reescribir datos.Adicionalmente, Mercurial trata cada escritura como parte de una transacci´ on, que puede cubrir varios ficheros.

Una transaccion es at   omica: o bien la transaccion tiene exito y entonces todos sus efectos son visibles para todos

los lectores, o la operacion completa es cancelada. Esta garantıa de atomicidad implica que, si usted esta ejecutando

dos copias de Mercurial, donde una de ellas esta leyendo datos y la otra los esta escribiendo, el lector nunca vera un

resultado escrito parcialmente que podrıa confundirlo.

El hecho de que Mercurial solo hace adiciones a los ficheros hace mas f acil proveer esta garantıa transaccional. A

medida que sea mas f acil hacer operaciones como esta, mas confianza tendra usted en que sean hechas correctamente.

4.2.3. Recuperacion rapida de datos

Mercurial evita ingeniosamente un problema comun a todos los sistemas de control de revisiones anteriores¿

el problema de la recuperaci´ on4 ineficiente de datos. Muchos sistemas de control de revisiones almacenan los con-

tenidos de una revision como una serie incremental de modificaciones a una “instantanea”. Para reconstruir una versioncualquiera, primero usted debe leer la instantanea, y luego cada una de las revisiones entre la instantanea y su version

objetivo. Entre mas largo sea el historial de un fichero, mas revisiones deben ser leıdas, y por tanto toma mas tiempo

reconstruir una version particular.

La innovacion que aplica Mercurial a este problema es simple pero efectiva. Una vez la cantidad de informaci on de

deltas acumulada desde la ultima instantanea excede un umbral fijado de antemano, se almacena una nueva instantanea

(comprimida, por supuesto), en lugar de otro delta. Esto hace posible reconstruir cualquier  version de un fichero

rapidamente. Este enfoque funciona tan bien que desde entonces ha sido copiado por otros sistemas de control de

revisiones.

La figura 4.3 ilustra la idea. En una entrada en el fichero ındice de un revlog, Mercurial almacena el rango de

entradas (deltas) del fichero de datos que se deben leer para reconstruir una revision en particular.

Nota al margen: la influencia de la compresion de vıdeo

Si le es familiar la compresion de vıdeo, o ha mirado alguna vez una emision de TV a traves de cable digital

o un servicio de satelite, puede que sepa que la mayor parte de los esquemas de compresion de vıdeo almacenan

2N. del T. Contraccion de revision log, registro de revision.3N. del T. Diferencias.4N. del T. Retrieval. Recuperacion en el sentido de traer los datos, o reconstruirlos a partir de otros datos, pero no debido a una falla o calamidad,

sino a la operacion normal del sistema.

38

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 49/204

Índice, rev 7

Índice de bitácora de revisiones (archivo .i) Datos de Bitacora de revisiones (archivo .d)

Snapshot, rev 4

Delta, rev 4 a 5

Delta, rev 5 a 6

Delta, rev 6 a 7

Delta, rev 2 a 3

Figura 4.3: Instantanea de un revlog, con deltas incrementales

cada cuadro del mismo como un delta contra el cuadro predecesor. Adicionalmente, estos esquemas usan tecnicas de

compresion “con perdida” para aumentar la tasa de compresion, por lo que los errores visuales se acumulan a lo largo

de una cantidad de deltas inter-cuadros.

Ya que existe la posibilidad de que un flujo de vıdeo se “pierda” ocasionalmente debido a fallas en la se nal, y

para limitar la acumulacion de errores introducida por la compresion con perdidas, los codificadores de vıdeo insertan

periodicamente un cuadro completo (tambien llamado “cuadro clave”) en el flujo de vıdeo; el siguiente delta es gen-

erado con respecto a dicho cuadro. Esto quiere decir que si la senal de vıdeo se interrumpe, se reanudara una vez se

reciba el siguiente cuadro clave. Ademas, la acumulacion de errores de codificacion se reinicia con cada cuadro clave.

4.2.4. Identificacion e integridad fuerte

Ademas de la informacion de deltas e instantaneas, una entrada en un revlog contiene un hash criptografico de

los datos que representa. Esto hace dif ıcil falsificar el contenido de una revision, y hace f acil detectar una corrupcion

accidental.

Los hashes proveen mas que una simple revision de corrupcion: son usados como los identificadores para las

revisiones. Los hashes de identificacion de conjuntos de cambios que usted ve como usuario final son de las revisiones

de la bitacora de cambios. Aunque los ficheros de registro y el manifiesto tambien usan hashes, Mercurial solo los usa

tras bambalinas.

Mercurial verifica que los hashes sean correctos cuando recupera revisiones de ficheros y cuando jala cambios

desde otro repositorio. Si se encuentra un problema de integridad, Mercurial se quejara y detendra cualquier operacion

que este haciendo.

Ademas del efecto que tiene en la eficiencia en la recuperacion, el uso periodico de instantaneas de Mercurial lo

hace mas robusto frente a la corrupcion parcial de datos. Si un fichero de registro se corrompe parcialmente debido a

un error de hardware o del sistema, a menudo es posible reconstruir algunas o la mayorıa de las revisiones a partir delas secciones no corrompidas del fichero de registro, tanto antes como despues de la seccion corrompida. Esto no serıa

posible con un sistema de almacenamiento basado unicamente en deltas.

39

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 50/204

4.3. Historial de revisiones, ramas y fusiones

Cada entrada en el revlog de Mercurial conoce la identidad de la revision de su ancestro inmediato, al que se conoce

usualmente como su padre. De hecho, una revision contiene sitio no solo para un padre, sino para dos. Mercurial usa

un hash especial, llamado el “ID nulo”, para representar la idea de “no hay padre aqu ı”. Este hash es simplemente una

cadena de ceros.

En la figura 4.4 usted puede ver un ejemplo de la estructura conceptual de un revlog. Los ficheros de registro,manifiestos, y bitacoras de cambios comparten la misma estructura; solo difieren en el tipo de datos almacenados en

cada delta o instantanea.

La primera revision en un revlog (al final de la imagen) tiene como padre al ID nulo, en las dos ranuras disponibles

para padres. En una revision normal, la primera ranura para padres contiene el ID de la revision padre, y la segunda

contiene el ID nulo, senalando ası que la revision solo tiene un padre real. Un par de revisiones que tenga el mismo ID

padre son ramas. Una revision que representa una fusion entre ramas tiene dos IDs de revision normales en sus ranuras

para padres.

4.4. El directorio de trabajo

En el directorio de trabajo, Mercurial almacena una instantanea de los ficheros del repositorio como si fueran los

de un conjunto de cambios particular.El directorio de trabajo “sabe” que conjunto de cambios contiene. Cuando usted actualiza el directorio de traba-

 jo para que contenga un conjunto de cambios particular, Mercurial busca la revision adecuada del manifiesto para

averiguar que ficheros estaba monitoreando cuando se hizo la consignacion del conjunto de cambios, y que revision

de cada fichero era la actual en ese momento. Luego de eso, recrea una copia de cada uno de esos ficheros, con los

mismos contenidos que tenıan cuando fue consignado el conjunto de cambios.

El estado de directorio5 contiene el conocimiento de Mercurial acerca del directorio de trabajo. Allı se detalla a

que conjunto de cambios es actualizado el directorio de trabajo, y todos los ficheros que Mercurial esta monitoreando

en este directorio.

Tal como la revision de un revlog tiene espacio para dos padres, para que pueda representar tanto una revisi on

normal (con un solo padre) o una fusion de dos revisiones anteriores, el estado de directorio tiene espacio para dos

padres. Cuando usted usa el comando “hg update”, el conjunto de cambios al que usted se actualiza es almacenado

en la casilla destinada al “primer padre”, y un ID nulo es almacenado en la segunda. Cuando usted hace una fusion

(“hg merge”) con otro conjunto de cambios, la casilla para el primer padre permanece sin cambios, y la casilla parael segundo es actualizada con el conjunto de cambios con el que usted acaba de hacer la fusi on. El comando “hg

parents” le indica cuales son los padres del estado de directorio.

4.4.1. Que pasa en una consignacion

El estado de directorio almacena informacion sobre los padres para algo mas que mero registro. Mercurial usa los

padres del estado de directorio como los padres de un nuevo conjunto de cambios cuando usted hace una consignacion.

La figura 4.5 muestra el estado normal del directorio de trabajo, que tiene un unico conjunto de cambios como

padre. Dicho conjunto de cambios es la punta, el conjunto de cambios mas reciente en el repositorio que no tiene

hijos.

Es util pensar en el directorio de trabajo como en “el conjunto de cambios que estoy a punto de enviar”. Cualquier

fichero que usted le diga a Mercurial que fue anadido, borrado, renombrado o copiado, se vera reflejado en ese conjunto

de cambios, como tambien se veran las modificaciones a cualquiera de los ficheros que Mercurial ya est e monitorean-do; el nuevo conjunto de cambios dentra los padres del directorio de trabajo como propios.

Luego de una consignacion, Mercurial actualizara los padres del directorio de trabajo, de tal manera que el primer

padre sea el ID del nuevo conjunto de cambios, y el segundo sea el ID nulo. Esto puede verse en la figura 4.6. Mercurial

no toca ninguno de los ficheros del directorio de trabajo cuando usted hace la consignacion; solo modifica el estado de

directorio para anotar sus nuevos padres.

5N. del T. dirstate, en ingles en el original.

40

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 51/204

4.4.2. Creacion de un nuevo frente

Es perfectamente normal actualizar el directorio de trabajo a un conjunto de cambios diferente a la punta actual. Por

ejemplo, usted podrıa desear saber en que estado se encontraba su proyecto el martes pasado, o podrıa estar buscando

en todos los conjuntos de cambios para saber cuando se introdujo un fallo. En casos como estos, la accion natural

es actualizar el directorio de trabajo al conjunto de cambios de su interes, y examinar directamente los ficheros en el

directorio de trabajo para ver sus contenidos tal como estaban en el momento de hacer la consignaci on. El efecto que

tiene esto se muestra en la figura 4.7.

Una vez se ha actualizado el directorio de trabajo a un conjunto de cambios anterior, qu e pasa si se hacen cambios,

y luego se hace una consignacion? Mercurial se comporta en la misma forma que describı anteriormente. Los padres

del directorio de trabajo se convierten en los padres del nuevo conjunto de cambios. Este nuevo conjunto de cambios

no tiene hijos, ası que se convierte en la nueva punta. Y el repositorio tiene ahora dos conjuntos de cambios que no

tienen hijos; a estos los llamamos frentes. Usted puede apreciar la estructura que esto crea en la figura 4.8.

Nota: Si usted es nuevo en Mercurial, deberıa tener en mente un “error” comun,

que es usar el comando “hg pull” sin ninguna opcion. Por defecto, el comando

“hg pull” no actualiza el directorio de trabajo, ası que usted termina trayendo

nuevos conjuntos de cambios a su repositorio, pero el directorio de trabajo sigue

usando el mismo conjunto de cambios que tenıa antes de jalar. Si usted hace al-

gunos cambios, y luego hace una consignacion, estara creando un nuevo frente,

porque su directorio de trabajo no es sincronizado a cualquiera que sea la nuevapunta.

Pongo la palabra “error” en comillas porque todo lo que usted debe hacer para

rectificar la situacion es hacer una fusion (“hg merge”), y luego una consignacion

(“hg commit”). En otras palabras, esto casi nunca tiene consecuencias negativas;

solo sorprende a la gente. Discutire otras formas de evitar este comportamiento,

y porque Mercurial se comporta de esta forma, inicialmente sorprendente, m as

adelante.

4.4.3. Fusion de frentes

Cuando usted ejecuta el comando “hg merge”, Mercurial deja el primer padre del directorio de trabajo intacto, y

escribe como segundo padre el conjunto de cambios contra el cual usted esta haciendo la fusion, como se muestra en

la figura 4.9.Mercurial tambien debe modificar el directorio de trabajo, para fusionar los ficheros que el monitorea en los dos

conjuntos de cambios. Con algunas simplificaciones, el proceso es el siguiente, por cada fichero en los manifiestos de

ambos conjuntos de cambios.

Si ningun conjunto de cambios ha modificado un fichero, no se hace nada con el mismo.

Si un conjunto de cambios ha modificado un fichero, y el otro no lo ha hecho, se crea una copia del fichero con

las modificaciones pertinentes en el directorio de trabajo.

Si un conjunto de cambios borra un fichero, y el otro no lo ha hecho (o tambien lo borro), se borra dicho fichero

del directorio de trabajo.

Si un conjunto de cambios ha borrado un fichero, pero el otro lo ha modificado, se le pregunta al usuario

que hacer: conservar el fichero modificado, o borrarlo?

Si ambos conjuntos de cambios han modificado un fichero, se invoca el programa externo de fusi on para definir

el nuevo contenido del fichero fusionado. Esto puede requerir interaccion directa de parte del usuario.

Si un conjunto de cambios ha modificado un fichero, y el otro ha renombrado o copiado el mismo, asegurarse

de que los cambios sigan al nuevo nombre de fichero.

41

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 52/204

Hay mas detalles—hacer una fusion tiene una gran cantidad de casos especiales—pero estas son las elecciones mas

comunes que se ven involucradas en una fusion. Como usted puede ver, muchos de los casos son completamente

automaticos, y de hecho la mayorıa de las fusiones terminan automaticamente, sin requerir la interaccion del usuario

para resolver ningun conflicto.

Cuando considere que pasa cuando usted hace una consignacion despues de una fusion, de nuevo el directorio

de trabajo es “el conjunto de cambios que estoy a punto de consignar”. Una vez termina su trabajo el comando “ hg

merge”, el directorio de trabajo tiene dos padre; estos se convertiran en los padres del nuevo conjunto de cambios.Mercurial le permite hacer multiples fusiones, pero usted debe consignar los resultados de cada fusion sucesi-

vamente. Esto es necesario porque Mercurial solo monitorea dos padres, tanto para las revisiones como para los

directorios de trabajo. Aunque tecnicamente es posible fusionar varios conjuntos de trabajo en una sola operacion, la

posibilidad de confundir al usuario y crear un desorden terrible en la fusion se hace incontenible de inmediato.

4.5. Otras caracterısticas de dise ˜ no interesantes

En las secciones anteriores, he tratado de resaltar algunos de los aspectos mas importantes del diseno de Mercurial,

para mostrar que se presta gran cuidado y atencion a la confiabilidad y el desempeno. Sin embargo, la atencion a

los detalles no para ahı. Hay una cantidad de aspectos de la construccion de Mercurial que encuentro interesantes

personalmente. Detallare unos cuantos de ellos aquı, aparte de los elementos “importantes” de arriba, para que, si

usted esta interesado, pueda obetener una idea mejor de la cantidad de esfuerzo mental invertido en el diseno de unsistema bien disenado.

4.5.1. Compresion ingeniosa

Cuando es adecuado, Mercurial almacenara tanto las instantaneas como los deltas en formato comprimido. Lo hace

tratando siempre de comprimir una instantanea o delta, y conservando la version comprimida solo si es mas pequena

que la version sin compresion.

Esto implica que Mercurial hace “lo correcto” cuando almacena un fichero cuyo formato original esta comprimido,

como un fichero zip o una imagen JPEG. Cuando estos tipos de ficheros son comprimidos por segunda vez, el fichero

resultante usualmente es mas grande que la version comprimida una sola vez, por lo que Mercurial almacenara el

fichero zip o JPEG original.

Los deltas entre revisiones de un fichero comprimido usualmente son mas grandes que las instantaneas del mismo

fichero, y Mercurial de nuevo hace “lo correcto” en estos casos. El encuentra que dicho delta excede el umbral respectoal cual se deberıa almacenar una instantanea completa del fichero, ası que almacena la instantanea, ahorrando espacio

de nuevo respecto al enfoque simplista de usar unicamente deltas.

Recompresion de red

Cuando almacena las revisiones en disco, Mercurial usa el algoritmo de compresi on “deflacion” (el mismo usado

en el popular formato de fichero zip), que provee una buena velocidad con una tasa de compresion respetable. Sin

embargo, cuando se transmiten datos de revisiones a traves de una conexion de red, Mercurial descomprime los datos

comprimidos de las revisiones.

Si la conexion es hecha a traves de HTTP, Mercurial recomprime el flujo completo de datos usando un algoritmo de

compresion que brinda una mejor tasa de compresion (el algoritmo Burrows-Wheeler del ampliamente usado paquete

de compresion bzip2). Esta combinacion de algoritmo y compresion del flujo completo de datos (en vez de una

revision a la vez) reduce sustancialmente la cantidad de bytes a transferir, brindando as ı un mejor desempeno de redsobre casi todo tipo de redes.

(Si la conexion se hace sobre ssh, Mercurial no recomprmime el flujo, porque ssh puede hacer esto por sı mismo.)

4.5.2. Reordenado de lectura/escritura y atomicidad

Anadir datos al final de un fichero no es todo lo que hace falta para garantizar que un lector no vera una escritura

parcial. Si recuerda la figura 4.2, las revisiones en la bitacora de cambios apuntan a revisiones en el manifiesto, y las

42

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 53/204

revisiones en el manifiesto apuntan a revisiones en ficheros de registro. Esta jerarquıa es deliberada.

Un escritor inicia una transaccion al escribir los datos del ficheros del fichero de registro y el manifiesto, y no

escribe nada en la bitacora de cambios hasta que dichas escrituras hayan terminado. Un lector empieza leyendo datos

de la bitacora de cambios, luego del manifiesto, y finalmente del fichero de registro.

Como el escritor siempre termina de escribir los datos en el fichero de registro y en el manifiesto antes de escribir

a la bitacora de cambios, un lector nunca vera un apuntador a una version parcialmente escrita de revisiones del

manifiesto desde la bitacora de cambios, y nunca leera un apuntador a una revision parcialmente escrita del fichero deregistro desde el manifiesto.

4.5.3. Acceso concurrente

El reordenado de lectura/escritura y la atomicidad garantizan que Mercurial nunca necesita bloquear un repositorio

cuando esta leyendo datos, aun si se esta escribiendo al repositorio mientras se hace la lectura. Esto tiene un gran

efecto en la escalabilidad; usted puede tener cualquier cantidad de procesos Mercurial leyendo datos de un repositorio

de manera segura al mismo tiempo, sin importar si se esta escribiendo al mismo o no.

La naturaleza carente de bloqueos de la lectura significa que si usted esta compartiendo un repositorio en un

sistema multiusuario, no necesita dar a los usuarios locales permisos de escritura a su repositorio para que ellos

puedan clonarlo o jalar cambios; solo necesitan permisos de lectura. (Esta no es una caracterıstica comun entre los

sistemas de control de revisiones, ası que no la de por hecha! Muchos de ellos requieren que los lectores sean capaces

de bloquear el repositorio antes de poder leerlo, y esto requiere acceso de escritura en al menos un directorio, lo quepor supuesto se convierte en una fuente de todo tipo de problemas administrativos y de seguridad bastante molestos.)

Mercurial usar bloqueos para asegurarse de que solo un proceso pueda escribir a un repositorio al mismo tiempo

(el mecanismo de bloqueo es seguro incluso sobre sistemas de ficheros notoriamente hostiles al bloqueo, como NFS).

Si un repositorio esta bloqueado, los escritores esperaran un buen rato para revisar si el repositorio ya ha sido desblo-

queado, pero si el repositorio sique bloqueado por mucho tiempo, el proceso que intenta escribir fallar a por tiempo de

espera maximo. Esto significa que sus guiones automaticos diarios no se quedaran esperando para siempre, apilandose

si el sistema se cayo sin que nadie se diera cuenta, por ejemplo. (S ı, el tiempo de espera maximo es configurable, de

cero a infinito).

Acceso seguro al estado de directorio

Al igual que con los datos de revision, Mercurial no requiere un bloqueo para leer el fichero de estado de directorio;

sı se usa un bloqueo para escribir a el. Para evitar la posibilidad de leer una copia parcialmente escrita del fichero deestado de directorio, Mercurial escribe a un fichero con un nombre unico en el mismo directorio del fichero de estado

de directorio, y luego renombra atomicamente este fichero temporal a dirstate6. Ası se garantiza que el fichero

llamado dirstate este completo, y no parcialmente escrito.

4.5.4. Evitar movimientos de brazo

Un aspecto crıtico para el desempeno de Mercurial es evitar los movimientos del brazo de lectura del disco duro, ya

que cualquier movimiento de brazo es mucho mas costoso que incluso una operacion de lectura relativamente grande.

Es por esto que, por ejemplo, el estado de directorio es almacenado como un solo fichero. Si hubiera un estado de

directorio por cada directorio que Mercurial monitorea, el disco harıa un movimiento de brazo por cada directorio. En

cambio, Mercurial lee el estado de directorio completo en un solo paso.

Mercurial tambien usa un esquema de “copiar al escribir” cuando clona un repositorio en un mismo medio de

almacenamiento local. En vez de copiar cada fichero de revlog del repositorio viejo al nuevo, se crea un “enlace duro”,que es una manera sucinta de decir “estos dos nombres apuntan al mismo fichero”. Cuando Mercurial est a a punto de

escribir a uno de los ficheros de revlog, revisa si la cantidad de nombres apuntando al fichero es de m as de uno. Si lo

es, mas de un repositorio esta usando el fichero, ası que Mercurial hace una nueva copia del fichero, privada para este

repositorio.

6N. del T. Estado de directorio.

43

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 54/204

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. Aunque esto es cierto, el almacenamiento

es barato, y este metodo brinda el maximo rendimiento al tiempo que delega la mayor parte del trabajo de manejo de

ficheros al sistema operativo. Un esquema alternativo seguramente reducirıa el desempeno y aumentarıa la complejidad

del software, cada uno de los cuales es mucho mas importante para la “sensacion” que se tiene del software en el trabajo

dıa a dıa.

4.5.5. Otros contenidos del estado de directorio

Debido a que Mercurial no lo fuerza a indicar si usted est a modificando un fichero, se usa el estado de directorio

para almacenar informacion extra para poder determinar efecientemente si usted ha modificado un fichero. Por cada

fichero en el directorio de trabajo, se almacena el momento en que Mercurial modific o por ultima vez el fichero, y el

tamano del fichero en ese momento.

Cuando usted anade (“hg add”), remueve (“hg remove”), renombra (“hg rename”)o copia (“hg copy”) ficheros,

Mercurial actualiza el estado de directorio para saber que hacer con dichos ficheros cuando usted haga la consignacion.

Cuando Mercurial esta revisando el estado de los ficheros en el directorio de trabajo, revisa primero la fecha de

modificacion del fichero. Si no ha cambiado, el fichero no ha sido modificado. Si el tamano del fichero ha cambiado,

el fichero ha sido modificado. Solo en el caso en que el tiempo de modificacion ha cambiado, pero el tamano no, es

necesario leer el contenido del fichero para revisar si ha cambiado. Almacenar estos pocos datos reduce dramatica-

mente la cantidad de datos que Mercurial debe leer, lo que brinda una mejora en el rendimiento grande, comparadocon otros sistemas de control de revisiones.

44

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 55/204

Segundo padre

32bf9a5f22c0

Hash de revisión

34b8b7a15ea1

...

Datos de Revisión (delta o snapshot)

Primer padre

000000000000

Segundo padre

000000000000

Hash de revisión

ff9dc8bc2a8b

...

Datos de revisión (delta o snapshot)

Primer padre

34b8b7a15ea1

Segundo padre

000000000000

Hash de revisión

1b67dc96f27a

...

Datos de revisión (delta o snapshot)

Primer padre

ff9dc8bc2a8b

Segundo padre

000000000000

Hash de revisión

5b80c922ebdd

...

Datos de revisión (delta o snapshot)

Primer padre

ecacb6b4c9fd

Segundo padre

000000000000

Hash de revisión

32bf9a5f22c0

...

Datos de revisión (delta o snapshot)

Primer padre

ff9dc8bc2a8b

Segundo padre

000000000000

Hash de revisión

ecacb6b4c9fd

...

Datos de revisión (delta o snapshot)

Revisión principal

(sin hijos)

Revisión de fusión

(dos padres)

Ramas

(dos revisiones,

mismo padre)

Primera revisión

(ambos padres nulos)

Primer padre

5b80c922ebdd

Figura 4.4:

45

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 56/204

e7639888bb2f

7b064d8bac5e

000000000000

Historia en el repositorio

e7639888bb2f

000000000000

Primer padre

Segundo padre

Padres del directorio de trabajo

Figura 4.5: El directorio de trabajo puede tener dos padres

dfbbb33f3fa3

e7639888bb2f

7b064d8bac5e

000000000000

Historia en el repositorio

dfbbb33f3fa3

000000000000

Primer padre

Segundo padre

Padres del directorio de trabajo

Nuevo

conjuntode

cambios

Figura 4.6: El directorio de trabajo obtiene nuevos padres luego de una consignaci on

46

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 57/204

e7639888bb2f

7b064d8bac5e

000000000000

Historia en el repositorio

7b064d8bac5e

000000000000

Primer padre

Segundo padre

Padres del directorio de trabajo

Figura 4.7: El directorio de trabajo, actualizado a un conjunto de cambios anterior

e7639888bb2f

7b064d8bac5e

000000000000

ffb20e1701ea

000000000000

Primer padre

Segundo padre

Padres del directorio de trabajo

ffb20e1701ea

Cabeza Pre−existente Cabeza recién creada (y tip)

Figura 4.8: Despues de una consignacion hecha mientras se usaba un conjunto de cambios anterior

47

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 58/204

7b064d8bac5e

000000000000

ffb20e1701ea

e7639888bb2f

Primer padre (sin cambio)

Segundo padre

Padres del directorio de trabajo

ffb20e1701ea

Cabeza pre−existente Cabeza recién creada(y tip)

e7639888bb2f

Figura 4.9: Fusion de dos frentes

48

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 59/204

Capıtulo 5

Mercurial dıa a dıa

5.1. Como indicarle a Mercurial que ficheros seguir

Mercurial no trabaja con ficheros en su repositorio a menos que usted se lo indique expl ıcitamente. La orden “hg

status” le mostrara cuales ficheros son desconocidos para Mercurial; se emplea un “?” para mostrar tales ficheros.

Para indicarle a Mercurial que tenga en cuenta un fichero, emplee la orden “hg add”. Una vez que haya adicionadoel fichero, la lınea referente al fichero al aplicar la orden “hg status” para tal fichero cambia de “?” a “A”.

1 $ hg init add-example

2 $ cd add-example

3 $ e c h o a > a

4 $ hg status

5 ? a

6 $ hg add a

7 $ hg status

8 A a

9 $ hg commit -m ’Added one file’

10 $ hg status

Despues de invocar “hg commit”, los ficheros que haya adicionado antes de consignar no se listar an en la salida

de “hg status”. La razon para esto es que “hg status” solamente le muestra aquellos ficheros “interesantes” —

los que usted haya modificado o a aquellos sobre los que usted haya indicado a Mercurial hacer algo— de forma

predeterminada. Si tiene un repositorio que contiene miles de ficheros, rara vez desear a saber cuales de ellos estan

siendo seguidos por Mercurial, pero que no han cambiado. (De todas maneras, puede obtener tal informaci on; mas

adelante hablaremos de ello.)

Cuando usted anade un fichero, Mercurial no hace nada con el inmediatamente. En cambio, tomara una instantanea

del estado del fichero la proxima vez que usted consigne. Continuara haciendo seguimiento a los cambios que haga

sobre el fichero cada vez que consigne, hasta que usted lo elimine.

5.1.1. Nombramiento explıcito e implıcito de ficheros

Mercurial tiene un comportamiento util en el cual si a una orden, le pasa el nombre de un directorio, todas las

ordenes lo interpretaran como “Deseo operar en cada fichero de este directorio y sus subdirectorios”.

1 $ mkdir b

2 $ echo b > b/b

3 $ echo c > b/c

4 $ mkdir b/d

49

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 60/204

5 $ echo d > b/d/d

6 $ hg add b

7 adding b/b

8 adding b/c

9 adding b/d/d

10 $ hg commit -m ’Added all files in subdirectory’

Tenga en cuenta que en este ejemplo Mercurial imprimio los nombres de los ficheros que se adicionaron, mientras que

no lo hizo en el ejemplo anterior cuando adicionamos el fichero con nombre a.

En el ultimo caso hicimos explıcito el nombre del fichero que deseabamos adicionar en la lınea de ordenes, y

Mercurial asume en tales casos que usted sabe lo que esta haciendo y no imprime informacion alguna.

Cuando hacemos impl  ıcitos los nombres de los ficheros dando el nombre de un directorio, Mercurial efectua el

paso extra de imprimir el nombre de cada fichero con el que va a hacer algo. Esto para aclarar lo que est a sucediendo,

y reducir en lo posible una sorpresa silenciosa pero fatal. Este comportamiento es com un a la mayorıa de ordenes en

Mercurial.

5.1.2. Nota al margen: Mercurial trata ficheros, no directorios

Mercurial no da seguimiento a la informacion de los directorios. En lugar de eso tiene en cuenta las rutas de

los ficheros. Antes de crear un fichero, primero crea todos los directorios que hagan falta para completar la ruta delmismo. Despues de borrar un fichero, borra todos los directorios vacıos que estuvieran en la ruta del fichero borrado.

Suena como una diferencia trivial, pero tiene una consecuencia practica menor: no es posible representar un directorio

completamente vacıo en Mercurial.

Los directorios vacıos rara vez son utiles, y hay soluciones alternativas no intrusivas que usted puede emplear para

obtener el efecto apropiado. 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.

Si necesita un directorio vacıo en su repositorio, hay algunas formas de lograrlo. Una es crear un directorio,

despues hacer “hg add” a un fichero “oculto” dentro de ese directorio. En sistemas tipo Unix, cualquier fichero cuyo

nombre comience con un punto (“.”) es tratado como oculto por la mayorıa de comandos y herramientas GUI. Esta

aproximacion se ilustra en la figura 5.1.

1

$ hg init hidden-example2 $ cd hidden-example

3 $ mkdir empty

4 $ touch empty/.hidden

5 $ hg add empty/.hidden

6 $ hg commit -m ’Manage an empty-looking directory’

7 $ ls empty

8 $ cd ..

9 $ hg clone hidden-example tmp

10 updating working directory

11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

12 $ ls tmp

13 empty

14 $ ls tmp/empty

Figura 5.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 construccion

antes de que lo necesiten.

50

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 61/204

5.2. Como dejar de hacer seguimiento a un fichero

Si decide que un fichero no pertenece a su repositorio, use la orden “hg remove”; se borrara el fichero y le

indicara a Mercurial que deje de hacerle seguimiento. Los ficheros eliminados se representan con “ R” al usar “hg

status”.

1 $ hg init remove-example

2 $ cd remove-example

3 $ e c h o a > a

4 $ mkdir b

5 $ echo b > b/b

6 $ h g a d d a b

7 adding b/b

8 $ hg commit -m ’Small example for file removal’

9 $ hg remove a

10 $ hg status

11 R a

12 $ hg remove b

13 removing b/b

Despues de hacer “hg remove” a un fichero, Mercurial dejara de hacer seguimiento al mismo, incluso si recrea el

fichero con el mismo nombre en su directorio de trabajo. Si decide recrear un fichero con el mismo nombre y desea que

Mercurial le haga seguimiento, basta con hacerle “hg add”. Mercurial sabra que el fichero recientemente adicionado

no esta relacionado con el fichero anterior que tenıa el mismo nombre.

5.2.1. Al eliminar un fichero no se afecta su historial

Es preciso tener en cuenta que eliminar un fichero tiene solo dos efectos.

Se elimina la version actual del fichero del directorio de trabajo.

Mercurial deja de hacer seguimiento a los cambios del fichero desde la proxima consignacion.

Al eliminar un fichero no se altera de ninguna manera el historial del mismo.Si actualiza su directorio de trabajo a un conjunto de cambios en el cual el fichero que elimino aun era tenido en

cuenta, este reaparecera en el directorio de trabajo, con los contenidos que este tenıa cuando se consigno tal conjunto

de cambios. Si usted actualiza el directorio de trabajo a un conjunto de cambios posterior en el cual el fichero hab ıa

sido eliminado, Mercurial lo eliminara de nuevo del directorio de trabajo.

5.2.2. Ficheros perdidos

Mercurial considera como perdido un fichero que usted borro, pero para el que no se uso “hg remove”. Los

ficheros perdidos se representan con “!” al visualizar “hg status”. Las ordenes de Mercurial generalmente no haran

nada con los ficheros perdidos.

1 $ hg init missing-example

2 $ cd missing-example3 $ e c h o a > a

4 $ hg add a

5 $ hg commit -m ’File about to be missing’

6 $ rm a

7 $ hg status

8 ! a

51

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 62/204

Si su repositorio contiene un fichero que “hg status” reporta como perdido, y desea que el mismo se vaya, se

puede usar “hg remove --after” posteriormente para indicarle a Mercurial que usted deseaba borrar tal fichero.

1 $ hg remove --after a

2 $ hg status

3 R a

Por otro lado, si borro un fichero perdido por accidente, puede usar “hg revert nombre de fichero” para

recuperar el fichero. Reaparecera, sin modificaciones.

1 $ hg revert a

2 $ cat a

3 a

4 $ hg status

5.2.3. Nota al margen: ¿Por que decirle explıcitamente a Mercurial que elimine un fichero?

Es posible que se haya preguntado por que Mercurial exige que usted le indique explıcitamente que esta borrando

un fichero. Al principio del desarrollo de Mercurial, este permitıa que usted borrara el fichero sin mas; Mercurial se

darıa cuenta de la ausencia del fichero automaticamente despues de la ejecucion de “hg commit”, y dejarıa de hacer

seguimiento al fichero. En la practica, resultaba muy sencillo borrar un fichero accidentalmente sin darse cuenta.

5.2.4. Atajo util—agregar y eliminar ficheros en un solo paso

Mercurial ofrece una orden combinada, “hg addremove”, que agrega los ficheros que no tienen seguimiento y

marca los ficheros faltantes como eliminados.

1 $ hg init addremove-example

2 $ cd addremove-example

3 $ e c h o a > a

4 $ e c h o b > b

5 $ hg addremove

6 adding a

7 adding b

La orden “hg commit” se puede usar con la opcion -A que aplica el mismo agregar-eliminar, seguido inmediatamente

de una consignacion.

1 $ e c h o c > c

2 $ hg commit -A -m ’Commit with addremove’

3 adding c

5.3. Copiar ficheros

Mercurial ofrece la orden “hg copy” para hacer una copia nueva de un fichero. Cuando se copia un fichero con

esta orden, Mercurial lleva un registro indicando que el nuevo fichero es una copia del fichero original. Los ficheros

copiados se tratan de forma especial cuando usted hace una fusion con el trabajo de alguien mas.

52

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 63/204

5.3.1. Resultados de copiar un fichero durante una fusion

Durante una fusion los cambios “siguen” una copia. Para ilustrar lo que esto significa, haremos un ejemplo. Comen-

zaremos con el mini repositorio usual que contiene un solo fichero

1 $ hg init my-copy

2 $ cd my-copy

3 $ echo line > file4 $ hg add file

5 $ hg commit -m ’Added a file’

Debemos hacer algo de trabajo en paralelo, de forma que tengamos algo para fusionar. Aquı clonamos el repositorio.

1 $ cd ..

2 $ hg clone my-copy your-copy

3 updating working directory

4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

De vuelta en el repositorio inicial, usemos la orden “hg copy” para hacer una copia del primer fichero que creamos.

1 $ cd my-copy

2 $ hg copy file new-file

Si vemos la salida de la orden “hg status”, el fichero copiado luce tal como un fichero que se ha anadido

normalmente.

1 $ hg status

2 A new-file

Pero si usamos la opcion -C de la orden “hg status”, se imprimira otra lınea: el fichero desde el cual fue copiado

nuestro fichero recien anadido.

1 $ hg status -C

2 A new-file

3 file

4 $ hg commit -m ’Copied file’

Ahora, en el repositorio que clonamos, hagamos un cambio en paralelo. Adicionaremos una lınea de contenido al

fichero original que creamos.

1 $ cd ../your-copy

2 $ echo ’new contents’ >> file

3 $ hg commit -m ’Changed file’

Hemos modificado el fichero file en este repositorio. Cuando jalemos los cambios del primer repositorio y fu-

sionemos las dos cabezas, Mercurial propagara los cambios que hemos hecho localmente en file a su copia, new-file.

1 $ hg pull ../my-copy

2 pulling from ../my-copy

3 searching for changes

4 adding changesets

5 adding manifests

6 adding file changes

53

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 64/204

7 added 1 changesets with 1 changes to 1 files (+1 heads)

8 (run ’hg heads’ to see heads, ’hg merge’ to merge)

9 $ hg merge

10 merging file and new-file

11 0 files updated, 1 files merged, 0 files removed, 0 files unresolved

12 (branch merge, don’t forget to commit)

13 $ cat new-file14 line

15 new contents

5.3.2. ¿Por que los cambios se reflejan en las copias?

Este comportamiento de cambios en ficheros que se propagan a las copias de los ficheros parecer ıa esoterico, pero

en la mayorıa de casos es absolutamente deseable. Es indispensable recordar que esta propagaci on solamente sucede

cuando fusionamos. Por lo tanto si sobre un fichero se usa “ hg copy”, y se modifica el fichero original durante el

curso normal de su trabajo, nada pasara.

Lo segundo a tener en cuenta es que las modificaciones solamente se propagaran en las copias unicamente si los

repositorios de los cuales esta jalando los cambios no saben de la copia.

Explicaremos a continuaci´on la raz

´on de este comportamiento de Mercurial. Digamos que yo he aplicado unarreglo de un fallo importante a un fichero fuente y consigne los cambios. Por otro lado, usted decidio hacer “hg

copy” sobre el fichero en su repositorio, sin saber acerca del fallo o sin ver el arreglo, y ha comenzado a trabajar sobre

su copia del fichero.

Si jala y fusiona mis cambios y Mercurial no hubiera propagado los cambios en las copias, su fichero fuente tendrıa

el fallo, a menos que usted haya recordado propagar el arreglo del fallo a mano, el mismo permanecer   ıa en su copia

del fichero.

Mercurial previene esta clase de problemas, gracias a la propagacion automatica del cambio que arreglo el fallo

del fichero original. Hasta donde se, Mercurial es el ´ unico sistema de control de revisiones que propaga los cambios

en las copias de esta forma.

Cuando su historial de cambios tiene un registro de la copia y la subsecuente fusi on, usualmente no es necesario

propagar los cambios el fichero original a las copias del mismo, y por esta raz on Mercurial propaga unicamente los

cambios en las copias hasta este punto y no mas alla.

5.3.3. Como hacer que los cambios no sigan a la copia?

Si por algun motivo usted decide que esta caracterıstica de propagacion automatica de cambios en las copias

no es para usted, simplemente use la orden usual de su sistema para copiar ficheros (en sistemas tipo Unix, es cp),

y posteriormente use “hg add” sobre la nueva copia hecha a mano. Antes de hacerlo, de todas maneras, relea la

seccion 5.3.2, y tome una decision asegurandose que este comportamiento no es el apropiado para su caso especıfico.

5.3.4. Comportamiento de la orden “hg copy”

Cuando usa la orden “hg copy”, Mercurial hace una copia de cada fichero fuente tal como se encuentra en el direc-

torio actual. Esto significa que si usted hace modificaciones a un fichero, y le aplica “hg copy” sin haber consignado

primero los cambios, la nueva copia contendra tambien las modificaciones que haya hecho hasta ese punto. (Este

comportamiento me parece poco intuitivo, y por tal motivo lo menciono.)La orden “hg copy” actua de forma parecida a la orden cp de Unix (puede usar el alias “hg cp” si le es mas

comodo). El ultimo argumento es el destino, y todos los argumentos previos son las fuentes. Si solamente indica un

fichero como la fuente, y el destino no existe, se crea un fichero nuevo con ese nombre.

1 $ mkdir k

2 $ hg copy a k

54

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 65/204

3 $ ls k

4 a

Si el destino es un directorio, Mercurial copia las fuentes en este.

1 $ mkdir d

2 $ h g c o p y a b d3 $ ls d

4 a b

La copia de un directorio es recursiva, y preserva la estructura del directorio fuente.

1 $ hg copy c e

2 copying c/a/c to e/a/c

Si tanto la fuente como el destino son directorios, la estructura de la fuente se recrea en el directorio destino.

1 $ hg copy c d

2 copying c/a/c to d/c/a/c

De la misma forma que la orden “hg rename”, si copia un fichero manualmente y desea que Mercurial sepa que

ha copiado un fichero, basta con aplicar la opcion --after a la orden “hg copy”.

1 $ c p a z

2 $ hg copy --after a z

5.4. Renombrar ficheros

La necesidad de renombrar un fichero es mas comun que hacer una copia del mismo. La razon por la cual discutı la

orden “hg copy” antes de hablar acerca de cambiar el nombre de los ficheros, es que Mercurial trata el renombrar un

fichero de la misma forma que una copia. Por lo tanto, saber lo que hace Mercurial cuando usted copia un fichero le

indica que esperar cuando renombra un fichero.Cuando usa la orden “hg rename”, Mercurial hace una copia de cada fichero fuente, lo borra y lo marca como

fichero eliminado.

1 $ hg rename a b

La orden “hg status” muestra la nueva copia del fichero como anadida y el fichero inicial de la copia, como elimi-

nado.

1 $ hg status

2 A b

3 R a

De la misma forma en que se usa la orden “hg copy

”, debemos usar la opcion-C

de la orden “hg status

” paraverificar que el fichero anadido realmente comienza a ser seguido por Mercurial como una copia del fichero original,

ahora eliminado.

1 $ hg status -C

2 A b

3 a

4 R a

55

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 66/204

Igual que con “hg remove” y “hg copy”, puede indicarsele a Mercurial acerca de un renombramiento inmediato

con la opcion --after. El comportamiento de la orden “hg rename” y las opciones que acepta, son similares a la

orden “hg copy” en casi todo.

5.4.1. Renombrar ficheros y fusionar cambios

Dado que el renombrado de Mercurial se implementa como un copiar-y-eliminar, la misma propagacion de cambiosocurre cuando usted fusiona despues de renombrar como despues de hacer una copia.

Si yo modifico un fichero y usted lo renombra a un nuevo fichero, y posteriormente fusionamos nuestros respectivos

cambios, mi modificacion al fichero bajo su nombre original se propagara en el fichero con el nuevo nombre. (Es lo

que se esperarıa que “simplemente funcione,” pero, no todos los sistemas de control de revisiones hacen esto.)

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, puede ser util,” deberıa ser claro que el seguimiento de cambios de un renombramiento es

definitivamente importante. Sin esto, serıa muy sencillo que los cambios se quedaran atras cuando los ficheros se

renombran.

5.4.2. Cambios de nombre divergentes y fusion

El caso de renombramiento con nombres divergentes ocurre cuando dos desarrolladores comienzan con un fichero—

llamemoslo foo—en sus repositorios respectivos.

1 $ hg clone orig anne

2 updating working directory

3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

4 $ hg clone orig bob

5 updating working directory

6 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

Anne renombra el fichero a bar.

1 $ cd anne

2 $ hg mv foo bar

3 $ hg ci -m ’Rename foo to bar’

Mientras que Bob lo renombra como quux.

1 $ cd ../bob

2 $ hg mv foo quux

3 $ hg ci -m ’Rename foo to quux’

Veo esto como un conflicto porque cada desarrollador ha expresado intenciones diferentes acerca de como consid-

era deberıa haberse nombrado el fichero.

¿Que cree que deberıa pasar cuando fusionen su trabajo? El comportamiento de Mercurial es que siempre preserva

ambos nombres cuando fusiona los conjuntos de cambios que contienen nombres divergentes.

1 # See http://www.selenic.com/mercurial/bts/issue455

2 $ cd ../orig

3 $ hg pull -u ../anne

4 pulling from ../anne

5 searching for changes

6 adding changesets

7 adding manifests

56

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 67/204

8 adding file changes

9 added 1 changesets with 1 changes to 1 files

10 1 files updated, 0 files merged, 1 files removed, 0 files unresolved

11 $ hg pull ../bob

12 pulling from ../bob

13 searching for changes

14 adding changesets15 adding manifests

16 adding file changes

17 added 1 changesets with 1 changes to 1 files (+1 heads)

18 (run ’hg heads’ to see heads, ’hg merge’ to merge)

19 $ hg merge

20 warning: detected divergent renames of foo to:

21 bar

22 quux

23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

24 (branch merge, don’t forget to commit)

25 $ ls

26 bar quux

Tenga en cuenta que Mercurial le advierte acerca de nombres divergentes, pero deja que usted decida qu e hacer

con la divergencia despues de la fusion.

5.4.3. Cambios de nombre convergentes y fusion

Otra clase de conflicto al cambiar el nombre de ficheros ocurre cuando dos personas eligen renombrar diferentes

ficheros fuente al mismo destino. En este caso Mercurial aplica su maquinaria de fusion usual, y le permite a usted

guiar la situacion a una resolucion adecuada.

5.4.4. 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, mientras que en otro hay un directorio con el mismo nombre. Esto esta documentado como Fallo de

Mercurial No. 29.

1 $ hg init issue29

2 $ cd issue29

3 $ e c h o a > a

4 $ hg ci -Ama

5 adding a

6 $ e c h o b > b

7 $ hg ci -Amb

8 adding b

9 $ h g u p 0

10 0 files updated, 0 files merged, 1 files removed, 0 files unresolved

11 $ mkdir b12 $ echo b > b/b

13 $ hg ci -Amc

14 adding b/b

15 created new head

16 $ hg merge

17 abort: Is a directory: /tmp/issue29HYiaCx/issue29/b

57

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 68/204

5.5. Recuperarse de equivocaciones

Mercurial tiene unas ordenes poderosas que le ayudaran a recuperarse de equivocaciones comunes.

La orden “hg revert” le permite deshacer cambios que haya hecho a su directorio de trabajo. Por ejemplo, si

aplico “hg add” a un fichero por accidente, ejecute “hg revert” con el nombre del fichero que anadio, y en tanto

que el fichero no haya sido tocado de forma alguna, no sera adicionado, ni seguido por Mercurial. Tambien puede usar

“hg revert” para deshacerse de cambios erroneos a un fichero.Tenga en cuenta que la orden “hg revert” se usa para cambios que no han sido consignados. Cuando haya

consignado un cambio, si decide que era un error, puede hacer algo todavıa, pero sus opciones pueden estar mas

limitadas.

Para obtener informacion acerca de la orden “hg revert” y detalles de como tratar con cambios consignados, vea

el capıtulo 9.

58

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 69/204

Capıtulo 6

Colaborar con otros

Debido a su naturaleza descentralizada, Mercurial no impone polıtica alguna de como deben trabajar los grupos

de personas. Sin embargo, si el control distribuido de versiones es nuevo para usted, es bueno tener herramientas y

ejemplos a la mano al pensar en posibles modelos de flujo de trabajo.

6.1. La interfaz web de Mercurial

Mercurial tiene una poderosa interfaz web que provee bastantes capacidades utiles.

Para uso interactivo, la interfaz le permite visualizar uno o varios repositorios. Puede ver el historial de un reposi-

torio, examinar cada cambio (comentarios y diferencias), y ver los contenidos de cada directorio y fichero.

Adicionalmente la interfaz provee notificaciones RSS de los cambios del repositorio. Esto le permite “subscribirse”a

un repositorio usando su herramienta de lectura de notificaciones favorita, y ser notificado automaticamente de la ac-

tividad en el repositorio tan pronto como sucede. Me gusta mucho mas este modelo que el estar suscrito a una lista de

correo a la cual se envıan las notificaciones, dado que no requiere configuracion adicional de parte de quien sea que

esta administrando el repositorio.

La interfaz web tambien permite a los usuarios remotos clonar repositorios, jalar cambios, y (cuando el servidor

esta configurado para permitirlo) empujar cambios al mismo. El protocolo de entunelamiento HTTP de Mercurial

comprime datos agresivamente, de forma que trabaja eficientemente incluso en conexiones de red con poco ancho debanda.

La forma mas sencilla de empezar a trabajar con la interfaz web es usar su navegador para visitar un repositorio

existente, como por ejemplo el repositorio principal de Mercurial en http://www.selenic.com/repo/hg?style=

gitweb.

Si esta interesado en proveer una interfaz web a sus propios repositorios, Mercurial ofrece dos formas de hacerlo.

La primera es usando la orden “hg serve”, que esta enfocada a servir “de forma liviana” y por intervalos cortos. Para

mas detalles de como usar esta orden vea la seccion 6.4 mas adelante. Si tiene un repositorio que desea hacer disponible

de forma permanente, Mercurial tiene soporte embebido para el estandar CGI (Common Gategay Interface), que es

manejado por todos los servidores web comunes. Vea la seccion 6.6 para los detalles de la configuracion a traves de

CGI.

6.2. Modelos de colaboracionCon una herramienta adecuadamente flexible, tomar decisiones acerca del flujo de trabajo es mucho mas un reto

de ingenierıa social que un problema tecnico. Mercurial impone pocas limitaciones sobre como puede estructurar el

flujo de trabajo en un proyecto, ası que depende de usted y de su grupo definir y trabajar con un modelo que se ajuste

a sus necesidades particulares.

59

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 70/204

6.2.1. Factores a tener en cuenta

El aspecto mas importante que usted debe considerar de cualquier modelo es que tan bien se ajusta a las necesidades

y capacidades de la gente que lo usara. Esto puede parecer auto-evidente; aun ası, usted no puede permitirse olvidarlo

ni por un momento.

Una vez definı un modelo de flujo de trabajo que parecıa ser perfectamente adecuado para mı, pero que causo una

cantidad considerable de consternacion y friccion dentro de mi equipo de desarrollo. A pesar de mis intentos de ex-

plicar porque necesitabamos un conjunto complejo de ramas, y de como debıan fluir los cambios entre ellas, algunos

miembros del equipo se molestaron. Aunque ellos eran personas inteligentes, no quer ıan prestar atencion a las lim-

itaciones bajo las cuales estabamos operando, o comparar las consecuencias de esas limitaciones con los detalles del

modelo que yo estaba proponiendo.

No esconda bajo la alfombra los problemas sociales o t ecnicos que usted pueda preveer. Sin importar el esquema

que usted use, debe hacer planes para enfrentar posibles errores o problemas. Considere anadir procedimientos autom-

atizados para prevenir, o recuperarse rapidamente de, los problemas que usted pueda anticipar. A manera de ejemplo,

si usted planea tener una rama en la vayan los cambios que no est en listos para produccion, harıa bien en pensar en la

posibilidad de que alguien fusione accidentalmente dichos cambios en una rama para publicacion. Usted podrıa evitar

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 facil de entender, y que

funciona perfectamente bien en unas cuantas situaciones inusuales.

Como un ejemplo, muchos proyectos tienen un grupo informal de colaboradores que rara vez se reunen f ısica-

mente. A algunos grupos les gusta evitar el aislamiento de trabajar a distancia organizando “sprints” ocasionales. En

un sprint, una cantidad de gente se reune en un mismo sitio (el cuarto de conferencias de una empresa, el cuarto de

reuniones de un hotel, ese tipo de lugares) y pasar varios dıas mas o menos encerrados allı, trabajando intensamente

en un punado de proyectos.

Un sprint es el lugar perfecto para usar el comando “hg serve”, ya que “hg serve” no requiere una infraestruc-

tura especial de servidores. Usted puede empezar a trabajar con “hg serve” en momentos, leyendo la seccion 6.4 mas

abajo. Luego simplemente dıgale a las personas cerca suyo que usted est a ejecutando un servidor, envıeles la URL a

traves de un mensaje instantaneo, y tendra de inmediato una forma rapida de trabajar juntos. Ellos pueden escribir su

URL en un navegador web y revisar sus cambios r apidamente; o ellos pueden jalar un arreglo de fallo que usted haya

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 solo las personas que saben de sus

cambios, y donde estan, pueden verlos. Un enfoque tan informal sencillamente no puede escalarse mas alla de un

punado de personas, porque cada individuo tiene que saber de n repositorios diferentes de los cuales jalar.

6.2.3. Un repositorio central unico

Para proyectos pequenos migrando desde una herramienta centralizada de control de revisiones, tal vez la forma

mas f acil de empezar es hacer que los cambios vayan a traves de un repositorio central compartido. Este es tambien el

“bloque base” para esquemas mas ambiciosos de flujo de trabajo.

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

esten listos para que los demas los vean.

Bajo este modelo, para los usuarios tiene sentido jalar cambios directamente entre ellos, sin ir a trav es del reposi-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 demas cuando lo jalen. Para reducir el potencial de dano, puedo

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 seccion 6.5. Tambien es usual publicar una copia de solo lectura del

60

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 71/204

repositorio sobre HTTP usando CGI, como en la seccion 6.6. Publicar a traves de HTTP satisface las necesidades de

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 simultanea en varios frentes. En elcaso del software, es comun que un proyecto tenga versiones periodicas oficiales. Una version puede entrar a “modo

mantenimiento” por un tiempo despues de su primera publicacion; las versiones de mantenimiento tienden a contener

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 esta especialmente preparado para administrar un buen numero de ramas simultaneas pero no identicas.

Cada “direccion de desarrollo” puede vivir en su propio repositorio central, y usted puede mezclar los cambios de una

a otra cuando sea necesario. Dado que los repositorios son independientes entre sı, los cambios inestables de una rama

de desarrollo nunca afectaran una rama estable a menos que alguien mezcle explıcitamente los cambios.

A continuacion hay un ejemplo de como podrıa hacerse esto en la practica. Digamos que tiene una “rama principal”

en un servidor central.

1 $ hg init main

2 $ cd main

3 $ echo ’This is a boring feature.’ > myfile

4 $ hg commit -A -m ’We have reached an important milestone!’

5 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 revision del hito.

1 $ hg tag v1.0

2 $ hg tip

3 changeset: 1:471e84684405

4 tag: tip

5 user: Bryan O’Sullivan <[email protected]>

6 date: Tue Feb 10 18:23:16 2009 +0000

7 summary: Added tag v1.0 for changeset a1e37e7a184f

8

9 $ hg tags

10 tip 1:471e84684405

11 v1.0 0:a1e37e7a184f

Digamos que en la rama principal ocurre mas desarrollo.

1 $ cd ../main

2 $ echo ’This is exciting and new!’ >> myfile

3

$ hg commit -m ’Add a new feature’4 $ cat myfile

5 This is a boring feature.

6 This is exciting and new!

Cuando se usa la etiqueta con que se identifico la version, la gente que clone el repositorio en el futuro puede usar

“hg update” para obtener una copia del directorio de trabajo igual a cuando se creo la etiqueta de la revision que se

consigno.

61

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 72/204

1 $ cd ..

2 $ hg clone -U main main-old

3 $ cd main-old

4 $ hg update v1.0

5 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

6 $ cat myfile7 This is a boring feature.

Adicionalmente, justo despues de que la rama principal se etiquete, alguien puede clonarla en el servidor a una

nueva rama “estable”, tambien en el servidor.

1 $ cd ..

2 $ hg clone -rv1.0 main stable

3 requesting all changes

4 adding changesets

5 adding manifests

6 adding file changes

7 added 1 changesets with 1 changes to 1 files

8 updating working directory9 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, consignar-

los, y empujarlos de vuelta.

1 $ hg clone stable stable-fix

2 updating working directory

3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

4 $ cd stable-fix

5 $ echo ’This is a fix to a boring feature.’ > myfile

6 $ hg commit -m ’Fix a bug’

7 $ hg push

8 pushing to /tmp/branchingOpMbpu/stable

9 searching for changes

10 adding changesets

11 adding manifests

12 adding file changes

13 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 automaticamente, las ramas estable y principal estan aisladas la una de la otra. Los cambios que haga en la rama

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 tambien. En lugar de

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 traera tales arreglos por usted.

1 $ cd ../main

2 $ hg pull ../stable

3 pulling from ../stable

4 searching for changes

5 adding changesets

6 adding manifests

62

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 73/204

7 adding file changes

8 added 1 changesets with 1 changes to 1 files (+1 heads)

9 (run ’hg heads’ to see heads, ’hg merge’ to merge)

10 $ hg merge

11 merging myfile

12 0 files updated, 1 files merged, 0 files removed, 0 files unresolved

13 (branch merge, don’t forget to commit)14 $ hg commit -m ’Bring in bugfix from stable branch’

15 $ cat myfile

16 This is a fix to a boring feature.

17 This is exciting and new!

La rama principal aun contendra los cambios que no estan en la estable y contendra ademas todos los arreglos de fallos

de la rama estable. La rama estable permanece incolume a tales cambios.

6.2.5. Ramas de caracterısticas

En proyectos grandes, una forma efectiva de administrar los cambios es dividir el equipo en grupos m as pequenos.

Cada grupo tiene una rama compartida, clonada de una rama “principal” que conforma el proyecto completo. Aquellos

que trabajan en ramas individuales usualmente estan aislados de los desarrollos de otras ramas.

maestro

cripto sistemadearchivos ipc memoria red seguridad

Figura 6.1: Ramas de Caracterısticas

Cuando se considera que una caracterıstica particular esta en buena forma, alguien de ese equipo de caracterısticas 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 publicacion

Algunos proyectos se organizan al estilo“tren”: una version se planifica para ser liberada cada cierto tiempo, y las

caracterısticas que esten listas cuando ha llegado el “tren”, se incorporan.

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 on liberada

hacia la rama de caracterıstica, y el trabajo continua sobre lo fusionado para que la caracterıstica logre estar en la

proxima version.

6.2.7. El modelo del kernel Linux

El desarrollo del kernel Linux tiene una estructura jerarquica bastante horizontal, rodeada de una nube de caos

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 aproximacion se traduce bien de Git a Mercurial.

En el centro de la comunidad esta Linus Torvalds, el creador de Linux. El publica un unico repositorio que es

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

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 74/204

Linus tiene varios “lugartenientes de confianza”. Como regla, el jala todos los cambios que ellos publican, en la

mayorıa de los casos sin siquiera revisarlos. Algunos de sus lugartenientes generalmente aceptan ser los “mantene-

dores”, responsables de subsistemas especıficos dentro del kernel. Si un hacker cualquiera desea hacer un cambio a un

subsistema y busca que termine en el arbol de Linus, debe encontrar quien es el mantenedor del subsistema y solici-

tarle que tome su cambio. Si el mantenedor revisa los cambios y esta de acuerdo en tomarlos, estos pasaran al arbol de

Linus a su debido tiempo.

Cada lugarteniente tiene su forma particular de revisar, aceptar y publicar los cambios; y para decidir cuandopresentarlos a Linus. Adicionalmente existen varias ramas conocidas que mucha gente usa para prop ositos distintos.

Por ejemplo, algunas personas mantienen repositorios “estables” de versiones anteriores del kernel, a los cuales aplican

arreglos de fallos crıticos cuando es necesario. Algunos mantenedores publican varios arboles: uno para cambios

experimentales; uno para cambios que van a ofrecer al mantenedor principal; y ası sucesivamente. Otros publican solo

un arbol.

Este modelo tiene dos caracterısticas notables. La primera es que es de “jalar exclusivamente”. Usted debe solicitar,

convencer o incluso rogar a otro desarrollador para que tome sus cambios, porque casi no hay arboles en los cuales

mas de una persona pueda publicar, y no hay forma de publicar cambios en un arbol que alguien mas controla.

La segunda es que esta basado en reputacion y meritocracia. Si usted es un desconocido, Linus probablemente

ignorara sus cambios, sin siquiera responderle. Pero el mantenedor de un subsistema probablemente los revisara, y

los acogera en caso de que aprueben su criterio de aplicabilidad. A medida que usted ofrezca “mejores” cambios a

un mantenedor, habra mas posibilidad de que se conf ıe en su juicio y se acepten los cambios. Si usted es reconocido

y mantiene una rama durante bastante tiempo para algo que Linus no ha aceptado, personas con intereses similarespueden jalar sus cambios regularmente para estar al d ıa con su trabajo.

La reputacion y meritocracia no necesariamente son transversales entre “personas” de diferentes subsistemas. Si

usted es un hacker respetado pero especializado en almacenamiento, y trata de arreglar un fallo de redes, tal cambio

puede recibir un nivel de escrutinio de un mantenedor de redes comparable con el que se le har ıa a un completo

extrano.

Personas que vienen de proyectos con un ordenamiento distinto, sienten que el proceso comparativamente caotico

del Kernel Linux es completamente lunatico. Es objeto de los caprichos individuales; la gente desecha cambios cuando

lo desea; y el ritmo de desarrollo es alucinante. A pesar de eso Linux es una pieza de software exitosa y bien reconocida.

6.2.8. Solamente jalar frente a colaboracion publica

Una fuente perpetua de discusiones en la comunidad de codigo abierto yace en la afirmacion de que el modelo de

desarrollo en el cual la gente solamente jala cambios de otros “es mejor que” uno en el cual muchas personas puedenpublicar cambios a un repositorio compartido.

Tıpicamente los partidarios del modelo de publicar usan las herramientas que se apegan a este modelo. Si usted

usa una herramienta centralizada de control de versiones como Subversion, no hay forma de elegir que modelo va a

usar: la herramienta le ofrece publicacion compartida, y si desea hacer cualquier otra cosa, va a tener que tomar una

aproximacion artificial (tal como aplicar parches a mano).

Una buena herramienta de control de versiones distribuida, tal como Mercurial, soportara los dos modelos. Usted

y sus colaboradores pueden estructurar como trabajaran juntos basados en sus propias necesidades y preferencias, sin

tener que llevar a cabo las peripecias que la herramienta les obligue a hacer.

6.2.9. Cuando la colaboracion encuentra la administracion ramificada

Una vez que usted y su equipo configuren algunos repositorios compartidos y comiencen a propagar cambios

entre sus repositorios locales y compartidos, usted comenzara a encarar un reto relacionado, pero un poco distinto:

administrar las direcciones en las cuales su equipo puede moverse. A pesar de que est a ıntimamente ligado acerca

de como interactua su equipo, este es un tema lo suficientemente denso para ameritar un tratamiento aparte, en el

capıtulo 8.

64

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 75/204

6.3. Aspectos tecnicos de la colaboracion

Lo que resta del capıtulo lo dedicamos a las cuestiones de servir datos a sus colaboradores.

6.4. Compartir informalmente con “hg serve”

La orden “hg serve” de Mercurial satisface de forma espectacular las necesidades de un grupo pequeno, acoplado

y agil. Tambien sirve como una demostracion de como se siente usar los comandos usando la red.

Ejecute “hg serve” dentro de un repositorio, y en pocos segundos se iniciara un servidor HTTP especializado;

aceptara conexiones desde cualquier cliente y servira datos de este repositorio mientras lo mantenga funcionando.

Todo el que conozca la URL del servidor que usted ha iniciado, y que pueda comunicarse con su computador a traves

de la red, puede usar un navegador web o Mercurial para leer datos del repositorio. Un URL para una instancia de “ hg

serve” ejecutandose en un portatil deberıa lucir similar a http://my-laptop.local:8000/ .

La orden “hg serve” no es un servidor web de proposito general. Solamente puede hacer dos cosas:

Permitir la visualizacion del historial del repositorio que esta sirviendo, desde un navegador web.

Hablar el protocolo de conexion de Mercurial, para que la gente pueda hacer “hg clone” o “hg pull” (jalar)

cambios desde tal repositorio.

En particular, “hg serve” no permitira que los usuarios remotos modifiquen su repositorio. Es de tipo solo lectura.

Si esta familiarizandose con Mercurial, no hay nada que le impida usar “hg serve” para servir un repositorio en

su propio computador, y posteriormente usar ordenes como “hg clone”, “hg incoming”, para comunicarse con el

servidor como si el repositorio estuviera alojado remotamente. Esto puede ayudarle a adecuarse rapidamente a usar

comandos en repositorios alojados en la red.

6.4.1. Cuestiones adicionales para tener en cuenta

Dado que permite lectura sin autenticacion a todos sus clientes, deberıa usar “hg serve” exclusivamente en am-

bientes en los cuales esto no sea importante, o en los cuales tenga control completo acerca de qui en puede acceder a

su red y jalar cambios de su repositorio.

La orden “hg serve” no tiene conocimiento acerca de programas cortafuegos que puedan estar instalados en su

sistema o en su red. No puede detectar o controlar sus cortafuegos. Si otras personas no pueden acceder a su instanciade “hg serve”, lo siguiente que deberıa hacer (despu´ es de asegurarse que tienen el URL correcto) es verificar su

configuracion de cortafuegos.

De forma predeterminada, “hg serve” escucha conexiones entrantes en el puerto 8000. Si otro proceso esta es-

cuchando en tal puerto, usted puede especificar un puerto distinto para escuchar con la opcion -p.

Normalmente, cuando se inicia “hg serve”, no muestra ningun mensaje, lo cual puede ser algo desconcertante.

Si desea confirmar que en efecto esta ejecutandose correctamente, y averiguar que URL deberıa enviar a sus colabo-

radores, inıcielo con la opcion -v.

6.5. Uso del protocolo Secure Shell (ssh)

Usted puede publicar y jalar cambios en la red de forma segura usando el protocolo Secure Shell (ssh). Para usarlo

exitosamente, tendra que hacer algo de configuracion a nivel de cliente o de servidor.Si no esta familiarizado con ssh, es un protocolo de red que le permite comunicarse de manera segura con otro

computador. Para usarlo con Mercurial, debera crear una o mas cuentas de usuario en un servidor de forma tal que los

usuarios remotos puedan entrar y ejecutar ordenes.

(Si ssh le es familiar, probablemente encontrara elemental una porcion del material a continuacion.)

65

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 76/204

6.5.1. Como leer y escribir URLs de ssh

Los URLs de ssh tienden a lucir de la siguiente forma:

1 ssh://[email protected]:22/hg/hgbook

1. La parte “ssh://” le indica a Mercurial que use el protocolo ssh.

2. El componente “bos@” indica el nombre del usuario que esta entrando al servidor. Puede omitirlo si el usuario

remoto coincide con el usuario local.

3. “hg.serpentine.com ” es el nombre del servidor al cual se desea entrar.

4. El “:22” identifica el numero del puerto en el servidor al cual se conectar a. El predeterminado es el 22, ası que

solamente necesitara especificar esa porcion si no esta usando el puerto 22.

5. La ultima porcion del URL es la ruta local del repositorio en el servidor.

El componente de la ruta del URL para ssh es una fuente de confusion, puesto que no hay una forma estandar

para que las herramientas puedan interpretarlo. Algunos programas se comportan de manera distinta a otros cuando

manipulan estas rutas. No es la situacion ideal, pero es muy poco probable que vaya a cambiar. Por favor lea los

parrafos siguientes cuidadosamente.

Mercurial trata la ruta al repositorio en el servidor como relativa al directorio personal del usuario remoto. Porejemplo, si el usuario foo en el servidor tiene el directorio personal /home/foo, entonces un URL ssh que tenga como

ruta a bar realmente se refiere al directorio /home/foo/bar.

Si desea especificar una ruta relativa a otro directorio de usuario, puede usar una ruta que comience con una

virgulilla, seguida del nombre del usuario (llamemosle otrousuario), ası

1 ssh://server/˜otheruser/hg/repo

Y si realmente desea especifica una ruta absoluta en el servidor, comience con el componente de la ruta con dos

barras, como en el siguiente ejemplo:

1 ssh://server//absolute/path

6.5.2. Encontrar un cliente ssh para su sistemaCasi todos los sistemas tipo Unix vienen con OpenSSH preinstalado. Si usted esta usando un sistema de estos, eje-

cute which ssh para identificar donde esta instalada la orden ssh (usualmente estara en /usr/bin). Si por casualidad

no esta presente, vea la documentacion de sus sistema para averiguar como instalarlo.

En Windows, primero tendra que descargar un cliente adecuado. Hay dos alternativas:

El excelente paquete PuTTY [Tat] de Simon Tatham, que ofrece un conjunto completo de ordenes de cliente

ssh.

Si tiene alta tolerancia al dolor, puede usar el porte de Cygwin para OpenSSH.

En cualquier caso, tendra que editar su fichero Mercurial.ini para indicarle a Mercurial donde encontrar la orden

real del cliente. Por ejemplo, si esta usando PuTTY, tendra que usar la orden plink como un cliente de lınea de

comandos para ssh.

1 [ui]

2 ssh = C:/ruta/a/plink.exe -ssh -i "C:/ruta/a/mi/llave/privada"

Nota: La ruta a plink no deberıa contener espacios o caracteres en blanco, o

Mercurial no podra encontrarlo correctamente (por lo tanto, probablemente no serıa

buena idea colocarlo en C:\Program Filesa

aN. del T. Ubicarlo en C:\Archivos de Programa tampoco lo serıa.

66

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 77/204

6.5.3. Generar un par de llaves

Para evitar la necesidad de teclear una clave de forma repetitiva cada vez que necesita usar el cliente, recomiendo

generar un par de llaves. En un sistema tipo Unix, la orden ssh-keygen se encargara de la tarea. En Windows, si

esta usando PuTTY, necesitara la orden puttygen.

Cuando genera un par de llaves, se aconseja comedidamente protegerlas con una frase clave. (La unica oportunidad

en la cual usted no querrıa hacerlo, es cuando esta usando el protocolo ssh para tareas automatizadas en una red segura.)

No basta con generar un par de llaves. Se requiere adicionar la llave p ublica al conjunto de llaves autorizadas

del usuario que usted usa para acceder a la maquina remota. Para aquellos servidores que usen OpenSSH (la gran

mayorıa), significara anadir la llave publica a la lista en el fichero llamado authorized keys en su directorio .ssh.

En sistemas tipo Unix, su llave publica tendra la extension .pub. Si usa puttygen en Windows, puede guardar la

llave publica en un fichero de su eleccion, o pegarla desde la ventana en la cual se despliega directamente en el fichero

authorized keys.

6.5.4. Uso de un agente de autenticacion

Un agente de autenticacion es un demonio que almacena frases clave en memoria (olvidara las frases clave si sale

de su sesion y vuelve a entrar). Un cliente ssh notara si el agente esta corriendo, y le solicitara una frase clave. Si

no hay un agente de autenticacion corriendo, o el agente no almacena la frase clave necesaria, tendr a que teclear su

frase clave cada vez que Mercurial intente comunicarse con un servidor para usted (p.e. cada vez que jale o publique

cambios).

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, en algunos casos incluso si su sistema ya ha sido reiniciado. Es su decisi on si es un

riesgo aceptable. Lo que sı es seguro es que evita reteclear.

En sistemas tipo Unix, el agente se llama ssh-agent, y usualmente se ejecuta automaticamente cuando usted inicia

sesion. Tendra que usar la orden ssh-add para anadir frases claves al agente. En Windows, si esta usando PuTTY, la

orden pageant actua como el agente. El anade un icono a su barra del sistema que le permitira administrar las frases

clave almacenadas.

6.5.5. Configurar el lado del servidor apropiadamente

Dado que puede ser dispendioso configurar ssh si es algo nuevo para usted, hay una variedad de cosas que podrıan ir

mal. Anada a eso Mercurial y hay mucho mas en que pensar. La mayor parte de estos problemas potenciales ocurren enel lado del servidor, no en el cliente. Las buenas noticias es que una vez tiene una configuraci on funcional, usualmente

esta continuara trabajando indefinidamente.

Antes de intentar que Mercurial hable con un servidor ssh, es mejor asegurarse de que puede usar la orden normal

ssh o putty para comunicarse primero con el servidor. Si tiene problemas usando estas ordenes directamente, de

seguro Mercurial no funcionara. Pero aun, esto escondera el problema subyacente. Cuando desee revisar un problema

relacionado con ssh y Mercurial, 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.

Lo primero para asegurar en el lado del servidor es que usted pueda iniciar sesion desde otra maquina. Si no puede

entrar usando ssh o putty, el mensaje de error que obtenga le puede dar pistas de que ha ido mal. Los problemas mas

comunes son los siguientes:

Si obtiene un error de “conexion rehusada”, es posible que no haya un demonio SSH corriendo en el servidor o

que no pueda accederse a el debido a la configuracion de cortafuegos.Si obtiene un error de “no hay ruta hasta el servidor”, puede tener una direccion incorrecta para el servidor o un

cortafuegos con bloqueo agresivo que negara la existencia del servidor.

Si obtiene un mensaje de “permiso denegado”, puede que haya tecleado mal el usuario en el servidor, o que

haya tecleado incorrectamente la frase clave de su llave o la clave del usuario remoto.

67

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 78/204

En resumen, si tiene problemas al comunicarse con el demonio ssh del servidor, primero aseg urese de que se este eje-

cutando. En muchos sistemas estara instalado, pero deshabilitado de forma predeterminada. Una vez que haya hecho

esto tendra que revisar si el cortafuegos del servidor esta configurado para recibir conexiones entrantes en el puerto

en el cual esta escuchando el demonio de ssh (usualmente el 22). No trate de buscar otras posibilidades ex oticas o

configuraciones erradas hasta que haya revisado primero estas dos.

Si esta usando un agente de autenticacion en el lado del cliente para almacenar las frase claves de sus contrasenas,

deberıa poder entrar al servidor sin necesidad de que se le soliciten frases claves o contrase nas. Si se le preguntaalguna, a continuacion algunas posibilidades:

Puede haber olvidado usar ssh-add o pageant para guardar la frase clave.

Puede haber almacenado una frase clave para una llave distinta.

Si se le solicita la clave del usuario remoto, hay otras posibilidades que deben revisarse:

O bien el directorio del usuario o su directorio .ssh tiene permisos excesivamente abiertos. Como resultado el

demonio ssh no confiara ni leera su fichero authorized keys. Por ejemplo, un directorio personal o .ssh con

permisos de escritura para grupo mostrara a veces este sıntoma.

El fichero authorized keys del usuario puede tener un problema. Si alguien distinto al usuario es dueno del

mismo o puede escribir en el fichero, el demonio ssh no confiara en el y no lo leera.

En un mundo ideal, deberıa poder ejecutar la siguiente orden exitosamente, y deberıa imprimir exactamente unalınea de salida, la fecha y hora actual.

1 ssh miservidor date

Si en su servidor tiene guion que se ejecuta a la entrada e imprime letreros o cualquier otra cosa, incluso cuando se

ejecutan ordenes no interactivas como esta, deberıa arreglarlo antes de continuar, de forma que solamente imprima algo

si se ejecuta interactivamente. De otra forma estos letreros al menos llenaran la salida de Mercurial. Incluso podrıan

causar problemas potenciales cuando se ejecuten ordenes de forma remota. Mercurial intenta detectar e ignorar los

letreros en sesiones no interactivas de ssh, pero no es a prueba de tontos. (Si edita sus guiones de entrada en el

servidor, la forma usual de ver si un guion de lınea de comandos se ejecuta en un interprete interactivo es verificar el

codigo de retorno de la orden tty -s.)

Cuando verifique que el venerado ssh funciona en su servidor, el siguiente paso es asegurarse de que Mercurial

corre en el servidor. 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”, sera porque Mercurial no fue instalado en

/usr/bin. Si este es el caso, no se preocupe; no necesita hacerlo. Pero deberıa revisar los posibles problemas:

¿Esta instalado Mercurial en el servidor? ¡Se que suena trivial pero es mejor revisar!

Tal vez la ruta de busqueda de la interfaz de ordenes (normalmente vıa la variable de entorno PATH) simplemente

esta mal configurada.

Puede ser que su variable de ambiente PATH solamente apunte al lugar en el cual esta el ejecutable hg si la sesion

de entrada es interactiva. Esto puede suceder si establece la ruta en el guion de lınea de comandos de entrada

incorrecto. Consulte la documentacion de su interprete de ordenes.

La variable de ambiente PYTHONPATH puede requerir contener la ruta a los modulos de Mercurial en Python.

Puede que ni siquiera esta establecida; podrıa estar incorrecta; o puede ser que se establezca unicamente cuando

hay entradas interactivas.

Si puede ejecutar “hg version” sobre una conexion ssh, ¡felicitaciones! Ha logrado la interaccion entre el cliente

y el servidor. Ahora deberıa poder acceder a los repositorios de Mercurial que tiene el usuario en el servidor. Si tiene

problemas con Mercurial y ssh en este punto, intente usar la opcion --debug para tener informacion mas clara de lo

que esta sucediendo.

68

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 79/204

6.5.6. Compresion con ssh

Mercurial no comprime datos cuando usa el protocolo ssh, dado que el protocolo puede comprimir datos transpar-

entemente. Pero el comportamiento predeterminado del cliente ssh es no utilizar compresion.

Sobre cualquier red distinta a una LAN rapida (incluso con una red inalambrica), hacer uso de compresion puede

mejorar el rendimiento de las operaciones de Mercurial que involucren la red. Por ejemplo, sobre WAN, alguien ha

medido que la compresion reduce la cantidad de tiempo requerido para clonar un repositorio particularmente grande

de 51 minutos a 17 minutos.

Tanto ssh como plink aceptan la opcion -C para activar la compresion. Puede editar f acilmente su hgrc para

habilitar la compresion para todos los usos de Mercurial con el protocolo ssh.

1 [ui]

2 ssh = ssh -C

Si usa ssh, puede reconfigurarlo para que siempre use compresion cuando se comunique con su servidor. Para

hacerlo, edite su fichero .ssh/config (que puede no existir aun), de la siguiente forma:

1 Host hg

2 Compression yes

3 HostName hg.ejemplo.com

Que define un alias, hg. Cuando lo usa con la orden ssh o con una URL de Mercurial con protocolo ssh, hara que

ssh se conecte a hg.ejemplo.com usando compresion. Esto le brindara un nombre mas corto para teclear, junto con

compresion, los cuales por derecho propio son buenos.

6.6. Servir sobre HTTP usando CGI

Dependiendo de que tan ambicioso sea, configurar la interfaz CGI de Mercurial puede tomar desde unos minutos

hasta varias horas.

Comenzaremos con el ejemplo mas sencillo, y nos dirigiremos hacia configuraciones mas complejas. Incluso para

el caso mas basico necesitara leer y modificar la configuracion de su servidor web.

Nota: Configurar un servidor web es una actividad compleja, engorrosa y alta-mente dependiente del sistema. De ninguna manera podremos cubrir todos los ca-

sos posibles con los cuales pueda encontrarse. Use su discrecion y juicio respecto

a las siguientes secciones. Preparese para cometer muchas equivocaciones, y em-

plear bastante tiempo leyendo las bitacoras de error de su servidor.

6.6.1. Lista de chequeo de la configuracion del servidor web

Antes de continuar, tomese un tiempo para revisar ciertos aspectos de la configuracion de su sistema:

1. ¿Tiene un servidor web? Mac OS X viene con Apache, pero otros sistemas pueden no tener un servidor web

instalado.

2. Si tiene un servidor web instalado, ¿Esta ejecutandose? En la mayorıa de sistemas, aunque este presente, puede

no estar habilitado de forma predeterminada.

3. ¿Esta configurado su servidor para permitir ejecutar programas CGI en el directorio donde planea hacerlo? Casi

todos los servidores de forma predeterminada deshabilitan explıcitamente la habilidad de ejecutar programas

CGI.

69

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 80/204

Si no tiene un servidor web instalado, y no tiene experiencia configurando Apache, deber ıa considerar usar el

servidor web lighttpd en lugar de Apache. Apache tiene una reputacion bien ganada por su configuracion barroca

y confusa. A pesar de que lighttpd tiene menos caracterısticas que Apache en ciertas areas, muchas de ellas no son

relevantes para servir repositorios de Mercurial. Y definitivamente es mucho mas sencillo comenzar con lighttpd

que con Apache.

6.6.2. Configuracion basica de CGI

En sistemas tipo Unix es comun que los usuarios tengan un subdirectorio con un nombre como public html en

su directorio personal, desde el cual pueden servir paginas web. Un fichero llamado foo en este directorio sera visible

en una URL de la forma http://www.example.com/˜username/foo .

Para comenzar, encuentre el guion hgweb.cgi que deberıa estar presente en su instalacion de Mercurial. Si no

puede encontrar rapidamente una copia local en su sistema, puede descargarlo del repositorio principal de Mercurial

en http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi.

Tendra que copiar este guion en su directorio public html, y asegurarse que sea ejecutable.

1 cp .../hgweb.cgi ˜/public_html

2 chmod 755 ˜/public_html/hgweb.cgi

El argumento 755 de la orden chmod esun pocomas general que hacerlo ejecutable: asegura que el guion sea ejecutablepor cualquiera, y que el “grupo” y los “otros” no tengan permiso de escritura. Si dejara los permisos de escritura

abiertos, el subsistema suexec de Apache probablemente se negarıa a ejecutar el guion. De hecho, suexec tambien

insiste en que el directorio en el cual reside el guion no tenga permiso de escritura para otros.

1 chmod 755 ˜/public_html

¿Que podrıa resultar mal?

Cuando haya ubicado el CGI en el sitio correspondiente, abra un navegador e intente visitar el URL http://

myhostname/˜myuser/hgweb.cgi , sin dejarse abatir por un error. Hay una alta probabilidad de que esta primera

visita al URL sea fallida, y hay muchas razones posibles para este comportamiento. De hecho, podr ıa toparse con cada

uno de los errores que describimos a continuacion, ası que no deje de leerlos cuidadosamente. A continuacion presento

los problemas que yo tuve en un sistema con Fedora 7, con una instalaci on nueva de Apache, y una cuenta de usuario

que cree especıficamente para desarrollar este ejercicio.

Su servidor web puede tener directorios por usuario deshabilitados. Si usa Apache, busque el fichero de con-

figuracion que contenga la directiva UserDir. Si no esta presente en sitio alguno, los directorios por usuario estan

deshabilitados. Si la hay, pero su valor es disabled, los directorios por usuario estaran deshabilitados. En caso con-

trario, la directiva UserDir tendra el nombre del subdirectorio bajo el cual Apache mirara en el directorio de cada

usuario, por ejemplo public html.

Los permisos de sus ficheros pueden ser demasiado restrictivos. El servidor web debe poder recorrer su directorio

personal y los directorios que esten bajo public html, ademas de tener permiso para leer aquellos que esten adentro.

A continuacion una receta rapida para hacer que sus permisos esten acordes con las necesidades basicas.

1 chmod 755 ˜

2 find ˜/public_html -type d -print0 | xargs -0r chmod 755

3 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 guion. En este caso, es posible que los permisos que tiene son demasiado permisivos. El subsistema suexec de

Apache no ejecutara un guion que tenga permisos de escritura para el grupo o el planeta, por ejemplo.

Su servidor web puede estar configurado para evitar la ejecucion de programas CGI en los directorios de usuario.

A continuacion presento una configuracion predeterminada por usuario en mi sistema Fedora.

70

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 81/204

1 <Directory /home/*/public_html>

2 AllowOverride FileInfo AuthConfig Limit

3 Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec

4 <Limit GET POST OPTIONS>

5 Order allow,deny

6 Allow from all7 </Limit>

8 <LimitExcept GET POST OPTIONS>

9 Order deny,allow

10 Deny from all

11 </LimitExcept>

12 </Directory>

Si encuentra un grupo de instrucciones de Directory similares en su configuracion de Apache, la directiva a revisar

es Options. Adicione ExecCGI al final de esta lista en caso de que haga falta y reinicie su servidor web.

Si resulta que Apache le muestra el texto del guion CGI en lugar de ejecutarlo, necesitara o bien descomentar (si

se encuentra presente) o adicionar una directiva como la siguiente:

1 AddHandler cgi-script .cgi

Otra posibilidad es que observe una traza de Python en colores informando que no puede importar un m odulo

relacionado con mercurial. ¡Esto es un gran progreso! El servidor es capaz de ejecutar su gui on CGI. Este error

solamente ocurrira si esta ejecutando una instalacion privada de Mercurial en lugar de una instalacion para todo el

sistema. Recuerde que el servidor que ejecuta el programa CGI no cuenta con variables de entorno de las cuales usted

sı dispone en una sesion interactiva. Si este error le ocurre, edite su copia de hgweb.cgi y siga las indicaciones dentro

del mismo para establecer de forma adecuada su variable de entorno PYTHONPATH.

Finalmente, puede que se encuentre con otra traza a todo color de Python al visitar el URL: esta seguramente

se referira a que no puede encontrar /path/to/repository 1. Edite su guion hgweb.cgi y reemplace la cadena

/path/to/repository con la ruta completa al repositorio que desea servir.

En este punto, cuando trate de recargar la pagina, debera tener una linda vista HTML del historial de su repositorio.

¡Uff!

Configuracion de lighttpd

En mi intencion de ser exhaustivo, intente configurar lighttpd, un servidor web con creciente aceptacion, para

servir los repositorios de la misma forma en que lo describı anteriormente con Apache. Ya supere los problemas que

mostre con Apache, muchos de los cuales no son especıficos del servidor. Por lo tanto estaba seguro de que mis

permisos para directorios y ficheros eran correctos y que mi guion hgweb.cgi tambien lo era.

Dado que ya Apache estaba en ejecucion correctamente, lograr que lighttpd sirviera mi repositorio fue rapido (en

otras palabras, si esta tratando de usar lighttpd, debera leer la seccion de Apache). Primero tuve que editar la seccion

mod access para habilitar mod cgi y mod userdir, los cuales estaban inhabilitados en mi instalacion predeterminada.

Anadı posteriormente unas lıneas al final del fichero de configuracion, para hacer lo propio con los modulos.

1 userdir.path = "public_html"

2 cgi.assign = ( ".cgi" => "" )

Hecho esto, lighttpd funciono inmediatamente para mı. Si hubiera configurado lighttpd antes que Apache, habrıa

tenido casi los mismos problemas a nivel de configuracion del sistema que con Apache. De todas maneras, considero

que lighttpd es bastante mas sencillo de configurar que Apache, a pesar de haber usado Apache por lo menos por

una decada, y de que esta fue mi primera experiencia con lighttpd.

1N. del T. Ruta al repositorio.

71

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 82/204

6.6.3. Compartir varios repositorios con un guion CGI

El guion hgweb.cgi permite publicar unicamente un repositorio, una restriccion frustrante. Si desea publicar mas

de uno sin complicarse con varias copias del mismo guion, cada una con un nombre distinto, resulta mucho mejor usar

el guion hgwebdir.cgi.

El procedimiento para configurar hgwebdir.cgi tiene una porcion adicional respecto al trabajo requerido con

hgweb.cgi. Primero se debe obtener una copia del guion. Si no tiene una a mano, puede descargarla del ftp principal

del repositorio de Mercurial en http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi.

Necesitara una copia del guion en su directorio public html, y debe asegurarse de que tenga permisos de ejecu-

cion.

1 cp .../hgwebdir.cgi ˜/public_html

2 chmod 755 ˜/public_html ˜/public_html/hgwebdir.cgi

Con la configuracion basica, intente visitar en su navegador http://myhostname/ ˜myuser/hgwebdir.cgi . Deberıa

mostrar una lista vacıa de repositorios. Si obtiene una ventana en blanco o un mensaje de error, verifique la lista de

problemas potenciales en la seccion 6.6.2.

El guion hgwebdir.cgi se apoya en un fichero externo de configuracion. De forma predeterminada, busca un

fichero llamado hgweb.config en el mismo directorio. Tendra que crear el fichero, y permitir lectura de todo el

mundo. El formato del fichero es similar a un fichero “ini” de Windows, que puede ser interpretado por el m odulo

ConfigParser [Pyt] de Python.

La forma mas sencilla de configurar hgwebdir.cgi es mediante una seccion llamada collections. Esta pub-

licara automaticamente todos los repositorios en los directorios que usted especifique. La secci on deberıa lucir ası:

1 [collections]

2 /mi/ruta = /mi/ruta

Mercurial lo interpreta buscando el nombre del directorio que este a la derecha del sımbolo “=”; ubicando repositorios

en la jerarquıa de directorios; y usando el texto a la izquierda para eliminar el texto de los nombres que mostrara en la

interfaz web. El componente restante de la ruta despues de esta eliminacion usualmente se llama “ruta virtual”.

Dado el ejemplo de arriba, si tenemos un repositorio cuya ruta local es /mi/ruta/este/repo , el guion CGI

eliminara la porcion inicial /mi/ruta del nombre y publicara el repositorio con una ruta virtual este/repo. Si el

URL base de nuestro guion CGI es http://myhostname/ ˜myuser/hgwebdir.cgi , el URL completo al repositoriosera http://myhostname/ ˜myuser/hgwebdir.cgi/this/repo .

Si reemplazamos /mi/ruta en el lado izquierdo de este ejemplo con /mi, hgwebdir.cgi eliminara solamente

/mi del nombre del repositorio, y nos ofrecera la ruta virtual ruta/este/repo en lugar de este/repo.

El guion hgwebdir.cgi buscara recursivamente en cada directorio listado en la seccion collections de su fichero

de configuracion, pero no hara el recorrido recursivo dentro de los repositorios que encuentre.

El mecanismo de collections permite publicar facilmente repositorios de una forma “hacer y olvidar”. Sola-

mente requiere configurar el guion CGI y el fichero de configuracion una vez. Despues de eso puede publicar y sacar

de publicacion un repositorio en cualquier momento incluyendolo o excluyendolo de la jerarquıa de directorios en la

cual le haya indicado a hgwebdir.cgi que mirase.

Especificacion explıcita de los repositorios a publicar

Ademas del mecanismo collections, el guion hgwebdir.cgi le permite publicar una lista especıfica de reposi-torios. Para hacerlo, cree una seccion paths, con los contenidos de la siguiente forma:

1 [paths]

2 repo1 = /mi/ruta/a/un/repo

3 repo2 = /ruta/a/otro/repo

72

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 83/204

En este caso, la ruta virtual (el componente que aparecera en el URL) esta en el lado derecho de cada definicion,

mientras que la ruta al repositorio esta a la derecha. Note que no tiene que haber relacion alguna entre la ruta virtual

que elija y el lugar del repositorio en su sistema de ficheros.

Si lo desea, puede usar tanto collections como paths simultaneamente en un solo fichero de configuracion.

Nota: Si varios repositorios tienen la misma ruta virtual, hgwebdir.cgi no repor-

tara ningun error. Pero se comportara de manera impredecible.

6.6.4. Descarga de ficheros fuente

La interfaz web de Mercurial permite a los usuarios descargar un conjunto de cualquier revision. Este conjunto

contendra una replica del directorio de trabajo en la revision en cuestion, pero no contendra una copia de los datos del

repositorio.

Esta caracterıstica no esta habilitada de forma predeterminada. Para habilitarla adicione un allow archive a la

seccion [web] de su fichero hgrc.

6.6.5. Opciones de configuracion en Web

Las interfaces web de Mercurial (la orden “hg serve”, y los guiones hgweb.cgi y hgwebdir.cgi) tienen varias

opciones de configuracion disponibles. Todas ellas van en la seccion [web].

allow archive Determina que mecanismos de descarga soportara Mercurial. Si habilita esta caracterıstica, los usuarios de

la interfaz web podran descargar una copia de la revision del repositorio que esten viendo. Para activar la

caracterıstica de descarga de conjunto, el valor tendra una secuencia de palabras extraıdas de la lista de abajo.

bz2 Un fichero tar con el metodo de compresion bzip2. Tiene la mejor tasa de compresion, pero usa mas

tiempo de procesamiento en el servidor.

gz Un fichero tar, comprimido con gzip.

zip Un fichero zip, comprimido con LZW. Este formato posee la peor tasa de compresi on, pero es muy usado

en el mundo Windows.

Si da una lista vacıa o no tiene la entrada allow archive, esta caracterıstica se deshabilitara. A continuacion se

presenta un ejemplo de como habilitar los tres formatos soportados.

1 [web]

2 allow_archive = bz2 gz zip

allowpull Booleano. Determina si la interfaz web permite a los usuarios remotos emplear “ hg pull” y “hg clone” sobre

el repositorio HTTP. Si se coloca no o false, solamente se habilita la porcion de los procesos “orientados-a-

humanos” de la interfaz web.

contact Cadena. Una cadena en forma libre (pero preferiblemente corta) que identifica a la persona o grupo a cargo

del repositorio. Usualmente contiene el nombre y la direcci on de correo electronico de una persona o de una

lista de correo. A veces tiene sentido colocar esta opcion en el fichero .hg/hgrc del repositorio, pero en otras

oportunidades es mejor hacerlo en el hgrc global si todos los repositorios tienen un unico mantenedor.

maxchanges Entero. La cantidad maxima de conjuntos de cambios a mostrar de forma predeterminada en cada pagina.

maxfiles Entero. La cantidad maxima predeterminada de ficheros modificados a desplegar en una p agina.

stripes Entero. Si la interfaz web despliega “franjas” para facilitar la visualizaci on alineada de filas cuando se ve una

tabla, este valor controla la cantidad de filas en cada franja.

style Controla la plantilla que Mercurial usa para desplegar la interfaz web. Mercurial viene con dos plantillas web,

llamadas default y gitweb (La primera es mas atractiva visualmente). Puede especificar una plantilla propia;

consulte el capıtulo 11. A continuacion mostramos como habilitar el estilo gitweb.

73

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 84/204

1 [web]

2 style = gitweb

templates Ruta. Directorio en el que se buscaran los ficheros plantilla. De forma predeterminada, el guion busca en el

directorio en el cual fue instalado.

Si usa hgwebdir.cgi, puede anadir otras opciones de configuracion en la seccion [web] del fichero hgweb.config

en lugar del fichero hgrc si lo considera mas conveniente. Estas opciones son motd y style.

Opciones especıficas para repositorios individuales

Ciertas opciones de configuracion de [web] deben estar ubicadas en el .hg/hgrc de un repositorio en lugar del

fichero del usuario o el hgrc global.

description Cadena. Una cadena de forma libre (preferiblemente corta) que describa los contenidos o el proposito del repos-

itorio.

name Cadena. El nombre para visualizar en la interfaz web del repositorio. Sustituye el nombre predeterminado, el

cual es el ultimo componente de la ruta del repositorio.

Opciones especıficas a la orden “hg serve”

Algunas opciones en la seccion [web] de un fichero hgrc son de uso exclusivo de la orden “hg serve”.

accesslog Ruta. El nombre del fichero en el cual se escribe la bit acora de acceso. En principio, la orden “hg serve”

escribe esta informacion a la salida estandar, no a un fichero. Las l ıneas de la bitacora se escriben en un formato

de fichero “combinado” estandar, usado por casi todos los servidores web.

address Cadena. La direccion local en la cual el servidor debe escuchar peticiones entrantes. De forma predeterminada,

el servidor escucha en todas las direcciones.

errorlog Ruta. El nombre de un fichero en el cual escribir la bitacora de error. En principio, la orden “hg serve” escribe

esta informacion en la salida de error estandar, no a un fichero.

ipv6 Booleano. Si se usa o no el protocolo IPv6. IPv6 no se usa de manera predeterminada.

port Entero. El numero del puerto TCP en el cual el servidor esperara conexiones. El puerto predeterminado es

el 8000.

Elegir el fichero hgrc correcto para las configuraciones de [web]

Es importante recordar que un servidor web como Apache o lighttpd se ejecutara bajo un ID de usuario que

generalmente no es el suyo Los guiones CGI ejecutados por su servidor, tales como hgweb.cgi, se ejecutaran tambien

con ese ID de usuario.

Si anade opciones [web] a su fichero personal hgrc los guiones CGI no leeran tal fichero hgrc. Tales configu-

raciones solamente afectaran el comportamiento de la orden “hg serve” cuando usted la ejecuta. Para logar que los

guiones CGI vean sus configuraciones, o bien cree un fichero hgrc en el directorio personal del usuario bajo cuyo ID

se ejecuta su servidor web, o anada tales opciones al fichero global hgrc.

74

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 85/204

Capıtulo 7

Nombres de ficheros y asociacion de

patrones

Mercurial provee mecanismos que le permiten trabajar con nombres de ficheros en una manera consistente y

expresiva.

7.1. Nombrado de ficheros simple

Mercurial usa un mecanismo unificado “bajo el capo” para manejar nombres de ficheros. Cada comando se com-

porta de manera uniforme con respecto a los nombres de fichero. La manera en que los comandos operan con nombres

de fichero es la siguiente.

Si usted especifica explıcitamente nombres reales de ficheros en la lınea de comandos, Mercurial opera unicamente

sobre dichos ficheros, como usted esperarıa.

1 $ hg add COPYING README examples/simple.py

Cuando usted provee el nombre de un directorio, Mercurial interpreta eso como “opere en cada fichero en este di-

rectorio y sus subdirectorios”. Mercurial va por todos los ficheros y subdirectorios de un directorio en orden alfabetico.Cuando encuentra un subdirectorio, lo recorrera antes de continuar con el directorio actual.

1 $ hg status src

2 ? src/main.py

3 ? src/watcher/_watcher.c

4 ? src/watcher/watcher.py

5 ? src/xyzzy.txt

7.2. Ejecucion de comandos sin ningun nombre de fichero

Los comandos de Mercurial que trabajan con nombres de fichero tienen comportamientos por defecto adecuados

cuando son utilizados sin pasar ningun patron o nombre de fichero. El tipo de comportamiento depende de lo que

haga el comando. Aquı presento unas cuantas reglas generales que usted puede usar para que es lo que probablemente

hara un comando si usted no le pasa ningun nombre de fichero con el cual trabajar.

Muchos comandos operaran sobre el directorio de trabajo completo. Por ejemplo, esto es lo que hace el comando

“hg add”,

75

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 86/204

Si el comando tiene efectos dif ıciles o incluso imposibles de revertir, se le obligara a usted a proveer explıcita-

mente al menos un nombre o patron (ver mas abajo). Esto lo proteje a usted de, por ejemplo, borrar ficheros

accidentalmente al ejecutar “hg remove” sin ningun argumento.

Es f acil evitar este comportamiento por defecto, si no es el adecuado para usted. Si un comando opera normalmente

en todo el directorio de trabajo, usted puede llamarlo para que trabaje solo en el directorio actual y sus subdirectorio

pasandole el nombre “.”.

1 $ cd src

2 $ hg add -n

3 adding ../MANIFEST.in

4 adding ../examples/performant.py

5 adding ../setup.py

6 adding main.py

7 adding watcher/_watcher.c

8 adding watcher/watcher.py

9 adding xyzzy.txt

10 $ hg add -n .

11 adding main.py

12 adding watcher/_watcher.c

13 adding watcher/watcher.py

14 adding xyzzy.txt

Siguiendo la misma lınea, algunos comandos normalmente imprimen las rutas de ficheros con respecto a la ra ız del

repositorio, aun si usted los llama dentro de un subdirectorio. Dichos comandos imprimiran las rutas de los ficheros

respecto al directorio en que usted se encuentra si se les pasan nombres expl ıcitos. Vamos a ejecutar el comando “hg

status” desde un subdirectorio, y a hacer que opere en el directorio de trabajo completo, a la vez que todas las rutas

de ficheros se imprimen respecto a nuestro subdirectorio, pasandole la salida del comando “hg root”.

1 $ hg status

2 A COPYING

3 A README

4 A examples/simple.py5 ? MANIFEST.in

6 ? examples/performant.py

7 ? setup.py

8 ? src/main.py

9 ? src/watcher/_watcher.c

10 ? src/watcher/watcher.py

11 ? src/xyzzy.txt

12 $ hg status ‘hg root‘

13 A ../COPYING

14 A ../README

15 A ../examples/simple.py

16 ? ../MANIFEST.in

17 ? ../examples/performant.py18 ? ../setup.py

19 ? main.py

20 ? watcher/_watcher.c

21 ? watcher/watcher.py

22 ? xyzzy.txt

76

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 87/204

7.3. Reportar que esta pasando

El ejemplo con el comando “hg add” en la seccion anterior ilustra algo mas que es util acerca de los comandos de

Mercurial. Si un comando opera en un fichero que usted no paso explıcitamente en la lınea de comandos, usualmente

se imprimira el nombre del fichero, para que usted no sea sorprendido por lo que sucede.

Esto es el principio de m´ ınima sorpresa. Si usted se ha referido explıcitamente a un fichero en la lınea de comandos,

no tiene mucho sentido repetir esto de vuelta a usted. Si Mercurial est a actuando en un fichero impl´ ıcitamente, porqueusted no paso nombres, ni directorios, ni patrones (ver masabajo), lo mas seguro es decirle a usted que se esta haciendo.

Usted puede silenciar a los comandos que se comportan de esta manera usando la opcion -q. Tambien puede hacer

que impriman el nombre de cada fichero, aun aquellos que usted indico explıcitamente, usando la opcion -v.

7.4. Uso de patrones para identificar ficheros

Ademas de trabajar con nombres de ficheros y directorios, Mercurial le permite usar patrones para identificar

ficheros. El manejo de patrones de Mercurial es expresivo.

En sistemas tipo Unix (Linux, MacOS, etc.), el trabajo de asociar patrones con nombres de ficheros recae sobre el

interprete de comandos. En estos sistemas, usted debe indicarle expl ıcitamente a Mercurial que el nombre que se le

pasa es un patron. En Windows, el interprete no expande los patrones, ası que Mercurial identificara automaticamente

los nombres que son patrones, y hara la expansion necesaria.Para pasar un patron en vez de un nombre normal en la lınea de comandos, el mecanismo es simple:

1 syntax:patternbody

Un patron es identificado por una cadena de texto corta que indica que tipo de patron es, seguido por un dos puntos,

seguido por el patron en sı.

Mercurial soporta dos tipos de sintaxis para patrones. La que se usa con mas frecuencia se denomina glob1; es el

mismo tipo de asociacion de patrones usado por el interprete de Unix, y tambien deberıa ser familiar para los usuarios

de la lınea de comandos de Windows.

Cuando Mercurial hace asociacion automatica de patrones en Windows, usa la sintaxis glob. Por esto, usted puede

omitir el prefijo “glob:” en Windows, pero tambien es seguro usarlo.

La sintaxis re2 es mas poderosa; le permite especificar patrones usando expresiones regulares, tambi en conocidas

como regexps.A proposito, en los ejemplos siguientes, por favor note que yo tengo el cuidado de rodear todos mis patrones con

comillas sencillas, para que no sean expandidos por el interprete antes de que Mercurial pueda verlos.

7.4.1. Patrones glob estilo interprete

Este es un vistazo general de los tipos de patrones que usted puede usar cuando est a usando asociacion con patrone

glob.

La secuencia “*” se asocia con cualquier cadena, dentro de un unico directorio.

1 $ hg add ’glob:*.py’

2 adding main.py

La secuencia “**” se asocia con cualquier cadena, y cruza los l ımites de los directorios. No es una elementoestandar de los tokens de glob de Unix, pero es aceptado por varios int erpretes Unix populares, y es muy util.

1 $ cd ..

2 $ hg status ’glob:**.py’

1N. del T. Grupo, coleccion, aglomeracion.2N. del T. Expresiones regulares.

77

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 88/204

3 A examples/simple.py

4 A src/main.py

5 ? examples/performant.py

6 ? setup.py

7 ? src/watcher/watcher.py

La secuencia “?” se asocia con cualquier caracter sencillo.

1 $ hg status ’glob:**.?’

2 ? src/watcher/_watcher.c

El caracter “[” marca el inicio de una clase de caracteres. Ella se asocia con cualquier caracter sencillo dentro de

la clase. La clase se finaliza con un caracter “]”. Una clase puede contener multiples rangos de la forma “a-f”, que

en este caso es una abreviacion para “abcdef”.

1 $ hg status ’glob:**[nr-t]’

2 ? MANIFEST.in

3 ? src/xyzzy.txt

Si el primer caracter en aparecer despues de “[” en la clase de caracteres es un “!”, se niega la clase, haciendo que seasocie con cualquier caracter sencillo que no se encuentre en la clase.

Un “{” marca el inicio de un grupo de subpatrones, en donde todo el grupo es asociado si cualquier subpatron en

el grupo puede ser asociado. El caracter “,” separa los subpatrones, y el “}” finaliza el grupo.

1 $ hg status ’glob:*.{in,py}’

2 ? MANIFEST.in

3 ? setup.py

Cuidado!

No olvide que si usted desea asocia un patron con cualquier directorio, no deberıa usar el elemento para asociar

con cualquier cadena “*”, ya que este solo generara asociaciones dentro de un solo directorio. En vez de eso, use el

caracter para asociar con cualquier cadena “**”. Este pequeno ejemplo ilustra la diferencia entre los dos.

1 $ hg status ’glob:*.py’

2 ? setup.py

3 $ hg status ’glob:**.py’

4 A examples/simple.py

5 A src/main.py

6 ? examples/performant.py

7 ? setup.py

8 ? src/watcher/watcher.py

7.4.2. Asociacion con patrones de expresiones regulares re

Mercurial acepta la misma sintaxis para expresiones regulares del lenguaje de programacion Python (internamente

se usa el motor de expresiones regulares de Python). Esta sintaxis est a basada en la misma del lenguaje Perl, que es el

dialecto mas popular en uso (por ejemplo, tambien se usa en Java).

No discutire el dialecto de expresiones regulares de Mercurial en detalle aquı, ya que las mismas no son usadas

frecuentemente. Las expresiones regulares al estilo Perl se encuentran documentadas exhaustivamente en una multitud

de sitios web, y en muchos libros. En vez de eso, me enfocare en unas cuantas cosas que usted deberıa conocer si tiene

la necesidad de usar expresiones regulares en Mercurial.

78

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 89/204

Una expresion regular es comparada contra un nombre de fichero completo, relativo a la ra ız del repositorio. En

otras palabras, aun si usted se encuentra en un subdirectorio foo, si desea asociar ficheros en este directorio, su patron

debe empezar con “foo/”.

Un detalle a tener en cuenta es que, si le son familiares las expresiones regulares al estilo Perl, las de Mercurial

estan enraızadas. Esto es, que la asociacion de una expresion se hace desde el inicio de la cadena; no se buscan

coincidencias dentro de la cadena. Para buscar coincidencias en cualquier sitio dentro de una cadena, empiece su

patron con un “.*”.

7.5. Filtrado de ficheros

Mercurial no solo le provee una variedad de formas para especificar ficheros; le permite limitar aun mas dichos

ficheros mediante el uso de filtros. Los comandos que operan con nombres de fichero aceptan dos opciones de filtrado.

-I, o --include, le permite especificar un patron con el que deben coincidir los ficheros para ser procesados.

-X, o --exclude, le brinda una manera de evitar  procesar ficheros, si coinciden con este patron.

Usted puede pasar multiples veces las opciones -I y -X en la lınea de comandos, e intercalarlos como desee. Por

defecto, Mercurial interpreta los patrones que usted pase usando la sintaxis glob (pero usted puede usar expresiones

regulares si lo necesita).El filtro -I puede verse como un “procese todos los ficheros que coincidan con este filtro”.

1 $ hg status -I ’*.in’

2 ? MANIFEST.in

El filtro -X puede verse como “procese unicamente los ficheros que no coincidan con este patron”.

1 $ hg status -X ’**.py’ src

2 ? src/watcher/_watcher.c

3 ? src/xyzzy.txt

7.6. Ignorar ficheros y directorios no deseados

XXX.

7.7. Sensibilidad a mayusculas

Si usted esta trabajando en un ambiente de desarrollo mixto que contiene tanto sistemas Linux (u otro Unix) y

sistemas Mac o Windows, deberıa tener en mente el hecho de que ellos tratan case (“N” versus “n”) of file names in

incompatible ways. This is not very likely to affect you, and it’s easy to deal with if it does, but it could surprise you

if you don’t know about it.

Operating systems and filesystems differ in the way they handle the case of characters in file and directory names.

There are three common ways to handle case in names.

Completely case insensitive. Uppercase and lowercase versions of a letter are treated as identical, both when

creating a file and during subsequent accesses. This is common on older DOS-based systems.

Case preserving, but insensitive. When a file or directory is created, the case of its name is stored, and can be

retrieved and displayed by the operating system. When an existing file is being looked up, its case is ignored.

This is the standard arrangement on Windows and MacOS. The names foo and FoO identify the same file. This

treatment of uppercase and lowercase letters as interchangeable is also referred to as case folding.

79

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 90/204

Case sensitive. The case of a name is significant at all times. The names foo and FoO identify different files.

This is the way Linux and Unix systems normally work.

On Unix-like systems, it is possible to have any or all of the above ways of handling case in action at once. For

example, if you use a USB thumb drive formatted with a FAT32 filesystem on a Linux system, Linux will handle

names on that filesystem in a case preserving, but insensitive, way.

7.7.1. Almacenamiento portable y seguro de repositorios

El mecanismo de almacenamiento de los repositorios en Mercurial es robusto frente a sensibilidad/insensibilidad 

a may´ usculas. Los nombres de fichero son traducidos para que puedan ser almacenados de manera segura tanto en

sistemas sensibles como insensibles a mayusculas. Esto significa que usted puede usar herramientas normales de

copia de ficheros para transferir un repositorio Mercurial a, por ejemplo, una memoria USB, y trasladar de manera

segura la memoria y el repositorio de ida y vuelta entre un Mac, un PC ejecutando Windows, y un sistema Linux

7.7.2. Deteccion de conflictos de mayusculas/minusculas

Al operar en el directorio de trabajo, Mercurial respeta la pol ıtica de nombrado del sistema de ficheros en que

se encuentre el directorio de trabajo. Si el sistema de ficheros conserva las diferencias entre may usculas, pero no es

sensible a ellas, Mercurial tratara los nombres que solo difieren en mayusculas como uno solo y el mismo.Un aspecto importante de este enfoque es que es posible consignar un conjunto de cambios en un sistema de

ficheros sensible a mayusculas (tıpicamente Linux o Unix) que terminara causando problemas para usuarios en sis-

temas insensibles a mayusculas (usualmente en Windows o MacOS). Si un usuario de Linux consigna cambios a dos

ficheros, uno de ellos llamado myfile.c y el otro llamado MyFile.C, ambos seran almacenados correctamente en

el repositorio. Y seran representados correctamente como ficheros separados, en los directorios de trabajo de otros

usuarios de Linux.

Si un usuario de Windows o Mac jalan este cambio, no tendran problemas inicialmente, porque el mecanismo de

almacenamiento de Mercurial es seguro frente a sensibilidad/insensibilidad a mayusculas. Sin embargo, una vez que

ellos traten de actualizar (“hg update”) el directorio de trabajo con ese conjunto de cambios, o hagan fusion (“hg

merge”) con ese conjunto de cambios, Mercurial vera el conflicto entre los dos nombres de fichero que el sistema de

ficheros tratarıa como el mismo, e impedira que ocurra la actualizacion o fusion.

7.7.3. Arreglar un conflicto de mayusculas/minusculas

Si usted esta usando Windows o Mac en un entorno mixto donde algunos de sus colaboradores est an usando Linux

o Unix, y Mercurial reporta un conflicto de mayusculas/minusculas cuando usted trata de actualizar (“hg update”) o

fusionar (“hg merge”), el procedimiento para arreglar el problema es simple.

Solo busque un sistema Linux o Unix cercano, clone el repositorio problema all ı, y use el comando “hg rename”

de Mercurial para cambiar los nombres de cualquiera de los ficheros o directorios problematicos para que no causen

mas conflictos. Consigne este cambio, y jalelo (“hg pull”) o empujelo (“hg push”) a su sistema Windows o MacOS,

y actualıcelo (“hg update”) a la revision con los nombres que ya no generan conflictos.

El conjunto de cambios con los nombres con conflictos de may usculas/minusculas permanecera en el historial de

su proyecto, y usted no podra actualizar (“hg update”) su directorio de trabajo a dicho conjunto de cambios en un

sistema Windows o MacOS, pero puede continuar el desarrollo sin impedimentos.

Nota: Antes de la version 0.9.3, Mercurial no usaba un mecanismos seguro frente

a sensibilidad/insensibilidad a mayusculas o minusculas, y no detectaba los con-flictos con nombres de ficheros. Si usted esta usando una version mas antigua de

Mercurial en Windows o MacOS, le recomiendo energicamente que se actualice.

80

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 91/204

Capıtulo 8

Administracion de versiones y desarrollo

ramificado

Mercurial ofrece varios mecanismos que le permiten administrar un proyecto que avanza en multiples frentes

simultaneamente. Para entender estos mecanismos, demos un vistazo a la estructura usual de un proyecto de software.

Muchos proyectos de software liberan una version “mayor” que contiene nuevas caracterısticas substanciales. En

paralelo, pueden liberar versiones “menores”. Usualmente estas son identicas a las versiones mayores en las cuales

estan basadas, pero con arreglos para algunos fallos.

En este capıtulo, comenzaremos hablando de como mantener registro de etapas del proyecto como las liberaciones

de una version. Continuaremos hablando del flujo de trabajo entre las diferentes fases de un proyecto, y como puede

ayudar Mercurial a aislar y administrar tal trabajo.

8.1. Dar un nombre persistente a una revision

Cuando usted decide otorgar a una revision el nombre particular de una “version”, es buena idea grabar la identidad

de tal revision. Esto le permitira reproducir dicha version en una fecha posterior, para cualquiera que sea el proposito

que se tenga en ese momento (reproducir un fallo, portar a una nueva plataforma, etc).

1 $ hg init mytag

2 $ cd mytag

3 $ echo hello > myfile

4 $ hg commit -A -m ’Initial commit’

5 adding myfile

Mercurial le permite dar un nombre permanente a cualquier revision usando la orden “hg tag”. Sin causa de

sorpresa, esos nombres se llaman “tags” (etiquetas).

1 $ hg tag v1.0

Una etiqueta no es mas que un “nombre simbolico” para una revision. Las etiquetas existen unicamente para su

conveniencia, brindandole una forma permanente y sencilla de referirse a una revision; Mercurial no interpreta de

ninguna manera los nombres de las etiquetas que usted use. Mercurial tampoco impone restriccion alguna al nombre

de una etiqueta, mas alla de lo necesario para asegurar que una etiqueta pueda procesarse sin ambiguedades. El nombre

de una etiqueta no puede tener ninguno de los siguientes caracteres:

Dos puntos (ASCII 58, “:”)

Retorno de carro (return) (ASCII 13, “\r”)

81

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 92/204

Nueva lınea (ASCII 10, “\n”)

Puede usar la orden “hg tags” para ver las etiquetas presentes en su repositorio. Al desplegarse, cada revision

marcada se identifica primero con su nombre, despues con el numero de revision y finalmente con un hash unico de la

revision.

1 $ hg tags

2 tip 1:515e5c86f4963 v1.0 0:1d3fd3640aaa

Note que tip aparece en en listado generado por “hg tags”. La etiqueta tip es una etiqueta “flotante” especial, que

identifica siempre la revision mas reciente en el repositorio.

Al desplegar la orden “hg tags”, las etiquetas se listan en orden inverso, por numero de revision. Lo que significa

usualmente que las etiquetas mas recientes se listan antes que las mas antiguas. Tambien significa que la etiqueta tip

siempre aparecera como primera etiqueta listada al desplegar la orden “hg tags”.

Cuando usted ejecuta “hg log”, si se muestra una revision que tenga etiquetas asociadas a ella, se imprimiran

tales etiquetas.

1 $ hg log

2 changeset: 1:515e5c86f496

3 tag: tip

4 user: Bryan O’Sullivan <[email protected]>

5 date: Tue Feb 10 18:23:29 2009 +0000

6 summary: Added tag v1.0 for changeset 1d3fd3640aaa

7

8 changeset: 0:1d3fd3640aaa

9 tag: v1.0

10 user: Bryan O’Sullivan <[email protected]>

11 date: Tue Feb 10 18:23:29 2009 +0000

12 summary: Initial commit

13

Siempre que requiera indicar un ID de revision a una orden de Mercurial, aceptara un nombre de etiqueta en sulugar. Internamente, Mercurial traducira su nombre de etiqueta en el ID de revisi on correspondiente, y lo usara.

1 $ echo goodbye > myfile2

2 $ hg commit -A -m ’Second commit’

3 adding myfile2

4 $ hg log -r v1.0

5 changeset: 0:1d3fd3640aaa

6 tag: v1.0

7 user: Bryan O’Sullivan <[email protected]>

8 date: Tue Feb 10 18:23:29 2009 +0000

9 summary: Initial commit

10

No hay lımites en la cantidad de etiquetas por repositorio, o la cantidad de etiquetas que una misma revisi on pueda

tener. Siendo practicos, no es muy buena idea tener “demasiadas” (la cantidad variar a de un proyecto a otro), debido a

que la intencion es ayudarle a encontrar revisiones. Si tiene demasiadas etiquetas, la facilidad de usarlas para identificar

revisiones disminuira rapidamente.

Por ejemplo, si su proyecto tiene etapas (milestones) frecuentes, de pocos d ıas, es perfectamente razonable asig-

narle una etiqueta a cada una de ellas. Pero si tiene un sistema de construccion automatica de binarios que asegura

82

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 93/204

que cada revision puede generarse limpiamente, estarıa introduciendo mucho ruido si se usara una etiqueta para ca-

da generacion exitosa. Mas bien, podrıa usar tags para generaciones fallidas (¡en caso de que estas sean raras!), o

simplemente evitar las etiquetas para llevar cuenta de la posibilidad de generacion de binarios.

Si quiere eliminar una etiqueta que no desea, use “hg tag --remove”.

1 $ hg tag --remove v1.0

2 $ hg tags

3 tip 3:31eda97c4db9

Tambien puede modificar una etiqueta en cualquier momento, para que identifique una revision distinta, simplemente

usando una nueva orden “hg tag”. Debera usar la opcion -f para indicarle a Mercurial que realmente desea actualizar

la etiqueta.

1 $ hg tag -r 1 v1.1

2 $ hg tags

3 tip 4:eb33d1c642f4

4 v1.1 1:515e5c86f496

5 $ hg tag -r 2 v1.1

6 abort: tag ’v1.1’ already exists (use -f to force)

7 $ hg tag -f -r 2 v1.1

8 $ hg tags9 tip 5:b26c4daf4a9d

10 v1.1 2:55d99d62d333

De todas maneras habra un registro permanente de la antigua identidad de la etiqueta, pero Mercurial no la usara.

Por lo tanto no hay problema al marcar con una etiqueta una revision incorrecta; lo unico que debe hacer es mover la

etiqueta hacia la revision correcta tan pronto como localice el error.

Mercurial almacena las etiquetas en un fichero controlado por revisiones en su repositorio. Si ha creado etiquetas,

las encontrara en un fichero llamado .hgtags. Cuando invoca la orden “hg tag”, Mercurial modifica este fichero,

y hace la consignacion del cambio al mismo automaticamente. Esto significa que cada vez que ejecuta “hg tag”,

vera un conjunto de cambios correspondiente en la salida de “hg log”.

1 $ hg tip

2 changeset: 5:b26c4daf4a9d3 tag: tip

4 user: Bryan O’Sullivan <[email protected]>

5 date: Tue Feb 10 18:23:30 2009 +0000

6 summary: Added tag v1.1 for changeset 55d99d62d333

7

8.1.1. Manejo de conflictos entre etiquetas durante una fusion

Usualmente no tendra que preocuparse por el fichero .hgtags, pero a veces hace su aparicion durante una fusion.

El formato del fichero es sencillo: Consiste de una serie de l ıneas. Cada lınea comienza con un hash de conjunto de

cambios, seguido por un espacio, seguido por el nombre de una etiqueta.

Si esta resolviendo un conflicto en el fichero .hgtags durante una fusion, hay un detalle para tener en cuenta almodificar el fichero .hgtags: cuando Mercurial procesa las etiquetas en el repositorio, nunca lee la copia de trabajo

del fichero .hgtags. En cambio, lee la version consignada m´ as reciente del fichero.

Una consecuencia desafortunada de este diseno es que usted no puede verificar que su fichero .hgtags fusion-

ado sea correcto hasta despu´ es de haber consignado un cambio. Ası que si se encuentra resolviendo un conflicto en

.hgtags durante una fusion, asegurese de ejecutar la orden “hg tags” despues de consignar. Si encuentra un error

en el fichero .hgtags, la orden reportara el lugar del error, que podra arreglar y despues consignar. Posteriormente

ejecute de nuevo la orden “hg tags” para asegurarse de que su arreglo fue aplicado correctamente .

83

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 94/204

8.1.2. Etiquetas y clonado

Puede haber notado que la orden “hg clone” tiene la opcion -r que le permite clonar una copia exacta del

repositorio hasta un conjunto de cambios especıfico. El nuevo clon no tendra historial posterior a la revision que usted

haya especificado. Esto tiene una interaccion con etiquetas que puede sorprender a los desprevenidos.

Recuerde que una etiqueta se almacena como una revision al fichero .hgtags, ası que cuando usted crea una eti-

queta, el conjunto de cambios en el cual esta se almacena necesariamente se refiere a un conjunto de cambios anterior.

Cuando ejecuta “hg clone -r foo” para clonar un repositorio hasta la etiqueta foo, el nuevo clon no contendr´ a el

historial que creo la etiqueta que uso para clonar el repositorio. El resultado es que tendr a exactamente el subconjunto

correcto del historial del proyecto en el nuevo repositorio, pero, no la etiqueta que podrıa haber esperado.

8.1.3. Cuando las etiquetas permanentes son demasiado

Dado que las etiquetas de Mercurial estan controladas por revisiones y se llevan en el historial del proyecto, todas

las personas involucradas veran las etiquetas que usted haya creado. El hecho de dar nombres a las revisiones tiene

usos mas alla que simplemente hacer notar que la revision 4237e45506ee es realmente v2.0.2. Si esta tratando de

encontrar un fallo sutil, posiblemente desearıa colocar una etiqueta recordandole algo como “Ana vio los sıntomas en

esta revision”.

Para estos casos, lo que usted posiblemente desearıa serıan etiquetas locales. Puede crear una etiqueta local con

la opcion -l de la orden “hg tag”. Esto guardara la etiqueta en un fichero llamado .hg/localtags. A diferencia de

.hgtags, .hg/localtags no esta controlado por revisiones. Cualquier etiqueta que usted cree usando -l se manten-

dra local al repositorio en el que este trabajando en ese momento.

8.2. El flujo de cambios—El gran cuadro vs. el peque ˜ no

Retomando lo mencionado en el comienzo de un capıtulo, pensemos en el hecho de que un proyecto tiene muchas

piezas concurrentes de trabajo en desarrollo al mismo tiempo.

Puede haber prisa por una nueva version “principal”; una nueva version con un arreglo de fallo a la ultima version;

y una version de “mantenimiento correctivo” a una version antigua que ha entrado en modo de mantenimiento.

Usualmente la gente se refiere a esas direcciones concurrentes de desarrollo como “ramas”. Sin embargo, ya hemos

visto que en varias ocasiones Mercurial trata a todo el historial como una serie de ramas y fusiones. Realmente lo que

tenemos aquı es dos ideas que se relacionan perifericamente, pero que en esencia comparten un nombre.

“El gran cuadro” Las ramas representan un barrido de la evolucion del proyecto; la gente les da nombres y

hablan acerca de ellas en sus conversaciones.

“El cuadro pequeno” Las ramas son artefactos de las actividades diarias de desarrollar y fusionar cambios.

Exponen la narrativa de como se desarrollo el codigo.

8.3. Administrar ramas en repositorios estilo gran cuadro

En Mercurial la forma mas sencilla de aislar una rama del “gran cuadro” es a traves de un repositorio dedica-

do. Si cuenta con un repositorio compartido existente —llamemoslo myproject—que alcanzo la etapa “1.0”, puede

comenzar a prepararse para versiones de mantenimiento futuras a partir de la version 1.0 marcando con una etiqueta

la revision con la cual preparo la version 1.0.

1 $ cd myproject

2 $ hg tag v1.0

Ahora puede clonar un repositorio compartido nuevo myproject-1.0.1 con tal etiqueta.

84

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 95/204

1 $ cd ..

2 $ hg clone myproject myproject-1.0.1

3 updating working directory

4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

Posteriormente, si alguien necesita trabajar en la reparacion de un fallo deberıa dirigirse a la liberacion de ver-sion 1.0.1 que viene en camino, ellos clonarıan el repositorio myproject-1.0.1, harıan sus cambios y los empujarıan

de vuelta.

1 $ hg clone myproject-1.0.1 my-1.0.1-bugfix

2 updating working directory

3 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

4 $ cd my-1.0.1-bugfix

5 $ echo ’I fixed a bug using only echo!’ >> myfile

6 $ hg commit -m ’Important fix for 1.0.1’

7 $ hg push

8 pushing to /tmp/branch-repo07QkL5/myproject-1.0.1

9 searching for changes

10 adding changesets11 adding manifests

12 adding file changes

13 added 1 changesets with 1 changes to 1 files

Mientras tanto, el desarrollo para la siguiente version mayor puede continuar aislado e incolume, en el repositorio

myproject.

1 $ cd ..

2 $ hg clone myproject my-feature

3 updating working directory

4 2 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 $ cd my-feature

6 $ echo ’This sure is an exciting new feature!’ > mynewfile7 $ hg commit -A -m ’New feature’

8 adding mynewfile

9 $ hg push

10 pushing to /tmp/branch-repo07QkL5/myproject

11 searching for changes

12 adding changesets

13 adding manifests

14 adding file changes

15 added 1 changesets with 1 changes to 1 files

8.4. No repita trabajo: fusion entre ramasEn muchos casos, cuando tiene un fallo para arreglar en una rama de mantenimiento, es muy probable que el

fallo tambien este en la rama principal (y posiblemente en otras ramas de mantenimiento tambi en). Solamente un

desarrollador extrano desearıa corregir el mismo fallo muchas veces, por tanto, veremos varias alternativas con las que

Mercurial puede ayudarle a administrar tales arreglos de fallo sin duplicar su trabajo.

En el caso mas sencillo, basta con jalar los cambios de la rama de mantenimiento a la rama objetivo en su clon

local.

85

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 96/204

1 $ cd ..

2 $ hg clone myproject myproject-merge

3 updating working directory

4 3 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 $ cd myproject-merge

6 $ hg pull ../myproject-1.0.17 pulling from ../myproject-1.0.1

8 searching for changes

9 adding changesets

10 adding manifests

11 adding file changes

12 added 1 changesets with 1 changes to 1 files (+1 heads)

13 (run ’hg heads’ to see heads, ’hg merge’ to merge)

A continuacion debera mezclar las cabezas de las dos ramas, y empujar de nuevo a la rama principal.

1 $ hg merge

2 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

3 (branch merge, don’t forget to commit)4 $ hg commit -m ’Merge bugfix from 1.0.1 branch’

5 $ hg push

6 pushing to /tmp/branch-repo07QkL5/myproject

7 searching for changes

8 adding changesets

9 adding manifests

10 adding file changes

11 added 2 changesets with 1 changes to 1 files

8.5. Nombrar ramas dentro de un repositorio

La aproximacion correcta en casi todas las oportunidades es aislar las ramas en los repositorios. Es f acil de entender

gracias a su simplicidad; y es dif ıcil cometer errores. Hay una relacion uno a uno entre las ramas y los directorios con

los que esta trabajando en su sistema. Esto le permite usar emplear herramientas usuales (que no son conscientes de

Mercurial) para trabajar con los ficheros dentro de una rama/repositorio.

Si se encuentra mas en la categorıa “usuario diestro” ( y sus colaboradores tambien), puede considerar otra alter-

nativa para administrar las ramas. He mencionado con anterioridad la distincion a nivel humano entre las ramas estilo

“cuadro pequeno” y “gran cuadro”. Mientras que Mercurial trabaja con muchas ramas del estilo “cuadro pequeno”

en el repositorio todo el tiempo (por ejemplo cuando usted jala cambios, pero antes de fusionarlos), tambi´ en puede

trabajar con varias ramas del “cuadro grande”.

El truco para trabajar de esta forma en Mercurial se logra gracias a que puede asignar un nombre persistente a una

rama. Siempre existe una rama llamada default. Incluso antes de que empiece a nombrar ramas por su cuenta, puede

encontrar indicios de la rama default si los busca.

Por ejemplo, cuando invoca la orden “hg commit”, y se lanza su editor para introducir el mensaje de la consignacion,busque la lınea que contiene el texto “HG: branch default” al final. Le esta indicando que su consignacion ocur-

rira en la rama llamada default.

Use la orden “hg branches” para empezar a trabajar con ramas nombradas. Esta orden mostrara las ramas pre-

sentes en su repositorio, indicandole que conjunto de cambios es la punta de cada una.

1 $ hg tip

2 changeset: 0:c54ce9a68981

86

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 97/204

3 tag: tip

4 user: Bryan O’Sullivan <[email protected]>

5 date: Tue Feb 10 18:23:16 2009 +0000

6 summary: Initial commit

7

8 $ hg branches

9 default 0:c54ce9a68981

Dado que todavıa no ha creado ramas nombradas, la unica que vera sera default.

Para hallar cual es la rama “actual”, invoque la orden “hg branch”, sin argumento alguno. Le informara en que ra-

ma se encuentra el padre del conjunto de cambios actual.

1 $ hg branch

2 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 $ hg branch foo

2 marked working directory as branch foo3 $ hg branch

4 foo

Despues de crear la rama, usted podrıa desear ver el efecto que tuvo la orden “hg branch”. ¿Que reportan las

ordenes “hg status” y “hg tip”?

1 $ hg status

2 $ hg tip

3 changeset: 0:c54ce9a68981

4 tag: tip

5 user: Bryan O’Sullivan <[email protected]>

6 date: Tue Feb 10 18:23:16 2009 +0000

7 summary: Initial commit8

Nada cambia en el directorio actual, y no se ha anadido nada al historial. Esto sugiere que al ejecutar la orden “ hg

branch” no hay un efecto permanente; solamente le indica a que nombre de rama usara la pr´ oxima vez que consigne

un conjunto de cambios.

Cuando consigna un cambio, Mercurial almacena el nombre de la rama en la cual consigno. Una vez que haya

cambiado de la rama default y haya consignado, vera que el nombre de la nueva rama se mostrara cuando use la

orden “hg log”, “hg tip”, y otras ordenes que desplieguen la misma clase de informacion.

1 $ echo ’hello again’ >> myfile

2 $ hg commit -m ’Second commit’

3 $ hg tip

4 changeset: 1:b108bc883cbc5 branch: foo

6 tag: tip

7 user: Bryan O’Sullivan <[email protected]>

8 date: Tue Feb 10 18:23:17 2009 +0000

9 summary: Second commit

10

87

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 98/204

Las ordenes del tipo “hg log” imprimiran el nombre de la rama de cualquier conjunto de cambios que no este en la

rama default. Como resultado, si nunca usa ramas nombradas, nunca vera esta informacion.

Una vez que haya nombrado una rama y consignado un cambio con ese nombre, todas las consignaciones subse-

cuentes que desciendan de ese cambio heredaran el mismo nombre de rama. Puede cambiar el nombre de una rama en

cualquier momento con la orden “hg branch”.

1

$ hg branch2 foo

3 $ hg branch bar

4 marked working directory as branch bar

5 $ echo new file > newfile

6 $ hg commit -A -m ’Third commit’

7 adding newfile

8 $ hg tip

9 changeset: 2:7f37f4b1f9a3

10 branch: bar

11 tag: tip

12 user: Bryan O’Sullivan <[email protected]>

13 date: Tue Feb 10 18:23:17 2009 +0000

14 summary: Third commit15

Esto es algo que no hara muy seguido en la practica, debido que los nombres de las ramas tienden a tener vidas largas.

(Esto no es una regla, solamente una observacion.)

8.6. Tratamiento de varias ramas nombradas en un repositorio

Si tiene mas de una rama nombrada en un repositorio, Mercurial recordara la rama en la cual esta su directorio de

trabajo cuando invoque una orden como “hg update” o “hg pull -u”. Se actualizara su directorio de trabajo actual

a la punta de esta rama, sin importar cual sea la punta “a lo largo del repositorio”. Para actualizar a una revisi on que

esta en una rama con distinto nombre, puede necesitar la opcion -C de “hg update”.

Este comportamiento puede ser sutil, ası que veamoslo en accion. Primero, recordemos en que rama estamostrabajando, y que ramas estan en nuestro repositorio.

1 $ hg parents

2 changeset: 2:7f37f4b1f9a3

3 branch: bar

4 tag: tip

5 user: Bryan O’Sullivan <[email protected]>

6 date: Tue Feb 10 18:23:17 2009 +0000

7 summary: Third commit

8

9 $ hg branches

10 bar 2:7f37f4b1f9a3

11 foo 1:b108bc883cbc (inactive)12 default 0:c54ce9a68981 (inactive)

Estamos en la rama bar, pero existe otra rama mas antigua llamada “hg foo”.

Podemos hacer “hg update” entre los tipos de las ramas foo y bar sin necesidad de usar la opcion -C, puesto que

esto solamente implica ir linealmente hacia adelante y atras en nuestro historial de cambios.

88

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 99/204

1 $ hg update foo

2 0 files updated, 0 files merged, 1 files removed, 0 files unresolved

3 $ hg parents

4 changeset: 1:b108bc883cbc

5 branch: foo

6 user: Bryan O’Sullivan <[email protected]>7 date: Tue Feb 10 18:23:17 2009 +0000

8 summary: Second commit

9

10 $ hg update bar

11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

12 $ hg parents

13 changeset: 2:7f37f4b1f9a3

14 branch: bar

15 tag: tip

16 user: Bryan O’Sullivan <[email protected]>

17 date: Tue Feb 10 18:23:17 2009 +0000

18 summary: Third commit

19

Si volvemos a la rama foo e invocamos la orden “hg update”, nos mantendra en foo, sin movernos a la punta de

bar.

1 $ hg update foo

2 0 files updated, 0 files merged, 1 files removed, 0 files unresolved

3 $ hg update

4 0 files updated, 0 files merged, 0 files removed, 0 files unresolved

Al consignar un cambio a la rama foo se introducira una nueva cabeza.

1 $ echo something > somefile

2 $ hg commit -A -m ’New file’3 adding somefile

4 created new head

5 $ hg heads

6 changeset: 3:1ca81328634a

7 branch: foo

8 tag: tip

9 parent: 1:b108bc883cbc

10 user: Bryan O’Sullivan <[email protected]>

11 date: Tue Feb 10 18:23:17 2009 +0000

12 summary: New file

13

14 changeset: 2:7f37f4b1f9a3

15 branch: bar

16 user: Bryan O’Sullivan <[email protected]>

17 date: Tue Feb 10 18:23:17 2009 +0000

18 summary: Third commit

19

89

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 100/204

8.7. Nombres de ramas y fusiones

Posiblemente ha notado que las fusiones en Mercurial no son simetricas. Supongamos que su repositorio tiene dos

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 fusion, y 23 como el segundo. Mientras que si hago “ hg update” a 23 y despues aplico “hg merge” con

17, grabara a 23 como el primer padre, y 17 como el segundo.

Esto afecta el como elige Mercurial el nombre de la rama cuando usted hace la fusion. Despues de una fusion,Mercurial mantendra el nombre de la rama del primer padre cuando consigne el resultado de la fusion. Si el primer

nombre de su padre es foo, y fusiona con bar, el nombre de la rama continuara siendo foo despues de fusionar.

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 tambien. Consignamos cambios distintos; yo jalo sus cambios; Ahora tengo

dos cabezas, cada una afirmando estar en la rama foo. El resultado de una fusion sera una unica cabeza en la rama foo

como usted esperarıa.

Pero si estoy trabajando en la rama bar, y fusiono el trabajo de la rama foo, el resultado permanecera en la rama

bar.

1 $ hg branch

2 bar

3 $ hg merge foo

4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 (branch merge, don’t forget to commit)

6 $ hg commit -m ’Merge’

7 $ hg tip

8 changeset: 4:a6a8b6aebf33

9 branch: bar

10 tag: tip

11 parent: 2:7f37f4b1f9a3

12 parent: 3:1ca81328634a

13 user: Bryan O’Sullivan <[email protected]>

14 date: Tue Feb 10 18:23:17 2009 +0000

15 summary: Merge

16

En un ejemplo mas concreto, si yo estoy trabajando en la rama bleeding-edge, y deseo traer los arreglos mas

recientes de la rama estable, Mercurial elegira el nombre de rama “correcto” (bleeding-edge) cuando yo jale una

fusion desde estable.

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 mas sencillo, dar un nombre a cada rama ofrece un registro permanente acerca de en que conjunto de

cambios se genero la rama. Esto le ofrece mas contexto cuando este tratando de seguir el historial de un proyecto

ramificado de larga vida.

Si esta trabajando con repositorios compartidos, puede configurar el gancho pretxnchangegroup para que cadauno bloquee los cambios con nombres de rama “incorrectos” que estan por adicionarse. Este provee una defensa

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 [hooks]

2 pretxnchangegroup.branch = hg heads --template ’branches ’ | grep mybranch

90

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 101/204

Capıtulo 9

Encontrar y arreglar sus equivocaciones

Errar es humano, pero tratar adecuadamente las consecuencias requiere un sistema de control de revisiones de

primera categorıa. En este capıtulo, discutiremos algunas tecnicas que puede usar cuando encuentra que hay un prob-

lema enraizado en su proyecto. Mercurial tiene unas caracterısticas poderosas que le ayudaran a isolar las fuentes de

los problemas, y a dar cuenta de ellas apropiadamente.

9.1. Borrar el historial local

9.1.1. La consignacion accidental

Tengo el problema ocasional, pero persistente de teclear mas rapido de lo que pienso, que aveces resulta en

consignar un conjunto de cambios incompleto o simplemente malo. En mi caso, el conjunto de cambios incompleto

consiste en que cree un nuevo fichero fuente, pero olvide hacerle “hg add”. Un conjunto de cambios“simplemente

malo” no es tan comun, pero sı resulta muy molesto.

9.1.2. Hacer rollback una transaccion

En la seccion 4.2.2, mencione que Mercurial trata modificacion a un repositorio como una transacci´ on. Cada vez

que consigna un conjunto de cambios o lo jala de otro repositorio, Mercurial recuerda lo que hizo. Puede deshacer,

o hacer roll back 1, exactamente una de tales acciones usando la orden “hg rollback”. (Ver en la seccion 9.1.4 una

anotacion importante acerca del uso de esta orden.)

A continuacion una equivocacion que me sucede frecuentemente: consignar un cambio en el cual he creado un

nuevo fichero, pero he olvidado hacerle “hg add”.

1 $ hg status

2 M a

3 $ e c h o b > b

4 $ hg commit -m ’Add file b’

La salida de “hg status” despues de la consignacion confirma inmediatamente este error.

1 $ hg status

2 ? b

3 $ hg tip

4 changeset: 1:be1cdd4c4fea

5 tag: tip

1N. del T. 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

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 102/204

6 user: Bryan O’Sullivan <[email protected]>

7 date: Tue Feb 10 18:23:29 2009 +0000

8 summary: Add file b

9

La consignacion capturo los cambios en el fichero a, pero no el nuevo fichero b. Si yo publicara este conjunto de

cambios a un repositorio compartido con un colega, es bastante probable que algo en a se refiriera a b, el cual podrıano estar presente cuando jalen mis cambios del repositorio. Me convertirıa el sujeto de cierta indignacion.

Como sea, la suerte me acompana—Encontre mi error antes de publicar el conjunto de cambios. Uso la orden “hg

rollback”, y Mercurial hace desaparecer el ultimo conjunto de cambios.

1 $ hg rollback

2 rolling back last transaction

3 $ hg tip

4 changeset: 0:c40e0a2ea41e

5 tag: tip

6 user: Bryan O’Sullivan <[email protected]>

7 date: Tue Feb 10 18:23:29 2009 +0000

8 summary: First commit

9

10 $ hg status

11 M a

12 ? b

El conjunto de cambios ya no esta en el historial del repositorio, y el directorio de trabajo cree que el fichero a ha

sido modificado. La consignacion y el roll back dejaron el directorio de trabajo exactamente como estaba antes de la

consignacion; el conjunto de cambios ha sido eliminado totlamente. Ahora puedo hacer “hg add” al fichero b, y hacer

de nuevo la consignacion.

1 $ hg add b

2 $ hg commit -m ’Add file b, this time for real’

9.1.3. Erroneamente jalado

Mantener ramas de desarrollo separadas de un proyecto en distintos repositorios es una practica comun con Mercu-

rial. Su equipo de desarrollo puede tener un repositorio compartido para la versi on “0.9” y otra con cambios distintos

para la version “1.0”.

Con este escenario, puede imaginar las consecuencias si tuviera un repositorio local “0.9”, y jalara accidentalmente

los cambios del repositorio compartido de la version “1.0” en este. En el peor de los casos, por falta de atenci on, es

posible que publique tales cambios en el arbol compartido “0.9”, confundiendo a todo su equipo de trabajo (pero no

se preocupe, volveremos a este terrorıfico escenario posteriormente). En todo caso, es muy probable que usted se de

cuenta inmediatamente, dado que Mercurial mostrara el URL de donde esta jalando, o que vea jalando una sospechosa

gran cantidad de cambios en el repositorio.

La orden “hg rollback” excluira eficientemente los conjuntos de cambios que haya acabado de jalar. Mercurial

agrupa todos los cambios de un “hg pull” a una unica transaccion y bastara con un “hg rollback” para deshaceresta equivocacion.

9.1.4. Despues de publicar, un roll back es futil

El valor de “hg rollback” se anula cuando ha publicado sus cambios a otro repositorio. Un cambio desaparece

totalmente al hacer roll back, pero solamente en el repositorio en el cual aplica “hg rollback”. Debido a que un roll

back elimina el historial, no hay forma de que la desaparicion de un cambio se propague entre repositorios.

92

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 103/204

Si ha publicado un cambio en otro repositorio—particularmente si es un repositorio publico—esencialmente

esta “en terreno agreste,” y tendra que reparar la equivocacion de un modo distinto. Lo que pasara si publica un

conjunto de cambios en algun sitio, hacer rollback y despues volver a jalar del repositorio del cual habıa publicado, es

que el conjunto de cambios reaparecera en su repositorio.

(Si esta absolutamente segruro de que el conjunto de cambios al que desea hacer rollback es el cambio m as reciente

del repositorio en el cual publico, y sabe que nadie mas pudo haber jalado de tal repositorio, puede hacer rollback del

conjunto de cambios allı, pero es mejor no confiar en una solucion de este estilo. Si lo hace, tarde o temprano unconjunto de cambios lograra colarse en un repositorio que usted no controle directamente (o del cual se ha olvidado),

y volvera a hostigarle.)

9.1.5. Solamente hay un roll back

Mercurial almacena exactamente una transaccion en su bitacora de transacciones; tal transaccion es la mas reciente

de las que haya ocurrido en el repositorio. Esto significa que solamente puede hacer roll back a una transaccion. Si

espera poder hacer roll back a una transaccion despues al antecesor, observara que no es el comportamiento que

obtendra.

1 $ hg rollback

2 rolling back last transaction

3 $ hg rollback

4 no rollback information available

Una vez que haya aplicado un rollback en una transaccion a un repositorio, no podra volver a hacer rollback hasta que

haga una consignacion o haya jalado.

9.2. Revertir un cambio equivocado

Si modifica un fichero y se da cuenta que no quer ıa realmente cambiar tal fichero, y todavıa no ha consignado

los cambios, 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, usualmente deshace sus

modificaciones.)

Ilustremos como actua la orden “hg revert” con un ejemplo pequeno. Comenzaremos modificando un fichero al

cual Mercurial ya esta siguiendo.

1 $ cat file

2 original content

3 $ echo unwanted change >> file

4 $ hg diff file

5 diff -r f8694d2c79ed file

6 --- a/file Tue Feb 10 18:23:21 2009 +0000

7 +++ b/file Tue Feb 10 18:23:21 2009 +0000

8 @@ -1,1 +1,2 @@

9 original content

10 +unwanted change

Si no queremos ese cambio, podemos aplicar “hg revert” al fichero.

1 $ hg status

2 M file

3 $ hg revert file

4 $ cat file

5 original content

93

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 104/204

La orden “hg revert” nos brinda un grado adicional de seguridad guardando nuestro fichero modificado con la

extension .orig.

1 $ hg status

2 ? file.orig

3 $ cat file.orig

4 original content

5 unwanted change

Este es un resumen de casos en los cuales la orden “hg revert” es de utilidad. Describiremos cada uno de ellos

con mas detalle en la seccion siguiente.

Si usted modifica un fichero, lo restaurara a su estado sin modificacion previo.

Si usted hace “hg add” a un fichero, revertira el estado de “adicionado” del fichero, pero no lo tocara

Si borra un fichero sin decirle a Mercurial, restaurara el fichero con sus contenidos sin modificacion.

Si usa la orden “hg remove” para eliminar un fichero, deshara el estado “removido” del fichero, y lo restau-

rara con sus contenidos sin modificacion.

9.2.1. Errores al administrar ficheros

La orden “hg revert” es util para mas que ficheros modificados. Le permite reversar los resultados de todas las

ordenes de administracion de ficheros que provee Mercurial—“hg add”, “hg remove”, y las demas.

Si usted hace “hg add” a un fichero, y no deseaba que Mercurial le diera seguimiento, use “hg revert” para

deshacer la adicion. No se preocupe; Mercurial no modificara de forma alguna el fichero. Solamente lo “desmarcara”.

1 $ echo oops > oops

2 $ hg add oops

3 $ hg status oops

4 A oops

5 $ hg revert oops

6 $ hg status

7 ? oops

De forma similar, Si le solicita a Mercurial hacer “hg remove” a un fichero, puede usar “hg revert” para restaru-

rarlo a los contenidos que tenıa la revision padre del directorio de trabajo.

1 $ hg remove file

2 $ hg status

3 R file

4 $ hg revert file

5 $ hg status

6 $ ls file

7 file

Funciona de la misma manera para un fichero que usted haya eliminado manualmente, sin decirle a Mercurial (recuerde

que en la terminologıa de Mercurial esta clase de fichero se llama “faltante”).

1 $ rm file

2 $ hg status

3 ! file

4 $ hg revert file

94

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 105/204

5 $ ls file

6 file

Si usted revierte un “hg copy”, el fichero a donde se copio permanece en su directorio de trabajo, pero sin

seguimiento. Dado que una copia no afecta el fichero fuente de copiado de ninguna maner, Mercurial no hace na-

da con este.

1 $ hg copy file new-file

2 $ hg revert new-file

3 $ hg status

4 ? new-file

Un caso ligeramente especial:revertir un renombramiento

Si hace “hg rename” a un fichero, hay un detalle que debe tener en cuenta. Cuando aplica “ hg revert” a un

cambio de nombre, no es suficiente proveer el nombre del fichero destino, como puede verlo en el siguiente ejemplo.

1 $ hg rename file new-file

2 $ hg revert new-file

3 $ hg status4 ? new-file

Como puede ver en la salida de “hg status”, el fichero con el nuevo nombre no se identifica m as como agregado,

pero el fichero con el nombre-inicial se elimna! Esto es contra-intuitivo (por lo menos para mı), pero por lo menos es

f acil arreglarlo.

1 $ hg revert file

2 no changes needed to file

3 $ hg status

4 ? new-file

Por lo tanto, recuerde, para revertir un “hg rename”, debe proveer ambos nombres, la fuente y el destino.

(A proposito, si elimina un fichero, y modifica el fichero con el nuevo nombre, al revertir ambos componentesdel renombramiento, cuando Mercurial restaure el fichero que fue eliminado como parte del renombramiento, no

sera modificado. Si necesita que las modificaciones en el fichero destino del renombramiento se muestren, no olvide

copiarlas encima.)

Estos aspectos engorrosos al revertir un renombramiento se constituyen discutiblemente en un fallo de Mercurial.

9.3. Tratar cambios consignados

Considere un caso en el que ha consignado el cambio a, y otro cambio b sobre este; se ha dado cuenta que el

cambio a era incorrecto. Mercurial le permite “retroceder” un conjunto de cambios completo autom aticamente, y

construir bloques que le permitan revertir parte de un conjunto de cambios a mano.

Antes de leer esta seccion, hay algo para tener en cuenta: la orden “hg backout” deshace cambios adicionando

al historial, sin modificar o borrar. Es la herramienta correcta si esta arreglando fallos, pero no si esta tratando dedeshacer algun cambio que tiene consecuencias catastroficas. Para tratar con esos, vea la seccion 9.4.

9.3.1. Retroceder un conjunto de cambios

La orden “hg backout” le permite “deshacer” los efectos de todo un conjunto de cambios de forma automatizada.

Dado que el historial de Mercurial es inmutable, esta orden no se deshace del conjunto de cambios que usted desea

deshacer. En cambio, crea un nuevo conjunto de cambios que reversa el conjunto de cambios que usted indique.

95

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 106/204

La operacion de la orden “hg backout” es un poco intrincada, y lo ilustraremos con algunos ejemplos. Primero

crearemos un repositorio con algunos cambios sencillos.

1 $ hg init myrepo

2 $ cd myrepo

3 $ echo first change >> myfile

4

$ hg add myfile5 $ hg commit -m ’first change’

6 $ echo second change >> myfile

7 $ hg commit -m ’second change’

La orden “hg backout” toma un ID de conjunto de cambios como su argumento; el conjunto de cambios a

retroceder. Normalmente “hg backout” le ofrecera un editor de texto para escribir el mensaje de la consignacion,

para dejar un registro de por que esta retrocediendo. En este ejemplo, colocamos un mensaje en la consignacion

usando la opcion -m.

9.3.2. Retroceder el conjunto de cambios punta

Comenzamos retrocediendo el ultimo conjunto de cambios que consignamos.

1 $ hg backout -m ’back out second change’ tip

2 reverting myfile

3 changeset 2:1d9ee76a7513 backs out changeset 1:cab6a78bf14b

4 $ cat myfile

5 first change

Puede ver que la segunda lınea de myfile ya no esta presente. La salida de “hg log” nos da una idea de lo que la

orden “hg backout” ha hecho.

1 $ hg log --style compact

2 2[tip] 1d9ee76a7513 2009-02-10 18:23 +0000 bos

3 back out second change

4

5 1 cab6a78bf14b 2009-02-10 18:23 +0000 bos

6 second change

7

8 0 60b8d10ede6c 2009-02-10 18:23 +0000 bos

9 first change

10

Vea que el nuevo conjunto de cambios que “hg backout” ha creado es un hijo del conjunto de cambios que retroced-

imos. Es mas sencillo de ver en la figura 9.1, que presenta una vista grafica del historial de cambios. Como puede ver,

el historial es bonito y lineal.

9.3.3. Retroceso de un cambio que no es la puntaSi desea retrocede un cambio distinto al ultimo que ha consignado, use la opcion --merge a la orden “hg backout”.

1 $ cd ..

2 $ hg clone -r1 myrepo non-tip-repo

3 requesting all changes

4 adding changesets

96

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 107/204

primer cambio

segundo cambio

reversar

segundo cambio

Figura 9.1: Retroceso de un cambio con la orden “hg backout”

5 adding manifests

6 adding file changes

7 added 2 changesets with 2 changes to 1 files

8 updating working directory

9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

10 $ cd non-tip-repo

Que resulta en un retroceso de un conjunto de cambios “en un solo tiro”, una operacion que resulta normalmente

rapida y sencilla.

1 $ echo third change >> myfile

2 $ hg commit -m ’third change’

3 $ hg backout --merge -m ’back out second change’ 1

4 reverting myfile

5 created new head

6 changeset 3:688f1a6067e5 backs out changeset 1:cab6a78bf14b

7 merging with changeset 3:688f1a6067e5

8 merging myfile

9 0 files updated, 1 files merged, 0 files removed, 0 files unresolved

10 (branch merge, don’t forget to commit)

Si ve los contenidos del fichero myfile despues de finalizar el retroceso, vera que el primer y el tercer cambio

estan presentes, pero no el segundo.

1 $ cat myfile

2 first change

3 third change

Como lo muestra el historial grafico en la figura 9.2, Mercurial realmente consigna dos cambios en estas situaciones

(los nodos encerrados en una caja son aquellos que Mercurial consigna automaticamente). Antes de que Mercurial

comience el proceso de retroceso, primero recuerda cual es el padre del directorio de trabajo. Posteriormente hace un

97

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 108/204

retroceso al conjunto de cambios objetivo y lo consigna como un conjunto de cambios. Finalmente, fusiona con el

padre anterior del directorio de trabajo, y consigna el resultado de la fusion.

primer cambio

segundo cambio

tercer cambioreversar

segundo cambio

fusión

automatizar

fusión

Figura 9.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”, solamente con un poco de historial adicional que deshace el

efecto de un conjunto de cambios que usted querıa evitar.

Use siempre la opcion --merge

De hecho, dado que la opcion --merge siempre hara lo “correcto” este o no retrocediendo el conjunto de cambios

punta (p.e. no tratara de fusionar si esta retrocediendo la punta, dado que no es necesario), usted deberıa usar siempre

esta opcion cuando ejecuta la orden “hg backout”.

9.3.4. Mas control sobre el proceso de retroceso

A pesar de que recomiendo usar siempre la opcion --merge cuando esta retrocediendo un cambio, la orden “hg

backout” le permite decidir como mezclar un retroceso de un conjunto de cambios. Es muy extrano que usted necestite

tomar control del proceso de retroceso de forma manual, pero puede ser util entender lo que la orden “hg backout”

esta haciendo automaticamente para usted. Para ilustrarlo, clonemos nuestro primer repositorio, pero omitamos el

retroceso que contiene.

1 $ cd ..

2 $ hg clone -r1 myrepo newrepo

3 requesting all changes

4 adding changesets

5 adding manifests

6 adding file changes

7 added 2 changesets with 2 changes to 1 files

98

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 109/204

8 updating working directory

9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

10 $ cd newrepo

Como en el ejemplo anterior, consignaremos un tercer cambio, despues haremos retroceso de su padre, y veremos

que pasa.

1 $ echo third change >> myfile

2 $ hg commit -m ’third change’

3 $ hg backout -m ’back out second change’ 1

4 reverting myfile

5 created new head

6 changeset 3:688f1a6067e5 backs out changeset 1:cab6a78bf14b

7 the backout changeset is a new head - do not forget to merge

8 (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; es por lo

tanto una nueva cabeza, no un descendiente del conjunto de cambios que era la punta. La orden “hg backout” fue

muy explıcita diciendolo.

1 $ hg log --style compact

2 3[tip]:1 688f1a6067e5 2009-02-10 18:23 +0000 bos

3 back out second change

4

5 2 72a18afb4ae5 2009-02-10 18:23 +0000 bos

6 third change

7

8 1 cab6a78bf14b 2009-02-10 18:23 +0000 bos

9 second change

10

11 0 60b8d10ede6c 2009-02-10 18:23 +0000 bos

12 first change

13

De nuevo, es mas sencillo lo que paso viendo una grafica del historial de revisiones, en la figura 9.3. Esto nos

aclara que cuando usamos “hg backout” para retroceder un cambio a algo que no sea la punta, Mercurial a nade una

nueva cabeza al repositorio (el cambio que consigno esta encerrado en una caja).

Despues de que la orden “hg backout” ha terminado, deja un nuevo conjunto de cambios de “retroceso” como el

padre del directorio de trabajo.

1 $ hg parents

2 changeset: 2:72a18afb4ae5

3 user: Bryan O’Sullivan <[email protected]>

4 date: Tue Feb 10 18:23:13 2009 +0000

5 summary: third change6

Ahora tenemos dos conjuntos de cambios aislados.

1 $ hg heads

2 changeset: 3:688f1a6067e5

3 tag: tip

99

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 110/204

primer cambio

segundo cambio

tercer cambioreversar

segundo cambio

Figura 9.3: Retroceso usando la orden “hg backout”

4 parent: 1:cab6a78bf14b

5 user: Bryan O’Sullivan <[email protected]>

6 date: Tue Feb 10 18:23:13 2009 +0000

7 summary: back out second change

8

9 changeset: 2:72a18afb4ae5

10 user: Bryan O’Sullivan <[email protected]>

11 date: Tue Feb 10 18:23:13 2009 +0000

12 summary: third change

13

Reflexionemos acerca de lo que esperamos ver como contenidos de myfile. El primer cambio deberıa estar pre-

sente, porque nunca le hicimos retroceso. El segundo cambio debio desaparecer, puesto que es el que retrocedimos.Dado que la grafica del historial muestra que el tercer camlio es una cabeza separada, no esperamos ver el tercer

cambio presente en myfile.

1 $ cat myfile

2 first change

3 second change

4 third change

Para que el tercer cambio este en el fichero, hacemos una fusion usual de las dos cabezas.

1 $ hg merge

2 merging myfile

3 0 files updated, 1 files merged, 0 files removed, 0 files unresolved4 (branch merge, don’t forget to commit)

5 $ hg commit -m ’merged backout with previous tip’

6 $ cat myfile

7 first change

8 third change

Despues de eso, el historial grafica de nuestro repositorio luce como la figura 9.4.

100

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 111/204

primer cambio

segundo cambio

tercer cambioreversar

segundo cambio

fusión

manual

Figura 9.4: Fusion manual de un retroceso

9.3.5. Por que “hg backout” hace lo que hace

Esta es una descripcion corta de como trabaja la orden “hg backout”.

1. Se asegura de que el directorio de trabajo es “limpio”, esto es, que la salida de “hg status” deberıa ser vacıa.

2. Recuerda el padre actual del directorio de trabajo. A este conjunto de cambio lo llamaremos orig

3. Hace el equivalente de un “hg update” para sincronizar el directorio de trabajo con el conjunto de cambios que

usted quiere retroceder. Lo llamaremos backout

4. Encuentra el padre del conjunto de cambios. Lo llamaremos parent.

5. Para cada fichero del conjunto de cambios que el retroceso afecte, hara el equivalente a “hg revert -r

parent” sobre ese fichero, para restaurarlo a los contenidos que tenıa antes de que el conjunto de cambios fuera

consignado.

6. Se consigna el resultado como un nuevo conjunto de cambios y tiene a backout como su padre.

7. Si especifica --merge en la lınea de comandos, se fusiona con orig, y se consigna el resultado de la fusion.

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 despues usar laa opcion --reverse de la orden patch para reversar el efecto del cambio

sin molestar el directorio de trabajo. Suena mucho mas simple, pero no funcionarıa bien ni de cerca.

La razon por la cual “hg backout” hace una actualizacion, una consignacion, una fusion y otra consignacion es

para dar a la maquinaria de fusion la mayor oportunidad de hacer un buen trabajo cuando se trata con todos los cambios

entre el cambio que esta retrocediendo y la punta actual.

101

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 112/204

Si esta retrocediendo un conjunto de cambios que esta a unas 100 atras en su historial del proyecto, las posibili-

dades de que una orden patch sea capaz de ser aplicada a un diff reverso, claramente no son altas, 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 chachara, vea una discusion de la orden patch en 12.4). Adicionalmente, la maquinaria de fusion

de Mercurial manejara ficheros y directorios renombrados, cambios de permisos, y modificaciones a ficheros binarios,

nada de lo cual la orden patch puede manejar.

9.4. Cambios que nunca debieron ocurrir

En la mayorıa de los casos, la orden “hg backout” es exactamente lo que necesita para deshacer los efectos de

un cambio. Deja un registro permanente y exacto de lo que usted hizo, cuando se consign o el conjunto de cambios

original y cuando se hizo la limpieza.

En ocasiones particulares, puede haber consignado un cambio que no deberıa estar de ninguna forma en el repos-

itorio. Por ejemplo, serıa muy inusual, y considerado como una equivocacion, consignar los ficheros objeto junto con

el codigo fuente. Los ficheros objeto no tienen valor intr ınseco y son grandes, por lo tanto aumentan el tamano del

repositorio y la cantidad de tiempo que se emplea al clonar o jalar cambios.

Antes de discutir las opciones que tiene si consigno cambio del tipo “bolsa de papel deschable” (el tipo que es

tan malo que le gustarıa colocarse una bolsa de papel desechable en su cabeza), 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. La unica excepcion

es cuando usted ha acabado de consignar un cambio y este no ha sido publicado o jalado en otro repositorio. Ahı es

cuando puede usar la orden “hg rollback” con seguridad, como detalle en la seccion 9.1.2.

Despues de que usted haya publicado un cambio en otro repositorio, usted podr   ıa usar la orden “hg rollback”

para hacer que en su copia local desaparezca el cambio, pero no tendra las consecuencias que desea. El cambio

estara presente en un repositorio remoto, y reaparecera en su repositorio local la proxima vez que jale

Si una situacion como esta se presenta, y usted sabe en que repositorios su mal cambio se ha propagado, puede

intentar deshacerse del conjunto de cambios de todos los repositorios en los que se pueda encontrar. Esta por supuesto,

no es una solucion satisfactoria: si usted deja de hacerlo en un solo repositorio, mientras est e eliminandolo, el cambio

todavıa estara “allı afuera”, y podrıa propagarse mas tarde.

Si ha consignado uno o mas cambios despu´ es del cambio que desea desaparecer, sus opciones son aun mas reduci-

das. Mercurial no provee una forma de “cabar un hueco” en el historial, dejando los conjuntos de cambios intactos.XXX This needs filling out. The hg-replay script in the examples directory works, but doesn’t handle merge

changesets. Kind of an important omission.

9.4.1. Como protegerse de cambios que han “escapado”

Si ha consignado cambios a su repositorio local y estos han sido publicados o jalados en cualquier otro sitio, no es

necesariamente un desastre. Puede protegerse de antemano de ciertas clases de conjuntos de cambios malos. Esto es

particularmente sencillo si su equipo de trabajo jala cambios de un repositorio central.

Al configurar algunos ganchos en el repositorio central para validar conjuntos de cambios (ver capıtulo 10), puede

prevenir la publicacion automaticamente de cierta clase de cambios malos. Con tal configuracion, cierta clase de

conjuntos de cambios malos tenderan naturalmente a“morir” debido a que no pueden propagarse al repositorio central.

Esto sucedera sin necesidad de intervencion explıcita.

Por ejemplo, un gancho de cambios de entrada que verifique que un conjunto de cambios compila, puede prevenirque la gente “rompa la compilacion” inadvertidamente.

9.5. Al encuentro de la fuente de un fallo

Aunque es muy bueno poder retroceder el conjunto de cambios que origino un fallo, se requiere que usted sepa

cual conjunto de cambios retroceder. Mercurial brinda una orden invaluable, llamada “ hg bisect”, que ayuda a

102

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 113/204

automatizar este proceso y a alcanzarlo muy eficientemente.

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. No tiene que saber que pieza de codigo introdujo el cambio, pero si

requiere que sepa como probar la existencia de un fallo. La orden “hg bisect” usa su prueba para dirigir su busqueda

del conjunto de cambios que introdujo el codigo causante del fallo.

A continuacion un conjunto de escenarios que puede ayudarle a entender como puede aplicar esta orden.

La version mas reciente de su programa tiene un fallo que usted recuerda no estaba hace unas semanas, pero no

sabe cuando fue introducido. En este caso, su prueba binaria busca la presencia de tal fallo.

Usted arreglo un fallo en un apurto, y es hora de dar por cerrado el caso en la base de datos de fallos de su

equipo de trabajo. La base de datos de fallos requiere el ID del conjunto de cambios que permita dar por cerrado

el caso, pero usted no recuerda que conjunto de cambios arreglo tal fallo. De nuevo la prueba binaria revisa la

presencia del fallo.

Su programa funciona correctamente, pero core 15 % mas lento que la ultima vez que lo midio. Usted desea

saber que conjunto de cambios introdujo esta disminucion de desempeno. En este caso su prueba binaria mide

el desempeno de su programa, para ver donde es “rapido” y donde es “lento”.

Los tamanos de los componentes del proyecto que usted lleva se expandieron recientemente, y sospecha que

algo cambio en la forma en que se construye su proyecto.

Para estos ejemplos deberıa ser claro que la orden “hg bisect” es util no solamente para encontrar la fuente de

los fallos. Puede usarla para encontrar cualquier “propiedad emergente” de un repositorio (Cualquier cosa que usted

no pueda encontrar con una busqueda de texto sencilla sobre los ficheros en el arbol) para la cual pueda escribir una

prueba binaria.

A continuacion introduciremos algo terminologıa, para aclarar que partes del proceso de busqueda son su respon-

sabilidad y cuales de Mercurial. Una prueba es algo que usted  ejecuta cuando “hg bisect” elige un conjunto de

cambios. Un sondeo es lo que “hg bisect” ejecuta para decidir si una revision es buena. Finalmente, usaremos la

palabra “biseccionar’, en frases como “buscar con la orden “hg bisect””.

Una forma sencilla de automatizar el proceso de busqueda serıa probar cada conjunto de cambios. Lo cual escala

muy poco. Si le tomo diez minutos hacer pruebas sobre un conjunto de cambios y tiene 10.000 conjuntos de cambios

en su repositorio, esta aproximacion exhaustiva tomarıa en promedio 35 d   ıas para encontrar el conjunto de cambios

que introdujo el fallo. Incluso si supiera que el fallo se introdujo en un de los ultimos 500 conjuntos de cambios y

limitara la busqueda a ellos, estarıa tomabdi mas de 40 horas para encontrar al conjunto de cambios culpable.La orden “hg bisect” usa su conocimiento de la “forma” del historial de revisiones de su proyecto para hacer

una busqueda proporcional al logaritmo del numero de conjunto de cambios a revisar (el tipo de busqueda que realiza

se llama busqueda binaria). Con esta aproximacion, el buscar entre 10.000 conjuntos de cambios tomara menos de

3 horas, incluso a diez minutos por prueba (La b usqueda requerira cerca de 14 pruebas). Al limitar la busqueda a la

ultima centena de conjuntos de cambios, tomara a lo sumo una hora (Apenas unas 7 pruebas).

La orden “hg bisect” tiene en cuenta la naturaleza “ramificada” del historial de revisiones del proyecto con

Mercurial, ası que no hay problemas al tratar con ramas, fusiones o cabezas multiples en un repositorio. Puede evitar

ramas enteras de historial con un solo sondeo.

9.5.1. Uso de la orden “hg bisect”

A continuacion un ejemplo de “hg bisect” en accion.

Nota: En las versiones 0.9.5 y anteriores de Mercurial, “hg bisect” no era una

orden incluıda en la distribucion principal: se ofrecıa como una extension de Mer-

curial. Esta seccion describe la orden embebida y no la extension anterior.

Creamos un repostorio para probar el comando “hg bisect” de forma aislada

1 $ hg init mybug

2 $ cd mybug

103

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 114/204

Simularemos de forma sencilla un proyecto con un fallo: haremos cambios triviales en un ciclo, e indicaremos que

un cambio especıfico sea el “fallo”. Este ciclo crea 35 conjuntos de cambios, cada uno a nade un unico fichero al

repositorio. Representaremos nuestro “fallo” con un fichero que contiene el texto “tengo un gub”.

1 $ buggy_change=22

2 $ f o r ( ( i = 0 ; i < 3 5 ; i + + ) ) ; d o

3

> if [[ $i = $buggy_change ]]; then4 > echo ’i have a gub’ > myfile$i

5 > hg commit -q -A -m ’buggy changeset’

6 > else

7 > echo ’nothing to see here, move along’ > myfile$i

8 > hg commit -q -A -m ’normal changeset’

9 > fi

10 > done

A continuacion observaremos como usar la orden “hg bisect”. Podemos usar el mecanismo de ayuda embebida

que trae Mercurial.

1 $ hg help bisect

2 hg bisect [-gbsr] [REV]3

4 subdivision search of changesets

5

6 This command helps to find changesets which introduce problems.

7 To use, mark the earliest changeset you know exhibits the problem

8 as bad, then mark the latest changeset which is free from the

9 problem as good. Bisect will update your working directory to a

10 revision for testing. Once you have performed tests, mark the

11 working directory as bad or good and bisect will either update to

12 another candidate changeset or announce that it has found the bad

13 revision.

14

15 options:16

17 -r --reset reset bisect state

18 -g --good mark changeset good

19 -b --bad mark changeset bad

20 -s --skip skip testing changeset

21 -U --noupdate do not update to target

22

23 use "hg -v help bisect" to show global options

La orden “hg bisect” trabaja en etapas, de la siguiente forma:

1. Usted ejecuta una prueba binaria.

Si la prueba es exitosa, usted se lo indicara a “hg bisect” ejecutando la orden “hg bisect good”.

Si falla, ejecutara la orden “hg bisect --bad”.

2. La orden usa su informacion para decidir que conjuntos de cambios deben probarse a continuacion.

3. Actualiza el directorio de trabajo a tal conjunto de cambios y el proceso se lleva a cabo de nuevo.

104

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 115/204

El proceso termina cuando “hg bisect” identifica un unico conjunto de cambios que marca el punto donde se encon-

tro la transicion de “exitoso” a “fallido”.

Para comenzar la busqueda, es indispensable ejecutar la orden “hg bisect --reset”.

1 $ if hg -v | head -1 | grep -e "version 0.*"

2 > then

3

#On mercurial 1.0 --init disappeared4 > hg bisect --init

5 > fi

En nuestro caso, la prueba binaria es sencilla: revisamos si el fichero en el repositorio contiene la cadena “tengo

un gub”. Si la tiene, este conjunto de cambios contiene aquel que “caus o el fallo”. Por convencion, un conjunto de

cambios que tiene la propiedad que estamos buscando es “malo”, mientras que el otro que no la tiene es “bueno”.

En la mayorıa de casos, la revision del directorio actual (usualmente la punta) exhibe el problema introducido por

el cambio con el fallo, por lo tanto la marcaremos como “mala”.

1 $ hg bisect --bad

Nuestra proxima tarea es nominar al conjunto de cambios que sabemos no tiene el fallo; la orden “hg bisect”

“acotara” su busqueda entre el primer par de conjuntos de cambios buenos y malos. En nuestro caso, sabemos que larevision 10 no tenıa el fallo. (Mas adelante dire un poco mas acerca de la eleccion del conjunto de cambios “bueno”.)

1 $ hg bisect --good 10

2 Testing changeset 22:ec1c6526e0eb (24 changesets remaining, ˜4 tests)

3 0 files updated, 0 files merged, 12 files removed, 0 files unresolved

Note que esta orden mostro algo.

Nos dijo cuantos conjuntos de cambios debe considerar antes de que pueda identifica aquel que introdujo el

fallo, y cuantas pruebas se requeriran.

Actualizo el directorio de trabajo al siguiente conjunto de cambios, y nos dijo que conjunto de cambios esta eval-

uando.

Ahora ejecutamos nuestra prueba en el directorio de trabajo. Usamos la orden grep para ver si nuestro fichero

“malo” esta presente en el directorio de trabajo. Si lo esta, esta revision es mala; si no esta revision es buena.

1 $ if grep -q ’i have a gub’ *2 > then

3 > result=bad

4 > else

5 > result=good

6 > fi

7 $ echo this revision is $result

8 this revision is bad

9 $ hg bisect --$result

10 Testing changeset 16:8fb73e2ea5f9 (12 changesets remaining, ˜3 tests)

11 0 files updated, 0 files merged, 6 files removed, 0 files unresolved

Esta prueba luce como candidata perfecta para automatizarse, por lo tanto la convertimos en una funcion de interfaz

de comandos.

105

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 116/204

1 $ mytest() {2 > if grep -q ’i have a gub’ *3 > then

4 > result=bad

5 > else

6 > result=good7 > fi

8 > echo this revision is $result

9 > hg bisect --$result

10 > }

Ahora podemos ejecutar un paso entero de pruebas con un solo comando, mytest.

1 $ mytest

2 this revision is good

3 Testing changeset 19:ffbbdeaade97 (6 changesets remaining, ˜2 tests)

4 3 files updated, 0 files merged, 0 files removed, 0 files unresolved

Unas invocaciones mas de nuestra prueba, y hemos terminado.

1 $ mytest

2 this revision is good

3 Testing changeset 20:c0c13593daf1 (3 changesets remaining, ˜1 tests)

4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

5 $ mytest

6 this revision is good

7 Testing changeset 21:d70e5938b22b (2 changesets remaining, ˜1 tests)

8 1 files updated, 0 files merged, 0 files removed, 0 files unresolved

9 $ mytest

10 this revision is good

11 The first bad revision is:

12 changeset: 22:ec1c6526e0eb

13 user: Bryan O’Sullivan <[email protected]>

14 date: Tue Feb 10 18:23:14 2009 +0000

15 summary: buggy changeset

16

Aunque tenıamos unos 40 conjuntos de cambios en los cuales buscar, la orden “hg bisect” nos permitio encontrar

el conjunto de cambios que introdujo el “fallo” con solo cinco pruebas. Porque el numero de pruebas que la orden “hg

bisect” ejecuta crece logarıtmicamente con la cantidad de conjuntos de cambios a buscar, la ventaja que esto tiene

frente a la busqueda por“fuerza bruta” crece con cada conjunto de cambios que usted adicione.

9.5.2. Limpieza despues de la busqueda

Cuando haya terminado de usar la orden “hg bisect” en un repositorio, puede usar la orden “hg bisect reset”

para deshacerse de la informacion que se estaba usando para lograr la busqueda. Lar orden no usa mucho espacio,

ası que no hay problema si olvida ejecutar la orden. En todo caso, “hg bisect” no le permitira comenzar una nueva

busqueda sobre el repositorio hasta que no aplique “hg bisect reset”.

1 $ hg bisect --reset

106

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 117/204

9.6. Consejos para encontrar fallos efectivamente

9.6.1. Dar una entrada consistente

La orden “hg bisect” requiere que usted ofrezca un reporte correcto del resultado de cada prueba que aplique.

Si usted le dice que una prueba falla cuando en realidad era acertada, podr   ıa detectar la inconsistencia. Si puede

identificar una inconsistencia en sus reportes, le dira que un conjunto de cambios particular es a la vez bueno y malo.

Aunque puede no hacerlo; estarıa tratando de reportar un conjunto de cambios como el responsable de un fallo aunque

no lo sea.

9.6.2. Automatizar tanto como se pueda

Cuando comence a usar la orden “hg bisect”, intente ejecutar algunas veces las pruebas a mano desde la lınea

de comandos. Es una aproximacion a la cual no esta acostumbrado. Despues de algunos intentos, me di cuenta que

estaba cometiendo tantas equivocaciones que tenıa que comenzar de nuevo con mis busquedas varias veces antes de

llegar a los resultados deseados.

Mi problema inicial al dirigir a la orden “hg bisect” manualmente ocurrieron incluso con busquedas en reposito-

rios pequenos; si el problema que esta buscando es mas sutil, o el numero de pruebas que “hg bisect” debe aplicar,

la posibilidad de errar es mucho mas alta. Una vez que comence a automatizar mis pruebas, obtuve mejores resultados.

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”.

En mi tutorial de ejemplo anterior, la orden grep busca el sıntoma, y la construccion if toma el resultado de esta

prueba y verifica que siempre alimentamos con los mismos datos a la orden “hg bisect”. La funcion mytest los une

de una forma reproducible, logrando que cada prueba sea uniforme y consistente.

9.6.3. Verificar los resultados

Dado que la salida de la busqueda de “hg bisect” es tan buena como los datos ofrecidos por usted, no confıe en

esto como si fuera la verdad absoluta. 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 reporto como la primera version erronea. Su prueba deberıa dar un reporte de

fallo.

El conjunto de cambios padre (cada padre, si es una fusion). Su prueba deberıa reportar este(os) conjunto(s) de

cambios como bueno(s).

Un hijo del conjunto de cambios. Su prueba deberıa reportar al conjunto de cambios hijo como malo.

9.6.4. Tener en cuenta la interferencia entre fallos

Es posible que su busqueda de un fallo pueda viciarse por la presencia de otro. Por ejemplo, digamos que su

programa se revienta en la revision 100, y que funciono correctamente en la revision 50. Sin su conocimiento, alguien

introdujo un fallo con consecuencias grandes en la revision 60, y lo arreglo en la revision 80. Sus resultados estarıandistorcionados de una o muchas formas.

Es posible que este fallo “enmascare” completamente al suyo, y que podrıa haberse revelado antes de que su propio

fallo haya tenido oportunidad de manifestarse. Si no puede saltar el otro fallo (por ejemplo, este evita que su proyecto

se arme o compile), y de esta forma no se pueda revisar si su fallo est e presente en un conjunto particular de cambios,

la orden “hg bisect” no podra ayudarle directamente. En cambio, puede marcar este conjunto de cambios como al

ejecutar “hg bisect --skip”.

107

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 118/204

Un problema distinto podrıa surgir si su prueba de la presencia de un fallo no es suficientemente especıfica. Si

usted busca “mi programa se revienta”, entonces tanto su fallo como el otro fallo sin relacion que terminan presentando

sıntomas distintos, podrıa terminar confundiendo a “hg bisect”.

Otra situacion en la cual serıa de mucha utilidad emplear a “hg bisect --skip” surge cuando usted no puede

probar una revision porque su proyecto estaba en una situacion de rompimiento y por lo tanto en un estado en el

cual era imposible hacer la prueba en esa revision, tal vez porque alguien consigno un cambio que hacıa imposible la

construccion del proyecto.

9.6.5. Acotar la busqueda perezosamente

Elegir los primeros “buenos” y “malos” conjuntos de cambios que marcaran los lımites de su busqueda en general

es sencillo, pero vale la pena discutirlo. Desde la perspectiva de “ hg bisect”, el conjunto de cambios “mas nuevo”

por convencion es el “malo”, y el otro conjunto de cambios es el “bueno”.

Si no recuerda cual podrıa ser el cambio “bueno”, para informar a “hg bisect”, podrıa hacer pruebas aleatorias

en el peor de los casos. 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 esta presente) y aquellos en los cuales otro fallo puede

enmascararlo (como se discutio anteriormente).

Incluso si termina “muy atras” por miles de conjuntos de cambios o meses de historial, solamente esta ra adicio-

nando unas pruebas contadas para “hg bisect”, gracias al comportamiento logarıtmico.

108

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 119/204

Capıtulo 10

Manejo de eventos en repositorios mediante

ganchos

Mercurial ofrece un poderoso mecanismo para permitirle a usted automatizar la ejecucion de acciones en respuesta

a eventos que ocurran en un repositorio. En algunos casos, usted puede controlar incluso la respuesta de Mercurial a

dichos eventos.

Mercurial usa el termino gancho para identificar estas acciones. Los ganchos son conocidos como “disparadores”

en algunos sistemas de control de revisiones, pero los dos nombres se refieren al mismo concepto.

10.1. Vistazo general de ganchos en Mercurial

A continuacion se encuentra una breve lista de los ganchos que Mercurial soporta. Volveremos a cada uno de estos

ganchos con mas detalle despues, en la seccion 10.8.

changegroup Es ejecutado luego de que un grupo de conjuntos de cambios ha sido tra ıdo al repositorio desde algun otro sitio.

commit Es ejecutado despues de la creacion de un conjunto de cambios en el repositorio local.

incoming Es ejecutado una vez por cada conjunto de cambios traıdo al repositorio desde otra ubicacion. Note la diferencia

respecto al gancho changegroup, que es ejecutado una vez por cada grupo de conjuntos de cambios que se

traiga.

outgoing Es ejecutado luego de que un grupo de conjuntos de cambios ha sido transmitido desde el repositorio.

prechangegroup Es ejecutado antes de iniciar la recepcion de un grupo de conjuntos de cambios en el repositorio.

precommit De control. Es ejecutado antes de iniciar una consignacion.

preoutgoing De control. Es ejecutado antes de iniciar la transmision de un grupo de conjuntos de cambios desde el repositorio.

pretag De control. Es ejecutado antes de crear una etiqueta.

retxnchangegroupDe control. Es ejecutado despu

´es de haber recibido un grupo de conjuntos de cambios en el repositorio local,pero antes de que la transaccion se complete y los cambios sean permanentes dentro del repositorio.

pretxncommit De control. Es ejecutado luego de la creacion de un conjunto de cambios en el repositorio local, pero antes de

que la transaccion que hace permanente el cambio sea completada.

preupdate De control. Es ejecutado antes de iniciar una actualizacion o fusion en el directorio de trabajo.

tag Es ejecutado despues de la creacion de una etiqueta.

109

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 120/204

update Es ejecutado despues de que termina una actualizacion o una fusion.

Cada uno de los ganchos cuya descripcion empieza con la frase “de control” tiene la facultad de determinar si una

actividad puede continuar. Si el gancho se ejecuta con exito, la actividad puede continuar; si falla, o bien la actividad

no es permitida, o se deshacen los cambios que se puedan haber llevado a cabo, dependiendo del gancho involucrado.

10.2. Ganchos y seguridad

10.2.1. Los ganchos se ejecutan con sus privilegios de usuario

Cuando usted ejecuta un comando de Mercurial en un repositorio, y el comando causa la ejecucion de un gancho,

dicho gancho se ejecuta en su sistema, en su cuenta de usuario, con sus privilegios. Ya que los ganchos son elementos

arbitrarios de codigo ejecutable, usted deberıa tratarlos con un nivel adecuado de desconfianza. No instale un gancho

a menos en que conf ıe en quien lo creo y en lo que el gancho hace.

En algunos casos, usted puede estar expuesto a ganchos que usted no instal o. Si usted usa Mercurial en un sistema

extrano, tenga en cuenta que Mercurial ejecutara los ganchos definidos en el fichero hgrc.

Si esta trabajando con un repositorio propiedad de otro usuario, Mercurial podra ejecutar los ganchos definidos

en el repositorio de dicho usuario, pero los ejecutara como “usted”. Por ejemplo, si usted jala (“hg pull”) desde ese

repositorio, y el .hg/hgrc define un gancho saliente (outgoing), dicho gancho se ejecuta bajo su cuenta de usuario,

aun cuando usted no es el propietario del repositorio.

Nota: Esto solo aplica si usted esta jalando desde un repositorio en un sistema

de ficheros local o de red. Si esta jalando a traves de http o ssh, cualquier gan-

cho saliente (outgoing) se ejecutara bajo la cuenta que esta ejecutando el proceso

servidor, en el servidor.

XXX Para ver que ganchos han sido definidos en un repositorio, use el comando “ hg config hooks”. Si usted

esta trabajando en un repositorio, pero comunicandose con otro que no le pertenece (por ejemplo, usando “hg pull”

o “hg incoming”), recuerde que los ganchos que debe considerar son los del otro repositorio, no los del suyo.

10.2.2. Los ganchos no se propagan

En Mercurial, no se hace control de revisiones de los ganchos, y no se propagan cuando usted clona, o jala de, un

repositorio. El motivo para esto es simple: un gancho es codigo ejecutable arbitrario. Se ejecuta bajo su identidad, consu nivel de privilegios, en su maquina.

Serıa extremadamente descuidado de parte de cualquier sistema distribuido de control de revisiones el implementar

control de revisiones para ganchos, ya que esto ofrecer ıa maneras f acilmente aprovechables de subvertir las cuentas

de los usuarios del sistema de control de revisiones.

Ya que Mercurial no propaga los ganchos, si usted esta colaborando con otras personas en un proyecto comun,

no deberıa asumir que ellos estan usando los mismos ganchos para Mercurial que usted usa, o que los de ellos est an

configurado correctamente. Usted deberıa documentar los ganchos que usted espera que la gente use.

En una intranet corporativa, esto es algo mas f acil de manejar, ya que usted puede, por ejemplo, proveer una

instalacion “estandar” de Mercurial en un sistema de ficheros NFS, y usar un fichero hgrc global para definir los

ganchos que veran todos los usuarios. Sin embargo, este enfoque tiene sus lımites; vea mas abajo.

10.2.3. Es posible hacer caso omiso de los ganchos

Mercurial le permite hacer caso omiso de la deficinion de un gancho, a traves de la redefinicion del mismo. Usted

puede deshabilitar el gancho fijando su valor como una cadena vacıa, o cambiar su comportamiento como desee.

Si usted instala un fichero hgrc a nivel de sistema o sitio completo que define algunos ganchos, debe entender que

sus usuarios pueden deshabilitar o hacer caso omiso de los mismos.

110

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 121/204

10.2.4. Asegurarse de que ganchos crıticos sean ejecutados

Algunas veces usted puede querer hacer respetar una polıtica, y no permitir que los demas sean capaces de evitarla.

Por ejemplo, usted puede tener como requerimiento que cada conjunto de cambios debe pasar un riguroso conjunto de

pruebas. Definir este requerimientos a traves de un gancho en un fichero hgrc global no servira con usuarios remotos

en computadoras portatiles, y por supuesto que los usuarios locales pueden evitar esto a voluntad haciendo caso omiso

del gancho.

En vez de eso, usted puede definir las polıticas para usar Mercurial de tal forma que se espere que los usuar-

ios propaguen los cambios a traves de un servidor “canonico” bien conocido que usted ha asegurado y configurado

apropiadamente.

Una manera de hacer esto es a traves de una combinacion de ingenierıa social y tecnologıa. Cree una cuenta de

acceso restringido; los usuarios pueden empujar cambios a traves de la red a los repositorios administrados por esta

cuenta, pero no podran ingresar a dicha cuenta para ejecutar ordenes en el interprete de comandos. En este escenario,

un usuario puede enviar un conjunto de cambios que contenga la porquerıa que el desee.

Cuando alguien empuja un conjunto de cambios al servidor del que todos jalan, el servidor probara el conjunto de

cambios antes de aceptarlo como permanente, y lo rechazara si no logra pasar el conjunto de pruebas. Si la gente solo

 jala cambios desde este servidor de filtro, servira para asegurarse de que todos los cambios que la gente jala han sido

examinados automaticamente

10.3. Precauciones con ganchos pretxn en un repositorio de acceso com-partido

Si usted desea usar ganchos para llevar a cabo autom aticamente algun trabajo en un repositorio al que varias

personas tienen acceso compartido, debe tener cuidado con la forma de hacerlo.

Mercurial solo bloquea un repositorio cuando esta escribiendo al mismo, y solo las partes de Mercurial que escriben

al repositorio le prestan atencion a los bloqueos. Los bloqueos de escritura son necesarios para evitar que multiples

escritores simultaneos interfieran entre sı, corrompiendo el repositorio.

Ya que Mercurial tiene cuidado con el orden en que lee y escribe datos, no necesita adquirir un bloqueo cuando

desea leer datos del repositorio. Las partes de Mercurial que leen del repositorio nunca le prestan atenci on a los

bloqueos. Este esquema de lectura libre de bloqueos incremententa en gran medida el desempeno y la concurrencia.

Sin embargo, para tener un gran desempeno es necesario hacer sacrificios, uno de los cuales tiene el potencial de

causarle problemas a menos de que usted este consciente de el. Describirlo requiere algo de detalle respecto a comoMercurial anade conjuntos de cambios al repositorio y como lee esos cambios de vuelta.

Cuando Mercurial escribe metadatos, los escribe directamente en el fichero de destino. Primero escribe los datos

del fichero, luego los datos del manifiesto (que contienen punteros a los nuevos datos del fichero), luego datos de la

bitacora de cambios (que contienen punteros a los nuevos datos del manifiesto). Antes de la primera escritura a cada

fichero, se guarda un registro de donde estaba el final de fichero en su registro de transacciones. Si la transacci on

debe ser deshecha, Mercurial simplemente trunca cada fichero de vuelta al tamano que tenıa antes de que empezara la

transaccion.

Cuando Mercurial lee metadatos, lee la bitacora de cambios primero, y luego todo lo demas. Como un lector solo

accedera a las partes del manifiesto o de los metadatos de fichero que el puede ver en la bitacora de cambios, nunca

puede ver datos parcialmente escritos.

Algunos ganchos de control (pretxncommit y pretxnchangegroup ) se ejecutan cuando una transaccion esta casi

completa. Todos los metadatos han sido escritos, pero Mercurial aun puede deshacer la transaccion y hacer que los

datos recien escritos desaparezcan.Si alguno de estos ganchos permanece en ejecucion por mucho tiempo, abre una ventana de tiempo en la que un

lector puede ver los metadatos de conjuntos de cambios que aun no son permanentes y que no deberıa considerarse

que esten “realmante ahı”. Entre mas tiempo tome la ejecucion del gancho, mas tiempo estara abierta esta ventana.

111

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 122/204

10.3.1. Ilustracion del problema

En principio, un buen uso del gancho pretxnchangegroup serıa ensamblar y probar automaticamente todos los

cambios entrantes antes de que sean aceptados en un repositorio central. Esto le permitirıa a usted garantizar que nadie

pueda empujar cambios que “rompan el ensamblaje”. Pero si un cliente puede jalar cambios mientras estan siendo

probados, la utilidad de esta prueba es nula; alguien confiado puede jalar cambios sin probar, lo que potencialmente

podrıa romper su proceso de ensamblaje.

La respuesta tecnica mas segura frente a este retos es montar dicho repositorio “guardian” como unidireccional.

Permita que reciba cambios desde el exterior, pero no permita que nadie jale cambios de el (use el gancho preoutgoing

para bloquear esto). Configure un gancho changegroup para que si el ensamblaje o prueba tiene exito, el gancho em-

puje los nuevos cambios a otro repositorio del que la gente pueda jalar.

En la practica, montar un cuello de botella centralizado como este a menudo no es una buena idea, y la visibilidad

de las transacciones no tiene nada que ver con el problema. A medida que el tamano de un proyecto—y el tiempo

que toma ensamblarlo y probarlo—crece, usted se acerca rapidamente a un lımite con este enfoque “pruebe antes de

comprar”, en el que tiene mas conjuntos de cambios a probar que tiempo para ocuparse de ellos. El resultado inevitable

es frustracion para todos los que esten involucrados.

Una aproximacion que permite manejar mejor el crecimiento es hacer que la gente ensamble y pruebe antes de

empujar, y ejecutar el ensamble y pruebas automaticas centralmente despu´ es de empujar, para asegurarse de que todo

este bien. La ventaja de este enfoque es que no impone un lımite a la rata en la que un repositorio puede aceptar

cambios.

10.4. Tutorial corto de uso de ganchos

Escribir un gancho para Mercurial es f acil. Empecemos con un gancho que se ejecute cuando usted termine un

“hg commit”, y simplemente muestre el hash del conjunto de cambios que usted acaba de crear. El gancho se lla-

mara commit.

1 $ hg init hook-test

2 $ cd hook-test

3 $ echo ’[hooks]’ >> .hg/hgrc

4 $ echo ’commit = echo committed $HG_NODE’ >> .hg/hgrc

5 $ cat .hg/hgrc

6 [hooks]

7 commit = echo committed $HG_NODE

8 $ e c h o a > a

9 $ hg add a

10 $ hg commit -m ’testing commit hook’

11 committed 233120f5d09c76e782c6ea86ccee729e735bf48f

Figura 10.1: Un gancho simple que se ejecuta al hacer la consignacion de un conjunto de cambios

Todos los ganchos siguen el patron del ejemplo 10.1. Usted puede anadir una entrada a la seccion [hooks] de su

fichero hgrc. A la izquierda esta el nombre del evento respecto al cual dispararse; a la derecha est a la accion a llevar

a cabo. Como puede ver, es posible ejecutar cualquier orden de la l ınea de comandos en un gancho. Mercurial le pasainformacion extra al gancho usando variables de entorno (busque HG NODE en el ejemplo).

10.4.1. Llevar a cabo varias acciones por evento

A menudo, usted querra definir mas de un gancho para un tipo de evento particular, como se muestra en el ejem-

plo 10.2. Mercurial le permite hacer esto anadiendo una extensi ´ on al final del nombre de un gancho. Usted extiende

112

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 123/204

el nombre del gancho poniendo el nombre del gancho, seguido por una parada completa (el caracter “ .”), seguido

de algo mas de texto de su eleccion. Por ejemplo, Mercurial ejecutara tanto commit.foo como commit.bar cuando

ocurra el evento commit.

1 $ echo ’commit.when = echo -n "date of commit: "; date’ >> .hg/hgrc

2 $ echo a >> a

3 $ hg commit -m ’i have two hooks’4 committed df4f3f8972104d2a43d114e51edd05719efccd42

5 date of commit: Tue Feb 10 18:23:23 GMT 2009

Figura 10.2: Definicion de un segundo gancho commit

Para dar un orden bien definido de ejecucion cuando hay multiples ganchos definidos para un evento, Mercurial

ordena los ganchos de acuerdo a su extension, y los ejecuta en dicho orden. En el ejemplo de arribam commit.bar se

ejecutara antes que commit.foo, y commit se ejecutara antes de ambos.

Es una buena idea usar una extension descriptiva cuando usted define un gancho. Esto le ayudara a recordar para

que se usa el gancho. Si el gancho falla, usted recibir a un mensaje de error que contiene el nombre y la extensi on del

gancho, ası que usar una extension descriptiva le dara una pista inmediata de porque el gancho fallo (vea un ejemplo

en la seccion 10.4.2).

10.4.2. Controlar cuando puede llevarse a cabo una actividad

En los ejemplos anteriores, usamos el gancho commit, que es ejecutado despues de que se ha completado una

consignacion. Este es uno de los varios ganchos que Mercurial ejecuta luego de que una actividad termina. Tales

ganchos no tienen forma de influenciar la actividad como tal.

Mercurial define un numero de eventos que ocurren antes de que una actividad empiece; o luego de que empiece,

pero antes de que termine. Los ganchos que se disparan con estos eventos tienen la capacidad adicional de elegir si la

actividad puede continuar, o si su ejecucion es abortada.

El gancho pretxncommit se ejecuta justo antes de que una consignacion se ejecute. En otras palabras, los metadatos

que representan el conjunto de cambios han sido escritos al disco, pero no se ha terminado la transaccion. El gancho

pretxncommit tiene la capacidad de decidir si una transaccion se completa, o debe deshacerse.Si el gancho pretxncommit termina con un codigo de salida de cero, se permite que la transaccion se complete; la

consignacion termina; y el gancho commit es ejecutado. Si el gancho pretxncommit termina con un codigo de salida

diferente de cero, la transaccion es revertida; los metadatos representando el conjunto de cambios son borrados; y el

gancho commit no es ejecutado.

El gancho en el ejemplo 10.3 revisa si el mensaje de consignacion contiene el ID de algun fallo. Si lo contiene, la

consignacion puede continuar. Si no, la consignacion es cancelada.

10.5. Escribir sus propios ganchos

Cuando usted escriba un gancho, puede encontrar util el ejecutar Mercurial o bien pasandole la opcion -v, o con el

valor de configuracion verbose fijado en “true” (verdadero). Cuando lo haga, Mercurial imprimira un mensaje antes

de llamar cada gancho.

10.5.1. Escoger como debe ejecutarse su gancho

Usted puede escribir un gancho que funcione como un programa normal —tıpicamente un guion de lınea de

comandos—o como una funcion de Python que se ejecuta dentro del proceso Mercurial.

Escribir un gancho como un programa externo tiene la ventaja de que no requiere ning un conocimiento del fun-

cionamiento interno de Mercurial. Usted puede ejecutar comandos Mercurial normales para obtener la informcion

113

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 124/204

1 $ cat check_bug_id

2 #!/bin/sh

3 # check that a commit comment mentions a numeric bug id

4 hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]"

5 $ echo ’pretxncommit.bug_id_required = ./check_bug_id $HG_NODE’ >> .hg/hgrc

6 $ echo a >> a

7 $ hg commit -m ’i am not mentioning a bug id’8 transaction abort!

9 rollback completed

10 abort: pretxncommit.bug_id_required hook exited with status 1

11 $ hg commit -m ’i refer you to bug 666’

12 committed d558e8617cbdf0b482db27a79d17f9a28af4701f

13 date of commit: Tue Feb 10 18:23:23 GMT 2009

Figura 10.3: Uso del gancho pretxncommit para controlar consignaciones

extra que pueda necesitar. La contraparte de esto es que los ganchos externos son mas lentos que los ganchos internos

ejecutados dentro del proceso.Un gancho Python interno tiene acceso completo a la API de Mercurial, y no se “externaliza” a otro proceso,

ası que es inherentemente mas rapido que un gancho externo. Adicionalmente es mas f acil obtener la mayorıa de

la informacion que un gancho requiere a traves de llamadas directas a la API de Mercurial que hacerlo ejecutando

comandos Mercurial.

Si se siente a gusto con Python, o requiere un alto desempeno, escribir sus ganchos en Python puede ser una buena

eleccion. Sin embargo, cuando usted tiene un gancho bastante directo por escribir y no le importa el desempe no (el

caso de la mayorıa de los ganchos), es perfectamente admisible un guion de lınea de comandos.

10.5.2. Parametros para ganchos

Mercurial llama cada gancho con un conjunto de parametros bien definidos. En Python, un parametro se pasa

como argumento de palabra clave a su funcion de gancho. Para un programa externo, los parametros son pasados

como variables de entornos.

Sin importar si su gancho esta escrito en Python o como guion de lınea de comandos, los nombres y valores de

los parametros especıficos de los ganchos seran los mismos. Un parametro booleano sera representado como un valor

booleano en Python, pero como el numero 1 (para “verdadero”) o 0 (para falso) en una variable de entorno para un

gancho externo. Si un parametro se llama foo, el argumento de palabra clave para un gancho en Python tambien se

llamara foo, mientras que la variable de entorno para un gancho externo se llamara HG FOO.

10.5.3. Valores de retorno de ganchos y control de actividades

Un gancho que se ejecuta exitosamente debe terminar con un codigo de salida de cero, si es externo, o retornar

el valor booleano “falso”, si es interno. Un fallo se indica con un codigo de salida diferente de cero desde un gancho

externo, o un valor de retorno booleano “verdadero”. Si un gancho interno genera una excepcion, se considera que el

gancho ha fallado.

Para los ganchos que controlan si una actividad puede continuar o no, cero/falso quiere decir “permitir”, mientras

que no-cero/verdadero/excepcion quiere decir “no permitir”.

10.5.4. Escribir un gancho externo

Cuando usted define un gancho externo en su fichero hgrc y el mismo es ejecutado, dicha definicion pasa a su

interprete de comandos, que hace la interpretacion correspondiente. Esto significa que usted puede usar elementos

114

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 125/204

normales del interprete en el cuerpo del gancho.

Un gancho ejecutable siempre es ejecutado con su directorio actual fijado al directorio ra ız del repositorio.

Cada parametro para el gancho es pasado como una variable de entorno; el nombre esta en mayusculas, y tiene

como prefijo la cadena “HG ”.

Con la excepcion de los parametros para los ganchos, Mercurial no define o modifica ninguna variable de entorno

al ejecutar un gancho. Es util recordar esto al escribir un gancho global que podrıa ser ejecutado por varios usuarios

con distintas variables de entorno fijadas. En situaciones con multiples usuarios, usted no deberıa asumir la existenciade ninguna variable de entorno, ni que sus valores sean los mismos que tenıan cuando usted probo el gancho en su

ambiente de trabajo.

10.5.5. 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 gan-

cho externo. El valor del gancho debe comenzar con el texto “ python:”, y continuar con el nombre completamente

cualificado de un objeto invocable que se usara como el valor del gancho.

El modulo en que vive un gancho es importado automaticamente cuando se ejecuta un gancho. Siempre que usted

tenga el nombre del modulo y la variable de entorno PYTHONPATH ajustada adecuadamente, todo deberıa funcionar sin

problemas.

El siguiente fragmento de ejemplo de un fichero hgrc ilustra la sintaxis y significado de los conceptos que

acabamos de describir.

1 [hooks]

2 commit.example = python:mymodule.submodule.myhook

Cuando Mercurial ejecuta el gancho commit.example, importa mymodule.submodule , busca el objeto invocable

llamado myhook, y lo invoca (llama).

10.5.6. Escribir un gancho interno

El gancho interno mas sencillo no hace nada, pero ilustra la estructura basica de la API1 para ganchos:

1 def myhook(ui, repo, **kwargs):

2 pass

El primer argumento para un gancho Python siempre es un objeto mercurial.ui.ui. El segundo es un objeto repos-

itorio; de momento, siempre es una instancia de mercurial.localrepo.localrepository . Despues de estos dos

argumentos estan los argumentos de palabra clave. Los argumentos que se pasen dependeran del tipo de gancho que se

este llamando, pero un gancho siempre puede ignorar los argumentos que no le interesen, relegandolos a un diccionario

de argumentos por palabras clave, como se hizo arriba con **kwargs.

10.6. Ejemplos de ganchos

10.6.1. Escribir mensajes de consignacion significativos

Es difıcil de imaginar un mensaje de consignacion util y al mismo tiempo muy corto. El simple gancho pretxncommitde la figura 10.4 evitara que usted consigne un conjunto de cambios con un mensaje de menos de 10 bytes de longitud.

1N. del T. Application Progamming Interface, Interfaz para Programacion de Aplicaciones

115

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 126/204

1 $ cat .hg/hgrc

2 [hooks]

3 pretxncommit.msglen = test ‘hg tip --template {desc} | wc -c‘ -ge 10

4 $ e c h o a > a

5 $ hg add a

6 $ hg commit -A -m ’too short’

7 transaction abort!8 rollback completed

9 abort: pretxncommit.msglen hook exited with status 1

10 $ hg commit -A -m ’long enough’

Figura 10.4: Un gancho que prohıbe mensajes de consignacion demasiado cortos

10.6.2. Comprobar espacios en blanco finales

Un uso interesante para ganchos relacionados con consignaciones es ayudarle a escribir codigo mas limpio. Un

ejemplo simple de “codigo mas limpio” es la regla de que un cambio no debe anadir lıneas de texto que contengan

“espacios en blanco finales”. El espacio en blanco final es una serie de caracteres de espacio y tabulacion que seencuentran al final de una lınea de texto. En la mayorıa de los casos, el espacio en blanco final es innecesario, ruido

invisible, pero ocasionalmente es problematico, y la gente en general prefiere deshacerse de el.

Usted puede usar cualquiera de los ganchos precommit o pretxncommit para revisar si tiene el problema de los

espacios en blanco finales. Si usa el gancho precommit, el gancho no sabra que ficheros se estan consignando, por lo

que se tendra que revisar cada fichero modificado en el repositorio para ver si tiene espacios en blanco finales. Si usted

solo quiere consignar un cambio al fichero foo, y el fichero bar contiene espacios en blanco finales, hacer la revision

en el gancho precommit evitara que usted haga la consignacion de foo debido al problem en bar. Este no parece el

enfoque adeucado.

Si usted escogiera el gancho pretxncommit, la revision no ocurrirıa sino hasta justo antes de que la transaccion

para la consignacion se complete. Esto le permitira comprobar por posibles problemas solo en los ficheros que seran

consignados. Sin embargo, si usted ingreso el mensaje de consignacion de manera interactiva y el gancho falla, la

transaccion sera deshecha; usted tendra que reingresar el mensaje de consignacion luego de que corrija el problema

con los espacios en blanco finales y ejecute “hg commit” de nuevo.

1 $ cat .hg/hgrc

2 [hooks]

3 pretxncommit.whitespace = hg export tip | (! egrep -q ’ˆ\+.*[ \t]$’)

4 $ e c h o ’ a ’ > a

5 $ hg commit -A -m ’test with trailing whitespace’

6 adding a

7 transaction abort!

8 rollback completed

9 abort: pretxncommit.whitespace hook exited with status 1

10 $ echo ’a’ > a

11 $ hg commit -A -m ’drop trailing whitespace and try again’

Figura 10.5: Un gancho simple que revisa si hay espacios en blanco finales

La figura 10.5 presenta un gancho pretxncommit simple que comprueba la existencia de espacios en blanco

finales. Este gancho es corto, pero no brinda mucha ayuda. Termina con un codigo de salida de error si un cambio

anade una lınea con espacio en blanco final a cualquier fichero, pero no muestra ninguna informacion que pueda ser

116

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 127/204

util para identificar el fichero o la lınea de texto origen del problema. Tambien tiene la agradable propiedad de no

prestar atencion a las lıneas que no sufrieron modificaciones; solo las lıneas que introducen nuevos espacios en blanco

finales causan problemas.

1 $ cat .hg/hgrc

2 [hooks]

3 pretxncommit.whitespace = .hg/check_whitespace.py4 $ e c h o ’ a ’ > > a

5 $ hg commit -A -m ’add new line with trailing whitespace’

6 a, line 2: trailing whitespace added

7 commit message saved to .hg/commit.save

8 transaction abort!

9 rollback completed

10 abort: pretxncommit.whitespace hook exited with status 1

11 $ sed -i ’s, *$,,’ a

12 $ hg commit -A -m ’trimmed trailing whitespace’

13 a, line 2: trailing whitespace added

14 commit message saved to .hg/commit.save

15 transaction abort!

16 rollback completed17 abort: pretxncommit.whitespace hook exited with status 1

Figura 10.6: Un mejor gancho para espacios en blanco finales

El ejemplo de la figura 10.6 es mucho mas complejo, pero tambien mas util. El gancho procesa un diff unificado

para revisar si alguna lınea anade espacios en blanco finales, e imprime el nombre del fichero y el numero de lınea

de cada ocurrencia. Aun mejor, si el cambio anade espacios en blanco finales, este gancho guarda el mensaje de

consignacion e imprime el nombre del fichero en el que el mensaje fue guardado, antes de terminar e indicarle a

Mercurial que deshaga la transaccion, para que uste pueda usar “hg commit -l nombre fichero” para reutilizar

el mensaje de consignacion guardado anteriormente, una vez usted haya corregido el problema.

Como anotacion final, note en la figura 10.6 el uso de la caracterıstica de edicion in-situ deperl

para eliminar losespacios en blanco finales en un fichero. Esto es lo suficientemente conciso y poderoso para que lo presente aquı.

1 perl -pi -e ’s,\s+$,,’ nombre fichero

10.7. Ganchos adicionales

Mercurial se instala con varios ganchos adicionales. Usted puede encontrarlos en el directorio hgext del arbol de

ficheros fuente de Mercurial. Si usted esta usando un paquete binario de Mercurial, los ganchos estaran ubicados en el

directorio hgext en donde su instalador de paquetes haya puesto a Mercurial.

10.7.1. acl—control de acceso a partes de un repositorio

La extension acl le permite controlar a que usuarios remotos les esta permitido empujar conjuntos de cambios a

un servidor en red. Usted puede proteger cualquier porcion de un repositorio (incluyendo el repositorio completo), de

tal manera que un usuario remoto especıfico pueda empujar cambios que no afecten la porcion protegida.

Esta extension implementa control de acceso basado en la identidad del usuario que empuja los conjuntos de

cambios, no en la identidad de quien hizo la consignacion de los mismos. Usar este gancho tiene sentido solo si se

tiene un servidor adecuadamente asegurado que autentique a los usuarios remotos, y si usted desea segurarse de que

solo se le permita a ciertos usuarios empujar cambios a dicho servidor.

117

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 128/204

Configuracion del gancho acl

Para administrar los conjuntos de cambios entrantes, se debe usar el gancho acl como un gancho de tipo pretxnchangegro

Esto le permite ver que ficheros son modificados por cada conjunto de cambios entrante, y deshacer el efecto de un

grupo de conjuntos de cambios si alguno de ellos modifica algun fichero “prohibido”. Ejemplo:

1 [hooks]

2 pretxnchangegroup.acl = python:hgext.acl.hook

La extension acl es configurada mediante tres secciones.

La seccion [acl] solo tiene una entrada, sources2, que lista las fuentes de los conjuntos de cambios entrantes a

las que el gancho debe prestar atencion. Usualmente usted no necesita configurar esta seccion.

serve Controlar conjuntos de cambios entrantes que estan llegando desde un repositorio a traves de http o ssh. Este es

el valor por defecto de sources, y usualmente es el unico valor de configuracion que necesitara para este ıtem.

pull Controlar conjuntos de cambios entrantes que lleguen vıa un pull (jalado) desde un repositorio local.

push Controlar conjuntos de cambios entrantes que lleguen vıa un push (empuje) desde un repositorio local.

bundle Controlar conjuntos de cambios entrantes que lleguen desde otro repositorio a traves de un paquete.

La seccion [acl.allow] controla los usuarios a los que les esta permitido anadir conjuntos de cambios al repos-

itorio. Si esta seccion no esta presente, se le permite acceso a todos los usuarios excepto a los que se les haya negado

explıcitamente el acceso. Si esta seccion no esta presente, se niega el acceso a todos los usuarios excepto a todos a los

que se les haya permitido de manera explıcita (ası que una seccion vacıa implica que se niega el acceso a todos los

usuarios).

La seccion [acl.deny] determina a que usuarios no se les permite anadir conjuntos de cambios al repositorio. Si

esta seccion no esta presente o esta vacıa, no se niega el acceso a ningun usuario.

La sintaxis para los ficheros [acl.allow] y [acl.deny] es identica. A la izquierda de cada entrada se encuentra

un patron glob que asocia ficheros o directorios, respecto a la raız del repositorio; a la derecha, un nombre usuario.

En el siguiente ejemplo, el usuario escritordoc solo puede empujar cambios al directorio docs del repositorio,

mientras que practicante puede enviar cambios a cualquier fichero o directorio excepto fuentes/sensitivo .

1 [acl.allow]2 docs/** = escritordoc

3

4 [acl.deny]

5 fuentes/sensitivo/** = practicante

Pruebas y resolucion de problemas

Si usted desea probar el gancho acl, ejecutelo habilitando la opcion de salida de depuracion habilitada. Ya que

usted probablemente lo estara ejecutando en un servidor donde no es conveniente (o incluso posible) pasar la opcion

--debug, no olvide que usted puede habilitar la salida de depuracion en su hgrc:

1 [ui]

2 debug = true

Con esto habilitado, el gancho acl imprimira suficiente informacion para permitirle saber porque esta permitiendo o

denegando la operacion de empujar a usuarios especıficos.

2N. del T. Fuentes.

118

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 129/204

10.7.2. bugzilla—integracion con Bugzilla

La extension bugzilla anade un comentario a un fallo Bugzilla siempre que encuentre una referencia al ID de

dicho fallo en un mensaje de consignacion. Usted puede instalar este gancho en un servidor compartido, para que cada

vez que un usuario remoto empuje cambios al servidor, el gancho sea ejecutado.

Se anade un comentario al fallo que se ve ası (usted puede configurar los contenidos del comentario—vea mas

abajo):

1 Changeset aad8b264143a, made by Joe User <[email protected]> in

2 the frobnitz repository, refers to this bug.

3

4 For complete details, see

5 http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a

6

7 Changeset description:

8 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. Si usted configura este gancho adecuadamente, hara f acil para la gente navegar directamente desde un

fallo Bugzilla a un conjunto de cambios que se refiere a ese fallo.Usted puede usar el codigo de este gancho como un punto de partida para otras recetas de integraci on con Bugzilla

aun mas exoticas. Aca hay algunas posibilidades:

Requerir que cada conjunto de cambios tenga un ID de fallo en su mensaje de consignacion. En este caso, usted

querra configurar el gancho como uno de tipo pretxncommit. Esto le permitira al gancho rechazar cambios que

no contiene IDs de fallos.

Permitir a los conjuntos de cambios entrantes modificar automaticamente el estado de un fallo, ası como simple-

mente anadir un comentario. Por ejemplo, el gancho podrıa reconocer la cadena “corregido fallo 31337” como

la senal de que deberıa actualizar el estado del fallo 31337 a “requiere pruebas”.

Configuracion del gancho bugzilla

Usted deberıa configurar este gancho en el hgrc de su servidor como un gancho incoming3, por ejemplo comosigue:

1 [hooks]

2 incoming.bugzilla = python:hgext.bugzilla.hook

Debido a la naturaleza especializada de este gancho, y porque Bugzilla no fue escrito con este tipo de integracion

en mente, configurar este gancho es un proceso algo complejo.

Antes de empezar, usted debe instalar la interfaz de Python para MySQL en los sistemas en los que se vaya a

ejecutar el gancho. Si no esta disponible como paquete binario para su sistema, usted puede descargar el paquete

desde [Dus].

La informacion para configurar este gancho se ubica en la seccion [bugzilla] de su hgrc.

version La version de Bugzilla instalada en el servidor. El esquema de base de datos que Bugzilla usa cambia ocasion-almente, ası que este gancho debe saber exactamente que esquema usar. A la fecha, la unica version soportada

es la 2.16.

host El nombre de maquina (hostname) del servidor MySQL que almacena sus datos Bugzilla. La base de datos debe

ser configurada para permitir conexiones desde las maquinas en las que usted ejecute el gancho bugzilla.

3N. del T. Entrante.

119

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 130/204

user El nombre de usuario que se usara para conectarse al servidor MySQL. La base de datos debe ser configurada

para permitir a dicho usuario conectarse desde cualquiera de las maquinas en las que se ejecute el gancho

bugzilla. Este usuario debe tener acceso y poder modificar las tablas de Bugzilla. El valor por defecto para

este ıtem es bugs, que es el nombre estandar del usuario para Bugzilla en una base de datos MySQL.

password La contrasena MySQL para el usuario configurado anteriormente. Esta es almacenada como texto plano, ası que

usted debera asegurarse de que los usuarios no autorizados no puedan leer el fichero hgrc en donde usted guarda

esta informacion.

db El nombre de la base de datos Bugzilla en el servidor MySQL. El nombre por defecto para este ıtem es bugs,

que es el nombre estandar de la base de datos MySQL en donde Bugzilla almacena sus datos.

notify Si usted desea que Bugzilla envıe un correo de notificacion a los suscriptores despues de que el gancho haya

anadido un comentario a un fallo, necesitara que este gancho ejecute un comando siempre que actualice la base

de datos. El comando que se ejecute depende de en donde haya sido instalado Bugzilla, pero tıpicamente se

vera ası, si usted ha instalado Bugzilla en /var/www/html/bugzilla :

1 cd /var/www/html/bugzilla && ./processmail %s [email protected]

El programa processmail de Bugzilla espera recibir un ID de fallo (el gancho reemplaza “ %s” por el ID del

fallo) y una direccion de correo. Tambien espera poder escribir a ciertos ficheros en el directorio en que seejecuta. Si Bugzilla y este gancho no estan instalados en la misma maquina, usted debera encontrar una manera

de ejecutar processmail en el servidor donde esta instalado Bugzilla.

Asociar nombres de consignadores a nombres de usuario Bugzilla

Por defecto, el gancho bugzilla trata de usar la direccion de correo electronico de la persona que hizo la

consignacion del conjunto de cambios como el nombre de usuario Bugzilla con el cual debe actualizar el fallo. Si

esto no se ajusta a sus necesidades, es posible asociar direcciones de correo a nombres de usuario Bugzilla usando una

seccion [usermap].

Cada ıtem en la seccion [usermap] contiene una direccion de correo electronico a la izquierda, y un nombre de

usuario Bugzilla a la derecha.

1 [usermap]2 [email protected] = jane

Usted puede mantener los datos de [usermap] en un fichero hgrc, o decirle al gancho bugzilla que lea la informa-

cion desde un fichero usermap externo. En este caso, usted puede almacenar los datos de usermap en (por ejemplo) un

repositorio modificable por los usuarios. Esto hace posible para sus usuarios mantener sus propias entradas usermap.

El fichero hgrc principal se verıa ası:

1 # fichero hgrc normal se refiere a un fichero usermap externo

2 [bugzilla]

3 usermap = /home/hg/repos/userdata/bugzilla-usermap.conf

Mientras que el fichero usermap al que se hace referencia se verıa ası:

1 # bugzilla-usermap.conf - dentro de un repositorio hg

2 [usermap]

3 [email protected] = steph

120

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 131/204

Configurar el texto que se a ˜ nade a un fallo

Usted puede configurar el texto que este gancho anade como comentario; usted los especifica como una plantilla

Mercurial. Varias entradas hgrc (aun en la seccion [bugzilla]) controlan este comportamiento.

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. Por ejemplo, si los repositorios en su servidor se ubican en /home/hg/repos, y usted

tiene un repositorio cuya ruta es /home/hg/repos/app/tests , entonces fijar strip a 4 resultara en una rutaparcial de app/tests. El gancho hara disponible esta ruta parcial cuando expanda una plantilla, como webroot.

template El texto de la plantilla a usar. En adicion a las variables usuales relacionadas con conjuntos de cambios, esta

plantilla puede usar hgweb (el valor del ıtem de configuracion hgweb de arriba) y webroot (la ruta construida

usando strip arriba).

Adicionalmente, usted puede anadir un ıtem baseurl a la seccion [web] de su hgrc. El gancho bugzilla pub-

licara esto cuando expanda una plantilla, como la cadena base a usar cuando se construya una URL que le permita a

los usuarios navegar desde un comentario de Bugzilla a la vista de un conjunto de cambios. Ejemplo:

1 [web]

2 baseurl = http://hg.domain.com/

A continuacion se presenta un ejemplo completo de configuracion para el gancho bugzilla.

1 [bugzilla]

2 host = bugzilla.example.com

3 password = mypassword

4 version = 2.16

5 # server-side repos live in /home/hg/repos, so strip 4 leading

6 # separators

7 strip = 4

8 hgweb = http://hg.example.com/

9 usermap = /home/hg/repos/notify/bugzilla.conf

10 template = Changeset {node|short}, made by {author} in the {webroot}11 repo, refers to this bug. nFor complete details, see

12 {hgweb}{webroot}?cmd=changeset;node={node|short} nChangeset

13 description: n t{desc|tabindent}

Pruebas y resolucion de problemas

Los problemas mas comunes que aparecen en la configuracion del gancho bugzilla suelen estar relacionados con

la ejecucion del guion de Bugzilla processmail y la asociacion de nombres de consignadores a nombres de usuario.

Recuerde que en la seccion 10.7.2 arriba el usuario que ejecuta el proceso Mercurial en el servidor es tambien

el usuario que ejecutara el guion processmail. El guion processmail algunas veces hace que Bugzilla escriba en

ficheros en su directorio de configuracion, y los ficheros de configuracion de Bugzilla usualmente son propiedad del

usuario bajo el cual se ejecuta el servidor web.

Usted puede hacer que processmail sea ejecutado con la identidad del usuario adecuado usando el comando

sudo. A continuacion se presenta una entrada de ejemplo para un fichero sudoers.

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.

Esta indireccion a traves de un guion envoltorio es necesaria, porque processmail espera que al ser ejecutado su

directorio actual sea aquel en el cual se instalo Bugzilla; usted no puede especificar ese tipo de condicion en un fichero

sudoers. Los contenidos del giuon envoltorio son simples:

121

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 132/204

1 #!/bin/sh

2 cd ‘dirname $0‘ && ./processmail "$1" [email protected]

No parece importar que direccion de correo se le pase a processmail.

Si su [usermap] no es configurada correctamente, los usuarios veran un mensaje de error del gancho bugzilla

cuando empujen cambios al servidor. El mensaje de error se ver a ası:

1 cannot find bugzilla user id for [email protected]

Lo que esto quiere decir es que la direccion del consignador, [email protected] , no es un nombre de

usuario Bugzilla valido, ni tiene una entrada en su [usermap] que lo asocie con un nombre de usuario valido Bugzilla.

10.7.3. notify—enviar notificaciones de correo electronico

Aunque el servidor web embebido de Mercurial provee notificaciones de cambios en cada repositorio, muchas

personas prefieren recibir las notificaciones de cambios vıa correo electronico. El gancho notify4 le permite a usted

enviar notificaciones a un conjunto de direcciones de correo cuando lleguen conjuntos de cambios en los que los

subscriptores esten interesados.

De la misma forma que con el gancho bugzilla, el gancho notify esta orientado a plantillas, ası que usted puedepersonalizar los contenidos del mensaje de notificacion que se envıa.

Por defecto, el gancho notify incluye un diff de cada conjunto de cambios que se envıa; usted puede limitar el

tamano del diff, o desactivar completamente esta caracterıstica. Es util para permitir a los subscriptores revisar los

cambios inmediatamente, en vez de tener que hacer clic para visitar una URL.

Configuracion del gancho notify

Usted puede configurar el gancho notify para enviar un mensaje de correo por conjunto de cambios entrante, o

uno por grupo entrante de conjuntos de cambios (todos los que llegaron en un unico empuje o jalado).

1 [hooks]

2 # enviar un correo por grupo de cambios

3 changegroup.notify = python:hgext.notify.hook4 # enviar un correo por cambio

5 incoming.notify = python:hgext.notify.hook

La informacion para configurar este gancho se ubica en la seccion [notify] de un fichero hgrc.

test Por defecto, este gancho no envıa correos en absoluto; en vez de eso, imprime el mensaje que se enviarıa. Fije

este ıtem en false para permitir el envıo de correos. El motivo por el que el envıo de correos esta desactivado es

que hacen falta varios intentos para configurar esta extension exactamente como usted desea, y serıa maleducado

enviar a los subscriptores una cantidad de notificaciones “rotas” mientras usted depura su configuracion.

config La ruta a un fichero de configuracion que contiene informacion de subscripcion. Esto se mantiene separado

del hgrc principal para que usted pueda mantenerlo en un repositorio. La gente puede clonar ese repositorio,

actualizar sus subscripciones, y empujar los cambios de vuelta a su servidor.

strip La cantidad de caracteres iniciales de separacion de ruta a remover de la ruta del repositorio, al decidir si un

repositorio tiene subscriptores. Por ejemplo, si los repositorios en su servidor estan en /home/hg/repos, y

notify esta trabajando con un repositorio llamado /home/hg/repos/shared/test , fijar strip a 4 hara que

notify elimine las partes iniciales de la ruta hasta shared/test, y asociara los subscriptores frente a dicha

ruta.

4N. del T. Notificacion.

122

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 133/204

template El texto de plantilla a usar cuando se envıen mensajes. Especifica los contenidos de la cabecera del mensaje y el

cuerpo del mismo.

maxdiff El numero maximo de lıneas de datos de diff a anadir al final de un mensaje. Si la longitud de un diff es mayor

a eso, se trunca. Por defecto, esta fijado en 300. Fije esto a 0 para omitir los diffs en los correos de notificacion.

sources Una lista de fuentes de conjuntos de cambios a considerar. Esto le permite a usted indicar a notify para que

solo envıe correos acerca de cambios que usuarios remotos hayan empujado al repositorio vıa un servidor, porejemplo. Vea la seccion 10.8.3 para las fuentes que usted puede especificar aquı.

Si usted fija el ıtem baseurl en la seccion [web], usted lo puede usar en una plantilla; estara disponible como

webroot.

A continuacion se presenta un ejemplo completo de configuracion para el gancho notify.

1 [notify]

2 # enviar correo

3 test = false

4 # datos de subscriptores estan en el repositorio notify

5 config = /home/hg/repos/notify/notify.conf

6 # repos estan en /home/hg/repos on server, ası que elimine 4

7 # caracteres"/"8 strip = 4

9 template = X-Hg-Repo: {webroot}10 Subject: {webroot}: {desc|firstline|strip}11 From: {author}12

13 changeset {node|short} in {root}14 details: {baseurl}{webroot}?cmd=changeset;node={node|short}15 description:

16 {desc|tabindent|strip}17

18 [web]

19 baseurl = http://hg.example.com/

Esto producira un mensaje que se vera como el siguiente:

1 X-Hg-Repo: tests/slave

2 Subject: tests/slave: Handle error case when slave has no buffers

3 Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT)

4

5 changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave

6 details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5

7 description:

8 Handle error case when slave has no buffers

9 diffs (54 lines):

10

11 diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h

12 --- a/include/tests.h Wed Aug 02 15:19:52 2006 -0700

13 +++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700

14 @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h)

15 [...snip...]

123

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 134/204

Pruebas y resolucion de problemas

No olvide que por defecto, la extension notify no enviar   a ning´ un correo electr   onico hasta que usted la configure

explıcitamente para hacerlo, fijando el valor de test a false. Hasta que usted haga eso, simplemente se imprimira el

mensaje que se enviar   ıa.

10.8. Informacion para escritores de ganchos

10.8.1. Ejecucion de ganchos internos

Un gancho interno es llamado con argumentos de la siguiente forma:

1 def myhook(ui, repo, **kwargs):

2 pass

El parametro ui es un objeto mercurial.ui.ui. El parametro repo es un objeto mercurial.localrepo.localrepository .

Los nombres y valores de los parametros en **kwargs dependen del gancho que se invoque, con las siguientes carac-

terısticas en comun:

Si hay un parametro llamado node o parentN , contendra un ID hexadecimal de un conjunto de cambios. La

cadena vacıa es usada para representar un “ID de conjunto de cambios nulo” en vez de una cadena de ceros.

Si hay un parametro llamado url, contendra la URL de un repositorio remoto, si puede ser determinada.

Los parametros booleanos son representados como objetos bool de Python.

Un gancho interno es ejecutado sin cambiar el directorio de trabajo del proceso (a diferencia de los ganchos

externos, que son ejecutados desde la raız del repositorio). El gancho no debe cambiar el directorio de trabajo del

proceso, porque esto harıa que falle cualquier llamada que se haga a la API de Mercurial.

Si un gancho retorna el valor booleano “false”5, se considera que este tuvo exito. Si retorna “true”6 o genera una

excepcion, se considera que ha fallado. Una manera util de pensar en esta convencion de llamado es “dıgame si usted

fallo”.

Note que los IDs de conjuntos de cambios son pasados a los ganchos de Python como cadenas hexadecimales, no

como los hashes binarios que la API de Mercurial usa normalmente. Para convertir un hash de hexadecimal a binario,

use la funcion mercurial.node.bin .

10.8.2. Ejecucion de ganchos externos

Un gancho externo es pasado al interprete de comandos del usuario bajo el cual se ejecuta Mercurial. Las car-

acterısticas del interprete, como sustitucion de variables y redireccion de comandos, estan disponibles. El gancho es

ejecutado desde el directorio raız del repositorio (a diferencia de los ganchos internos, que se ejecutan desde el mismo

directorio en que Mercurial fue ejecutado).

Los parametros para el gancho se pasan como variables de entorno. El nombre de cada variable de entorno se pasa

a mayusculas y se le anade el prefijo “HG ”. Por ejemplo, si el nombre de un parametro es “node”, el nombre de la

variable de entorno que almacena el parametro se llamara “HG NODE”.

Un parametro booleano se representa con la cadena “1” para “true”, “0” para “false”. Si una variable se llama

HG NODE, HG PARENT1 o HG PARENT2, contendra un ID de conjunto de cambios representado como una cadena hex-

adecimal. La cadena vacıa es usada para representar un “ID de conjunto de cambios nulo” en vez de una cadena de

ceros. Si una variable de entorno se llama HG URL, contendra la URL de un repositorio remoto, si puede ser determi-

nada.

Si un gancho termina con un codigo de salida de cero, se considera que tuvo exito. Si termina con un codigo de

salida diferente de cero, se considera que fallo.

5N. del T. Falso.6N. del T. Verdadero.

124

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 135/204

10.8.3. Averiguar de donde vienen los conjuntos de cambios

Un gancho que involucra la transferencia de conjuntos de cambios entre un repositorio local y otro puede ser capaz

de averiguar informacion acerca de “el otro lado”. Mercurial sabe c´ omo son transferidos los conjuntos de cambios, y

en muchos casos tambien desde o hacia donde estan siendo transferidos.

Fuentes de conjuntos de cambios

Mercurial le indicara a un gancho cuales son, o fueron, los medios usados para transferir los conjuntos de cambios

entre repositorios. Esta informacion es provista por Mercurial en un parametro Python llamado source7, o una variable

de entorno llamada HG SOURCE.

serve Los conjuntos de cambios son transferidos desde o hacia un repositorio remoto a trav es de http o ssh.

pull Los conjuntos de cambios son transferidos vıa una operacion de jalado de un repositorio a otro.

push Los conjuntos de cambios son transferidos vıa un empuje de un repositorio a otro.

bundle Los conjuntos de cambios son transferidos desde o hacia un paquete.

A donde van los cambios—URLs de repositorios remotos

Cuando es posible, Mercurial le indicara a los ganchos la ubicacion de “el otro lado” de una actividad que transfieradatos de conjuntos de cambios entre repositorios. Esto es provisto por Mercurial en un parametro Python llamado url,

o en una variable de entorno llamada HG URL.

No siempre esta informacion esta disponible. Si un gancho es invocado un repositorio que es servido a trav es de

http o ssh, Mercurial no puede averiguar donde esta el repositorio remoto, pero puede saber desde donde se conecta el

cliente. En esos casos, la URL tendra una de las siguientes formas:

remote:ssh:ip-address—cliente ssh remoto, en la direccion IP dada.

remote:http:ip-address—cliente remoto http, en la direccion IP dada. Si el cliente esta usando SSL,

tendra la forma remote:https:ip-address.

Vacıo—no se pudo descubrir informacion acerca del cliente remoto.

10.9. Referencia de ganchos

10.9.1. changegroup—luego de a ˜ nadir conjuntos de cambios remotos

Este gancho es ejecutado luego de que un grupo de conjuntos de cambios preexistentes ha sido anadido al repos-

itorio, por ejemplo vıa un “hg pull” o “hg unbundle”. Este gancho es ejecutado una vez por cada operacion que

anade uno o mas conjuntos de cambios. Este gancho se diferencia del gancho incoming, que es ejecutado una vez por

cada conjunto de cambios, sin importar si los cambios llegan en grupo.

Algunos usos posibles para este gancho includen el probar o ensamblar los conjuntos de cambios a nadidos, actu-

alizar una base de datos de fallos, o notificar a subscriptores de que el repositorio contiene nuevos cambios.

Parametros para este gancho:

node Un ID de conjunto de cambios. El ID del primer conjunto de cambios que fue anadido en el grupo. Todos los

conjuntos de cambios entre este y la punta (tip), inclusive, fueron anadidos por un unico jalado (“hg pull”),empuje (“hg push”) o “hg unbundle”.

source Una cadena. La fuente de estos cambios. Vea la seccion 10.8.3 para mas detalles.

url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.

Veta tambien: incoming (seccion 10.9.3), prechangegroup (seccion 10.9.5), pretxnchangegroup (seccion 10.9.9)

7N. del T. Fuente.

125

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 136/204

10.9.2. commit—luego de la creacion de un nuevo conjunto de cambios

Este gancho es ejecutado luego de la creacion de un nuevo conjunto de cambios.

Parametros para este gancho:

node Un ID de conjunto de cambios. El ID de conjunto de cambios del conjunto de cambios que acab o de ser

consignado.

parent1 Un ID de conjunto de cambios. El ID de conjunto de cambios del primer padre del conjunto de cambios que

acaba de ser consignado.

parent2 Un ID de conjunto de cambios. El ID de conjunto de cambios del segundo padre del conjunto de cambios que

acaba de ser consignado.

Vea tambien: precommit (seccion 10.9.6), pretxncommit (seccion 10.9.10)

10.9.3. incoming—luego de que un conjunto de cambios remoto es a ˜ nadido

Este gancho es ejecutado luego de que un conjunto de cambios preexistente ha sido anadido al repositorio, por

ejemplo, vıa un “hg push”. Si un grupo de conjuntos de cambios fue anadido en una sola operacion, este gancho es

ejecutado una vez por cada conjunto de cambios anadido.

Usted puede usar este gancho para los mismos fines que el gancho changegroup (seccion 10.9.1); simplementealgunas veces es mas conveniente ejecutar un gancho una vez por cada grupo de conjuntos de cambios, mientras que

otras es mas util correrlo por cada conjunto de cambios.

Parametros para este gancho:

node Un ID de conjunto de cambios. El ID del conjunto de cambios reci en anadido.

source Una cadena. La fuente de estos cambios. Vea la seccion 10.8.3 para mas detalles.

url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.

Vea tambien: changegroup (seccion 10.9.1) prechangegroup (seccion 10.9.5), pretxnchangegroup(seccion 10.9.9)

10.9.4. outgoing—luego de la propagacion de los conjuntos de cambios

Este gancho es ejecutado luego de que un grupo de conjuntos de cambios ha sido propagado fuera de este reposi-

torio, por ejemplo por un comando “hg push” o “hg bundle”.

Un uso posible para este gancho es notificar a los administradores que los cambios han sido jalados.

Parametros para este gancho:

node Un ID de conjunto de cambios. El ID del primer conjunto de cambios del grupo que fue enviado.

source Una cadena. La fuente de la operacion (vea la seccion 10.8.3). Si un cliente remoto jalo cambios de este

repositorio, source sera serve. Si el cliente que obtuvo los cambios desde este repositorio era local, source

sera bundle, pull, o push, dependiendo de la operacion que llevo a cabo el cliente.

url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.

Vea tambien: preoutgoing (seccion 10.9.7)

126

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 137/204

10.9.5. prechangegroup—antes de empezar la adicion de conjuntos de cambios remotos

Este gancho de control es ejecutado antes de que Mercurial empiece a a nadir un grupo de conjuntos de cambios de

otro repositorio.

Este gancho no tiene ninguna informacion acerca de los conjuntos de cambios que van a ser anadidos, porque es

ejecutado antes de que se permita que empiece la transmision de dichos conjuntos de cambios. Si este gancho falla,

los conjuntos de cambios no seran transmitidos.

Un uso para este gancho es prevenir que se anadan cambios externos a un repositorio. Por ejemplo, usted podr ıa

usarlo para “congelar” temporal o permanentemente una rama ubicada en un servidor para que los usuarios no puedan

empujar cambios a ella, y permitiendo al mismo tiempo modificaciones al repositorio por parte de un administrador

local.

Parametros para este gancho:

source Una cadena. La fuente de estos cambios. Vea la seccion 10.8.3 para mas detalles.

url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.

Vea tambien: changegroup (seccion 10.9.1), incoming (seccion 10.9.3), , pretxnchangegroup (seccion 10.9.9)

10.9.6. precommit—antes de iniciar la consignacion de un conjunto de cambios

Este gancho es ejecutado antes de que Mercurial inicie la consignacion de un nuevo conjunto de cambios. Es

ejecutado antes de que Mercurial tenga cualquier de los metadatos para la consignacion, como los ficheros a ser

consignados, el mensaje de consignacion, o la fecha de consignacion.

Un uso para este gancho es deshabilitar la capacidad de consignar nuevos conjuntos de cambios, pero permi-

tiendo conjuntos de cambios entrantes. Otro es ejecutar un proceso de ensamble/compilacion o prueba, y permitir la

consignacion solo si el ensamble/compilacion o prueba tiene exito.

Parametros para este gancho:

parent1 Un ID de conjunto de cambios. El ID de conjunto de cambios del primer padre del directorio de trabajo.

parent2 Un ID de conjunto de cambios. El ID de conjunto de cambios del segundo padre del directorio de trabajo.

Si la consignacion continua, los padres del directorio de trabajo se convertiran en los padres del nuevo conjunto de

cambios.Vea tambien: commit (seccion 10.9.2), pretxncommit (seccion 10.9.10)

10.9.7. preoutgoing—antes de empezar la propagacion de conjuntos de cambios

Este gancho es ejecutado antes de que Mercurial conozca las identidades de los conjuntos de cambios que deben

ser transmitidos.

Un uso para este gancho es evitar que los cambios sean transmitidos a otro repositorio.

Parametros para este gancho:

source Una cadena. La fuente la operacion que esta tratando de obtener cambios de este repositorio (vea la sec-

cion 10.8.3). Revise la documentacion para el parametro source del gancho outgoing, en la seccion 10.9.4,

para ver los posibles valores de este parametro.

url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.

Vea tambien: outgoing (seccion 10.9.4)

127

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 138/204

10.9.8. pretag—antes de etiquetar un conjunto de cambios

Este gancho de control es ejecutado antes de la creacion de una etiqueta. Si el gancho termina exitosamente, la

creacion de la etiqueta continua. Si el gancho falla, no se crea la etiqueta.

Parametros para este gancho:

local Un booleano. Indica si la etiqueta es local a esta instancia del repositorio (p.e. almacenado en .hg/localtags)

o administrado por Mercurial (almacenado en .hgtags).

node Un ID de conjunto de cambios. El ID del conjunto de cambios a etiquetar.

tag Una cadena. El nombre de la etiqueta por crear.

Si la etiqueta que se va a crear se encuentra bajo control de revisiones, los ganchos precommit y pretxncommit

(secciones 10.9.2 y 10.9.10) tambien seran ejecutados.

Vea tambien: tag (seccion 10.9.12)

10.9.9. pretxnchangegroup—antes de completar la adicion de conjuntos de cambios

remotos

Este gancho de control es ejecutado antes de una transaccion—la que maneja la adicion de un grupo de conjuntos

de cambios nuevos desde fuera del repositorio—se complete. Si el gancho tiene exito, la transaccion se completa, y

todos los conjuntos de cambios se vuelven permanentes dentro de este repositorio. Si el gancho falla, la transacci on es

deshecha, y los datos para los conjuntos de cambios son eliminados.

Este gancho puede acceder a los metadatos asociados con los conjuntos de cambios casi a nadidos, pero no debe

hacer nada permanente con estos datos. Tampoco debe modificar el directorio de trabajo.

Mientras este gancho esta corriendo, si otro proceso Mercurial accesa el repositorio, podra ver los conjuntos de

cambios casi anadidos como si fueran permanentes. Esto puede llevar a condiciones de carrera si usted no toma

precauciones para evitarlas.

Este gancho puede ser usado para examinar automaticamente un grupo de conjuntos de cambios. Si el gancho falla,

todos los conjuntos de cambios son “rechazados” cuando la transacci on se deshace.

Parametros para este gancho:

node Un ID de conjunto de cambios. El ID del primer conjunto de cambios que fue anadido en el grupo. Todos los

conjuntos de cambios entre este y el tip, inclusive, fueron anadidos por un unico “hg pull”, “hg push” o “hg

unbundle”.

source Una cadena. La fuente de estos cambios. Vea la seccion 10.8.3 para mas detalles.

url Una URL. La ubicacion del repositorio remoto, si es conocida. Vea la seccion 10.8.3 para mas informacion.

Vea tambien: changegroup (seccion 10.9.1), incoming (seccion 10.9.3), prechangegroup (seccion 10.9.5)

10.9.10. pretxncommit—antes de completar la consignacion de un nuevo conjunto de

cambios

Este gancho de control es ejecutado antes de que una transaccion—que maneja una nueva consignacion—se com-

plete. Si el gancho tiene exito, la transaccion se completa y el conjunto de cambios se hace permanente dentro de esterepositorio. Si el gancho falla, la transaccion es deshecha, y los datos de consignacion son borrados.

Este gancho tiene acceso a los metadatos asociados con el practicamente nuevo conjunto de cambios, pero no

deberıa hacer nada permanente con estos datos. Tampoco debe modificar el directorio de trabajo.

Mientras este gancho esta corriendo, si otro proceso Mercurial accesa este repositorio, podra ver el practicamente

nuevo conjunto de cambios como si fuera permanente. Esto puede llevar a condiciones de carrera si usted no toma

precauciones para evitarlas.

Parametros para este gancho:

128

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 139/204

node Un ID de conjunto de cambios. El ID del conjunto de cambios reci en consignado.

parent1 Un ID de conjunto de cambios. El ID de conjunto de cambios del primer padre del conjunto de cambios que

acaba de ser consignado.

parent2 Un ID de conjunto de cambios. El ID de conjunto de cambios del segundo padre del conjunto de cambios que

acaba de ser consignado.

Vea tambien: precommit (seccion 10.9.6)

10.9.11. 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. Es ejecutado s olo si las

revisiones usuales de Mercurial antes de las actualizaciones determinan que la actualizacion o fusion pueden proceder.

Si el gancho termina exitosamente, la actualizacion o fusion pueden proceder.; si falla, la actualizacion o fusion no

empiezan.

Parametros para este gancho:

parent1 Un ID de conjunto de cambios. El ID del padre al que el directorio de trabajo sera actualizado. Si se esta fusio-

nando el directorio de trabajo, no cambiara este padre.

parent2 Un ID de conjunto de cambios. Solo esta definido si se esta fusionando el directorio de trabajo. El ID de larevision con la cual esta siendo fusionado el directorio de trabajo.

Vea tambien: update (seccion 10.9.13)

10.9.12. tag—luego de etiquetar un conjunto de cambios

Este gancho es ejecutado luego de la creacion de una etiqueta.

Parametros para este gancho:

local Un booleano. Indica si la etiqueta es local a esta instancia del repositorio (p.e. almacenado en .hg/localtags)

o administrado por Mercurial (almacenado en .hgtags).

node Un ID de conjunto de cambios. El ID del conjunto de cambios que fue etiquetado.

tag Una cadena. El nombre de la etiqueta que fue creada.

Si la etiqueta creada esta bajo control de revisiones, el gancho commit (seccion 10.9.2) es ejecutado antes de este

gancho.

Vea tambien: pretag (seccion 10.9.8)

10.9.13. update—luego de actualizar o fusionar el directorio de trabajo

Este gancho es ejecutado despues de una actualizacion o fusion en el directorio de trabajo. Ya que una fusion

puede fallar (si el comando externo hgmerge no puede resolver los conflictos en un fichero), este gancho indica si la

actualizacion o fusion fueron completados adecuadamente.

error Un booleano. Indica si la actualizacion o fusion fue completada exitosamente.

parent1 Un ID de conjunto de cambios. El ID del padre al cual fue actualizado el directorio de trabajo. Si se fusiono el

directorio de trabajo, no se habra cambiado este padre.

parent2 Un ID de conjunto de cambios. Solo esta definido si se fusiono el directorio de trabajo. El ID de la revision con

la que fue fusionado el directorio de trabajo.

Vea tambien: preupdate (seccion 10.9.11)

129

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 140/204

Capıtulo 11

Personalizar los mensajes de Mercurial

Mercurial provee un poderoso mecanismo que permite controlar como despliega la informacion. El mecanismo se

basa en plantillas. Puede usar plantillas para generar salida especıfica para una orden particular o para especificar la

visualizacion completa de la interfaz web embebida.

11.1. Usar estilos que vienen con Mercurial

Hay ciertos estilos listos que vienen con Mercurial. Un estilo es simplemente una plantilla predeterminada que

alguien escribio e instalo en un sitio en el cual Mercurial puede encontrarla.

Antes de dar un vistazo a los estilos que trae Mercurial, revisemos su salida usual.

1 $ hg log -r1

2 changeset: 1:522d8d7a8fda

3 tag: mytag

4 user: Bryan O’Sullivan <[email protected]>

5 date: Tue Feb 10 18:23:30 2009 +0000

6 summary: added line to end of <<hello>> file.

7

Es en cierta medida informativa, pero ocupa mucho espacio—cinco l ıneas de salida por cada conjunto de cambios.

El estilo compact lo reduce a tres lıneas, presentadas de forma suscinta.

1 $ hg log --style compact

2 3[tip] b638ce454bd0 2009-02-10 18:23 +0000 bos

3 Added tag v0.1 for changeset 4b75acdd4698

4

5 2[v0.1] 4b75acdd4698 2009-02-10 18:23 +0000 bos

6 Added tag mytag for changeset 522d8d7a8fda

7

8 1[mytag] 522d8d7a8fda 2009-02-10 18:23 +0000 bos

9 added line to end of <<hello>> file.

10

11 0 d0c3b909ac1b 2009-02-10 18:23 +0000 bos

12 added hello

13

El estilo de la bitacora de cambios vislumbra el poder expresivo del sistema de plantillas de Mercurial. Este

estilo busca seguir los estandares de bitacora de cambios del proyecto GNU[RS].

130

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 141/204

1 $ hg log --style changelog

2 2009-02-10 Bryan O’Sullivan <[email protected]>

3

4 * .hgtags:

5 Added tag v0.1 for changeset 4b75acdd4698

6 [b638ce454bd0] [tip]7

8 * .hgtags:

9 Added tag mytag for changeset 522d8d7a8fda

10 [4b75acdd4698] [v0.1]

11

12 * goodbye, hello:

13 added line to end of <<hello>> file.

14

15 in addition, added a file with the helpful name (at least i hope

16 that some might consider it so) of goodbye.

17 [522d8d7a8fda] [mytag]

18

19 * hello:20 added hello

21 [d0c3b909ac1b]

22

No es una sorpresa que el estilo predeterminado de Mercurial se llame default1.

11.1.1. Especificar un estilo predeterminado

Puede modificar el estilo de presentacion que Mercurial usara para toda orden vıa el fichero hgrc indicando el

estilo que prefiere usar.

1 [ui]

2 style = compact

Si escribe un estilo, 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

instalacion de Mercurial).

11.2. Ordenes que soportan estilos y plantillas

Todas las ordenes de Mercurial“relacionadas con log” le permiten usar estilos y plantillas: “hg incoming”, “hg

log”, “hg outgoing” y “hg tip”.

Al momento de la escritura del manual estas son las unicas ordenes que soportan estilos y plantillas. Dado que son

las ordenes mas importantes que necesitan personalizacion, no ha habido muchas solicitudes desde la comunidad de

usuarios de Mercurial para anadir soporte de plantillas y estilos a otras ordenes.

11.3. Cuestiones basicas de plantillas

Una plantilla de Mercurial es sencillamente una pieza de texto. Cierta porcion nunca cambia, otras partes se

expanden, o reemplazan con texto nuevo cuando es necesario.

1N. del T. predeterminado

131

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 142/204

Antes de continuar, veamos de nuevo un ejemplo sencillo de la salida usual de Mercurial:

1 $ hg log -r1

2 changeset: 1:522d8d7a8fda

3 tag: mytag

4 user: Bryan O’Sullivan <[email protected]>

5 date: Tue Feb 10 18:23:30 2009 +00006 summary: added line to end of <<hello>> file.

7

Ahora, ejecutemos la misma orden, pero usemos una plantilla para modificar su salida:

1 $ hg log -r1 --template ’i saw a changeset\n’

2 i saw a changeset

El ejemplo anterior ilustra la plantilla mas sencilla posible; es solamente una porcion estatica de codigo que se

imprime una vez por cada conjunto de cambios. La opcion --template de la orden “hg log” indica a Mercurial usar

el texto dado como la plantilla cuando se imprime cada conjunto de cambios.

Observe que la cadena de plantilla anterior termina con el texto “ \n”. Es una secuencia de control, que le indicaa Mercurial imprimira una nueva lınea al final de cada objeto de la plantilla. Si omite esta nueva lınea, Mercurial

colocara cada pieza de salida seguida. Si desea mas detalles acerca de secuencias de control, vea la seccion 11.5.

Una plantilla que imprime una cadena fija de texto siempre no es muy util; intentemos algo un poco mas complejo.

1 $ hg log --template ’i saw a changeset: {desc}\n’

2 i saw a changeset: Added tag v0.1 for changeset 4b75acdd4698

3 i saw a changeset: Added tag mytag for changeset 522d8d7a8fda

4 i saw a changeset: added line to end of <<hello>> file.

5

6 in addition, added a file with the helpful name (at least i hope that some might consider it so) o

7 i saw a changeset: added hello

Como puede ver, la cadena “{desc}” en la plantilla ha sido reemplazada en la salida con la descricipci on de cadaconjunto de cambios. Cada vez que Mercurial encuentra texto encerrado entre corchetes (“{” y “}”), intentara reem-

plazar los corchetes y el texto con la expansion de lo que sea esta adentro. Para imprimir un corchete de forma literal,

debe escaparlo, como se describe en la seccion 11.5.

11.4. Palabras claves mas comunes en las plantillas

Puede empezar a escribir plantillas sencillas rapidamente con las palabras claves descritas a continuacion:

author Cadena. El autor NO modificado del conjunto de cambios.

branches Cadena. El nombre de la rama en la cual se consigno el conjunto de cambios. Sera vacıa si el nombre de la rama

es default.

date Informacion de fecha. La fecha en la cual se consigno el conjunto de cambios. No es legible por un humano, debe

pasarla por un firltro que la desplegara apropiadamente. En la seccion 11.6 hay mas detalles acerca de filtros. La

fecha se expresa como un par de numeros. El primer numero corresponde a una marca de tiempo UNIX UTC

(segundos desde el primero de enero de 1970); la segunda es el corrimiento horario de la zona horaria del UTC

en la cual se encontraba quien hizo la consignacion, en segundos.

desc Cadena. La descripcion en texto del conjunto de cambios.

132

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 143/204

1 $ hg log -r1 --template ’author: {author}\n’

2 author: Bryan O’Sullivan <[email protected]>

3 $ hg log -r1 --template ’desc:\n{desc}\n’

4 desc:

5 added line to end of <<hello>> file.

6

7 in addition, added a file with the helpful name (at least i hope that some might consider it so) o8 $ hg log -r1 --template ’files: {files}\n’

9 files: goodbye hello

10 $ hg log -r1 --template ’file_adds: {file_adds}\n’

11 file_adds: goodbye

12 $ hg log -r1 --template ’file_dels: {file_dels}\n’

13 file_dels:

14 $ hg log -r1 --template ’node: {node}\n’

15 node: 522d8d7a8fda9a24dcac9c5ccfcca067b933220b

16 $ hg log -r1 --template ’parents: { parents}\n’

17 parents:

18 $ hg log -r1 --template ’rev: {rev}\n’

19 rev: 1

20 $ hg log -r1 --template ’tags: {tags}\n’21 tags: mytag

Figura 11.1: Template keywords in use

files Lista de cadenas. Todos los ficheros modificados, adicionados o eliminados por este conjunto de cambios.

file adds Lista de cadenas. Ficheros adicionados por este conjunto de cambios.

file dels Lista de cadenas. Ficheros eliminados por este conjunto de cambios.

node Cadena. El hash de identificacion de este conjunto de cambios como una cadena hexadecimal de 40 caracteres.

parents Lista de cadenas. Los ancestros del conjunto de cambios.

rev Entero. El numero de revision del repositorio local.

tags Lista de cadenas. Todas las etiquetas asociadas al conjunto de cambios.

Unos experimentos sencillos nos mostraran que esperar cuando usamos estas palabras claves; puede ver los resul-

tados en la figura 11.1.

Como mencionamos anteriormente, la palabra clave de fecha no produce salida legible por un humano, debemos

tratarla de forma especial. Esto involucra usar un filtro, acerca de lo cual hay mas en la seccion 11.6.

1 $ hg log -r1 --template ’date: {date}\n’

2 date: 1234290210.00

3 $ hg log -r1 --template ’date: {date|isodate}\n’

4 date: 2009-02-10 18:23 +0000

11.5. Secuencias de Control

El motor de plantillas de Mercurial reconoce las secuencias de control mas comunmente usadas dentro de las

cadenas. Cuando ve un backslash (“\”), ve el caracter siguiente y sustituye los dos caracteres con un reemplazo

sencillo, como se describe a continuacion:

133

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 144/204

\\ Backslash, “\”, ASCII 134.

\n Nueva lınea, ASCII 12.

\r Cambio de lınea, ASCII 15.

\t Tab, ASCII 11.

\v Tab Vertical, ASCII 13.

\{ Corchete abierto, “{”, ASCII 173.

\} Corchete cerrado, “}”, ASCII 175.

Como se indico arriba, si desea que la expansion en una plantilla contenga un caracter literal “\”, “{”, o “{”, debe

escaparlo.

11.6. Uso de filtros con palabras claves

Algunos de los resultados de la expansion de la plantilla no son faciles de usar de inmediato. Mercurial le permite

especificar una cadena de filtros opcionales para modificar el resultado de expandir una palabra clave. Ya ha visto el

filtro usual isodate en accion con anterioridad para hacer legible la fecha.

A continuacion hay una lista de los filtros de Mercurial mas comunmente usados. Ciertos filtros pueden aplicarse

a cualquier texto, otros pueden usarse unicamente en circunstancias especıficas. El nombre de cada filtro esta seguido

de la indicacion de donde puede ser usado y una descripcion de su efecto.

addbreaks Cualquier texto. Anade una etiqueta XHTML “<br/>” antes del final de cada l ınea excepto en la final. Por

ejemplo, “foo\nbar” se convierte en “foo<br/>\nbar”.

age palabra clave date. Muestra la edad de la fecha, relativa al tiempo actual. Ofrece una cadena como “10 minutes”.

basename Cualquier texto, pero de utilidad sobre todo en palabras claves relativas a ficheros. Trata el texto como una

ruta, retornando el nombre base. Por ejemplo, “foo/bar/baz”, se convierte en “baz”.

date datepalabra clave. Mostrar la fecha en un formato similar a la orden

datede in a similar format to the Unix,pero con la zona horaria incluıda. Una cadena como “Mon Sep 04 15:13:13 2006 -0700”.

domain Cualquier texto, pero de mayor utilidad para la palabra clave author. Encuentra la primera cadena que luce

como una direccion de correo electronico, y extrae solamente el componente del dominio. Por ejemplo, de

“Bryan O’Sullivan <[email protected]>” se extrae “serpentine.com”.

email Cualquier texto, pero de mayor utilidad para la palabra clave author. Extrae la primera cadena que luce como

una direccion de correo. Por ejemplo, de “Bryan O’Sullivan <[email protected]>” extrae “[email protected]

escape Cualquier texto. Reemplaza los caracteres especiales de XML/XHTML: “&”, “<” y “>” con las entidades XML.

fill68 Cualquier texto. Lograr que el texto ocupe las primeras 68 columnas. Es util emplearlo antes de pasar el texto

por el filtro tabindent, y queremos que aun quepa en una ventana de fuente fija y 80 columnas.

fill76 Cualquier texto. Lograr que el texto quepa en 76 columnas.

firstline Cualquier texto. Mostrar la primera lınea de texto sin saltos de lınea.

hgdate date palabra clave. Mostrar la fecha como un par de numeros legibles. Muestra una cadena como “1157407993 25200”.

isodate date palabra clave. Mostrar la fecha como una cadena de texto en el formato. Muestra una cadena como

“2006-09-04 15:13:13 -0700”.

134

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 145/204

obfuscate Cualquier texto, pero de mayor utilidad para la palabra clave author. Muestra el campo de texto como una

secuencia de entidades XML. Esto ayuda a eliminar ciertos robots estupidos de adquisicion de correo.

person Cualquier texto, util sobre todo para la palabra clave author. Muestra el texto que hay antes de la direccion de

correo electronico. Por ejemplo, “Bryan O’Sullivan <[email protected]>” mostrarıa “Bryan O’Sullivan”.

rfc822date date palabra clave. Muestra una fecha con el mismo formato que se usa en los encabezados de correo. Mostrar ıa

una cadena como “Mon, 04 Sep 2006 15:13:13 -0700”.

short Hash del conjunto de cambios. Muestra la forma corta de un hash de conjunto de cambios, of a changeset hash,

p.e. una cadena hexadecimal de 12 bytes.

shortdate date palabra clave. Mostrar ano, mes y dıa de una fecha. Muestrauna cadena como “2006-09-04”.

strip Cualquier texto. Elimina todos los espacios en blanco al principio y al final de la cadena.

tabindent Cualquier texto. Muestra el texto con todas las lıneas excepto la primera que comience con el caracter tab.

urlescape Cualquier texto. Escapa todos los caracteres que se consideren como “especiales” por los parsers de URL. Por

ejemplo, foo bar se convierte en foo%20bar.

user Cualquier texto, util sobre todo para la palabra clave author. Retorna el “usuario” de una direccion de correo.

Por ejemplo, “Bryan O’Sullivan <[email protected]>” se convierte en “bos”.

Nota: Si trata de aplicar un filtro a una porcion de datos que no puede procesarse,

Mercurial fallara e imprimira una excepcion de Python. Por ejemplo, el tratar de

usar la salida de la palabra clave desc con el filtro isodate no resultara algo util.

11.6.1. Combinar filtros

Combinar filtros es para generar una salida en la forma como usted lo desea es muy sencillo. La cadena de fil-

tros siguientes arman una descripcion, despues aseguran que cabe limpiamente en 68 columnas, y las indenta con

8 caracteres (por lo menos en sistemas tipo Unix, en los que el tab por convencion se extiende en 8 caracteres).

1 $ hg log -r1 --template ’description:\n\t{desc|strip|fill68|tabindent}\n’

2

description:3 added line to end of <<hello>> file.

4

5 in addition, added a file with the helpful name (at least i hope

6 that some might consider it so) of goodbye.

Observe el uso de “\t” (un caracter tab) en la plantilla para forzar que la primera lınea se indente; esto es necesario

para lograr que la primera lınea luzca indentada; es necesario debido a que tabindent indenta todas las lıneas excepto

la primera.

Tenga en cuenta que el orden de los filtros importa. El primer filtro se aplica primero al resultado de la palabra clave;

el segundo al resultado de la aplicacion del primer filtro y ası sucesivamente. Por ejemplo, usar fill68|tabindent

es muy distinto al resultado de usar tabindent|fill68 .

11.7. De plantillas a estilos

Una plantilla provee una forma rapida y sencilla para dar formato a una salida. Las plantillas pueden volvers ver-

bosas, y es util poder darle un nombre a una plantilla. Un fichero de estilo es una plantilla con un nombre, almacenado

en un fichero.

Mas aun, al usar un fichero de estilo se dispara el poder del motor de plantillas en un nivel imposible de alcanzar

usando las opcion --template desde la lınea de ordenes.

135

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 146/204

1 $ hg log -r1 --template ’{author}\n’

2 Bryan O’Sullivan <[email protected]>

3 $ hg log -r1 --template ’{author|domain}\n’

4 serpentine.com

5 $ hg log -r1 --template ’{author|email}\n’

6 [email protected]

7 $ hg log -r1 --template ’{author|obfuscate}\n’ | cut -c-768 &#66;&#114;&#121;&#97;&#110;&#32;&#79;&#39;&#83;&#117;&#108;&#108;&#105;&#11

9 $ hg log -r1 --template ’{author|person}\n’

10 Bryan O’Sullivan

11 $ hg log -r1 --template ’{author|user}\n’

12 bos

13 $ hg log -r1 --template ’looks almost right, but actually garbage:{date}\n’

14 looks almost right, but actually garbage: 1234290210.00

15 $ hg log -r1 --template ’{date|age}\n’

16 1 second

17 $ hg log -r1 --template ’{date|date}\n’

18 Tue Feb 10 18:23:30 2009 +0000

19 $ hg log -r1 --template ’{date|hgdate}\n’

20 1234290210 021 $ hg log -r1 --template ’{date|isodate}\n’

22 2009-02-10 18:23 +0000

23 $ hg log -r1 --template ’{date|rfc822date}\n’

24 Tue, 10 Feb 2009 18:23:30 +0000

25 $ hg log -r1 --template ’{date|shortdate}\n’

26 2009-02-10

27 $ hg log -r1 --template ’{desc}\n’ | cut -c-76

28 added line to end of <<hello>> file.

29

30 in addition, added a file with the helpful name (at least i hope that some m

31 $ hg log -r1 --template ’{desc|addbreaks}\n’ | cut -c-76

32 added line to end of <<hello>> file.<br/>

33 <br/>

34 in addition, added a file with the helpful name (at least i hope that some m

35 $ hg log -r1 --template ’{desc|escape}\n’ | cut -c-76

36 added line to end of &lt;&lt;hello&gt;&gt; file.

37

38 in addition, added a file with the helpful name (at least i hope that some m

39 $ hg log -r1 --template ’{desc|fill68}\n’

40 added line to end of <<hello>> file.

41

42 in addition, added a file with the helpful name (at least i hope

43 that some might consider it so) of goodbye.

44 $ hg log -r1 --template ’{desc|fill76}\n’

45

added line to end of <<hello>> file.46

47 in addition, added a file with the helpful name (at least i hope that some

48 might consider it so) of goodbye.

49 $ hg log -r1 --template ’{desc|firstline}\n’

50 added line to end of <<hello>> file.

51 $ hg log -r1 --template ’{desc|strip}\n’ | cut -c-76

52 added line to end of <<hello>> file.

53

54 in addition, added a file with the helpful name (at least i hope that some m

55 $ hg log -r1 --template ’{desc|tabindent}\n’ | expand | cut -c-76

56 added line to end of <<hello>> file.

57

58 in addition, added a file with the helpful name (at least i hope tha59 $ hg log -r1 --template ’{node}\n’

60 522d8d7a8fda9a24dcac9c5ccfcca067b933220b

136

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 147/204

11.7.1. Los ficheros de estilo mas sencillos

Nuestro fichero sencillo de estilo contiene una sola lınea:

1 $ echo ’changeset = "rev: {rev}\n"’ > rev

2 $ hg log -l1 --style ./rev

3 rev: 3

Se le indica a Mercurial, “si esta imprimiendo un conjunto de cambios, use el texto de la derecha como la plantilla”.

11.7.2. 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.

Se ignoran el espacio en blanco circundante.

Se omiten las lıneas en blanco.

Si una lınea comienza con los caracteres “#” o “;”, la lınea completa se trata como un comentario, y se omitecomo si fuera vacıa.

Una lınea comienza con una palabra clave. Esta debe comenzar con una caracter alfabetico o una raya al piso,

y puede contener subsecuentemente cualquier caracter alfanumerico o una raya al piso. (En notacion de expre-

siones regulares debe coincidir con [A-Za-z_][A-Za-z0-9_]* .)

El proximo elemento debe ser un caracter “=”, que puede estar precedido o seguido por una cantidad arbitraria

de espacio.

Si el resto de la lınea comienza y termina con caracteres encerrados entre caracteres de comillas (bien sea

sencillas o dobles), se trata como cuerpo de la plantilla.

Si el resto de la lınea no comienza con una comilla, se trata como el nombre de un fichero; los contenidos de

este fichero se leeran y se usaran como cuerpo de la plantilla.

11.8. Ejemplos de ficheros de estilos

Para ilustrar la creacion de un fichero de estilo, construiremos algunos ejemplos. En lugar de ofrecer un fichero

completo de estilo y analizarlo, replicaremos el proceso usual de desarrollo de un fichero de estilo comenzando con

algo muy sencillo, y avanzando por una serie de ejemplos sucesivos m as completos.

11.8.1. Identificar equivocaciones en ficheros de estilo

Si Mercurial encuentra un problema en un fichero de estilo en el cual usted est a trabajando, imprime un mensaje

de error suscinto, cuando usted identifique lo que significa, resulta muy util.

1 $ cat broken.style

2 changeset =

Tenga en cuenta que broken.style trata de definir la palabra clave changeset, pero omite dar un contenido para

esta. Cuando se le indica a Mercurial que use este fichero de estilo, se queja inmediatamente.

137

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 148/204

1 $ hg log -r1 --style broken.style

2 abort: broken.style:1: parse error

Este mensaje de error luce intimidante, pero no es muy dif ıcil de seguir:

El primer componente es la forma como Mercurial dice “me rindo”.

1 abort: broken.style:1: parse error

A continuacion viene el nombre del fichero que contiene el error.

1 abort: broken.style:1: parse error

Siguendo el nombre del fichero viene el numero de lınea en la que se encontro el error.

1 abort: broken.style:1: parse error

Finalmente, la descripcion de lo que fallo.

1 abort: broken.style:1: parse error

La descripcion del problema no siempre es clara (como en este caso), pero aunque sea cr ıptica, casi siempre es

trivial la inspeccion visual de la lınea en el fichero de estilo y encontrar lo que est a mal.

11.8.2. Identificar de forma unica un repositorio

Si desea identificar un repositorio de Mercurial “de forma unica” con una cadena corta como identificador, puede

usar la primera revision en el repositorio.

1 $ hg log -r0 --template ’{node}’

2 92cb4692d38c537be0935f906eeff2a47033600c

No es garantıa de unicidad, pero no es utill en ciertos casos: many cases.

No funcionara en un repositorio completamente vacıo, porque un repositorio ası no tiene una revision zero.

Tampoco funcionara en caso (muy raro) cuando el repositorio sea una fusion de dos repositorios independientes

y tiene los dos directorios por ahı.

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.

Como una parte del par { ID repositorio, ID revisi´ on}. Almacene esta informacion de forma independiente cuan-

do ejecute construcciones automatizadas u otras actividades, de forma que pueda “reconstruir” posteriormente

en caso de ser necesario.

138

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 149/204

11.8.3. Mostrando salida parecida a Subversion

Intentemos emular la salida usual que usa otro sistema de control de revisiones, Subversion.

1 $ svn log -r9653

2 ------------------------------------------------------------------------

3 r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines

4

5 On reporting a route error, also include the status for the error,

6 rather than indicating a status of 0 when an error has occurred.

7

8 Signed-off-by: Sean Hefty <[email protected]>

9

10 ------------------------------------------------------------------------

Dado que la salida de Subversion es sencilla, es f acil copiar y pegar una porcion de su salida en un fichero, y

reemplazar el texto producido previamente por Subversion con valores base que quisieramos ver expandidos.

1 $ cat svn.template

2 r{rev} | {author|user} | {date|isodate} ({date|rfc822date})

3

4 {desc|strip|fill76}5

6 ------------------------------------------------------------------------

Esta plantilla difiere en algunos detalles de la salida producida por Subversion:

Subversion imprime una fecha “legible” (el “Wed, 27 Sep 2006” en el ejemplo de salida anterior) en parente-

sis. El motor de plantillas de Mercurial no ofrece una forma sencilla de desplegar una fecha en este formato sin

imprimir tambien la hora y la zona horaria.

Emulamos las lıneas de “separacion” de subversion con caracteres “-” en una lınea. Usamos la palabra clave

header del motor de plantillas para imprimir una lınea de separacion como la primera lınea de salida (ver mas

abajo), para lograr una salida similara a la de Subversion.

La salida de subversion incluye un conteo en el encabezado del numero de lıneas en el mensaje de consinacion.

No podemos replicarlo en Mercurial; el motor de plantilla no ofrece en la actualidad un filtro que cuente la

cantidad de objetos que se le pasen.

No me tomo mas de un minuto o dos de trabajo para reemplazar texto literal de un ejemplo de salida de la salida

de Subversion con ciertas palabras claves y filtros para ofrecer la plantilla anterior. El fichero de estilo se refiere

sencillamente a la plantilla.

1 $ cat svn.style

2 header = ’------------------------------------------------------------------------\n\n’

3 changeset = svn.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”, pero harıa muy dif ıcil de leer el fichero de estilos. La facilidad

para leer es importante cuando esta decidiendo si un texto pertenece a un fichero de estilo o a un fichero de plantilla

incluıdo en el estilo. Si el fichero de estilo luce muy grande o complicado, si inserta una pieza de texto literal, mejor

coloquelo en una plantilla.

139

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 150/204

Capıtulo 12

Administracion de cambios con Colas de

Mercurial

12.1. El problema de la administracion de parches

Un escenario frecuente: usted necesita instalar un paquete de software desde las fuentes, pero encuentra un fallo

que debe arreglar antes de poder comenzar a usarlo. Hace sus cambios, y se olvida del paquete por un tiempo, unos

meses despues necesita actualizar a una nueva version del paquete. Si la nueva version del paquete todavıa tiene el

fallo, debe extraer su arreglo del arbol de fuentes anteriores y aplicarlo a la nueva versi on. Una tarea tediosa en la cual

es f acil equivocarse.

Este es un caso simple del problema del “manejo de parches”. Usted tiene un arbol de fuentes del “mantenedor

principal” que no puede cambiar: necesita hacer algunos cambios locales sobre el arbol principal; y desearıa poder

mantener tales cambios separados, de forma tal que pueda aplicarlos a versiones m as nuevas del arbol principal.

El problema de administracion de parches surge en muchas situaciones. Probablemente la mas visible es cuando un

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.Cuando hay pocos cambios por mantener, es muy sencillo administrar un solo parche con los programas est andar

diff y patch (ver la seccion 12.4 para ver como emplear tales herramientas). Cuando la cantidad de cambios comienza

a crecer, tiene sentido mantener parches como “porciones de trabajo” individual, de forma que cada cambio contiene

solamente un arreglo de un fallo (el parche puede modificar varios ficheros, pero est a “haciendo una sola cosa”),

y puede tener cierta cantidad de tales parches para diferentes fallos y cambios locales. En esta situacion, si envıa un

parche que arregla un fallo a los mantenedores principales de un paquete y ellos incluyen su arreglo en una publicaci on

posterior, puede deshacerse de tal parche cuando se actualice a la nueva versi on.

Mantener un solo parche frente a un arbol principal es algo tedioso y es facil equivocarse, pero no es difıcil.

Aunque, la complejidad del problema crece rapidamente a medida que la cantidad de parches que tiene que mantener

crece. Con mas que una pequena cantidad de cambios, entender cuales ha aplicado se convierte de algo desordenado a

algo avasallante.

Afortunadamente Mercurial provee una extension poderos: Colas de Mercurial (o simplemente “MQ”), que sim-

plifica en gran medida el problema de administracion de parches.

12.2. La prehistoria de las Colas de Mercurial

A finales de los 90s, muchos desarrolladores del nucleo de Linux comenzaron a mantener “series de parches”

que modificaron el comportamiento del nucleo de Linux. Algunos se enfocaban en estabilidad, otros en aumentar las

caracterısticas, y otros un poco mas especulativos.

140

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 151/204

Los tamanos de las series de parches crecieron rapidamente. En el 2002, Andrew Morton publico algunos guiones

de lınea de ordenes que estuvo usando para automatizar la tarea de administrar su cola de parches. Andrew us o ex-

itosamente tales guiones para administrar centenas (a veces millares) de parches en el n ucleo de Linux.

12.2.1. Trabajar parches con quilt

A comienzos del 2003, Andreas Gruenbacher y Martin Quinson tomaron la aproximaci on de los guiones de An-drew y publicaron una herramienta llamada “patchwork quilt” [AG], o simplemente “quilt” (ver [Gru05] el paper que

lo describe). Dado que quilt automatizaba sustancialmente la administracion de parches, fue adoptado en gran medida

por desarrolladores de programas abiertos.

Quilt maneja una pila de parches sobre un arbol de directorios. Para comenzar, usted le indica a quilt que administre

un arbol de directorios, le indica que ficheros manejar; Este almacena los nombres y los contenidos de estos ficheros.

Para arreglar un fallo, usted crea un nuevo parche (con una sola orden), edita los ficheros que esta arreglando y

“refresca” el parche.

El paso de refresco hace que quilt revise el arbol de directorios; actualiza el parche con todos los cambios que usted

haya hecho. Puede crear otro parche sobre el primero, que hara seguimiento de los cambios requeridos para modificar

el arbol desde “el arbol con un parch aplicado” a un “arbol con dos parches aplicados”.

Usted puede elegir  que cambios desea aplicar al arbol. Si “pop”1 un parche, los cambios hechos por tal parchve

desapareceran del arbol de directorios. Quilt recuerda que parches ha sacado, para que pueda “introducirlos”2 posteri-

ormente, ası el arbol de directorios se restaurara con las modificaciones que vienen del parche. Lo mas importante esque puede ejecutar la orden “refresh” en cualquier momento, y el ultimo parche sera actualizado. Esto significa que

puede, en cualquier momento, cambiar que parches seran aplicados y que modificaciones hacen ellos.

Quilt no tiene nada que ver con herramientas de control de versiones, y puede trabajar bien sobre un conjunto de

fuentes que viene de un fichero comprimido y empaquetado o una copia de trabajo de Subversion.

12.2.2. Pasar de trabajo con parches con Quilt hacia Colas de Mercurial

A mediados de 2005, Chris Mason tomo las caracterısticas de quilt y escribio una extension que llamo Colas de

Mercurial3, que proporciono un comportamiento a Mercurial al estilo quilt.

La diferencia clave entre quilt y MQ es que quilt no sabe nada acerca del sistema de control de revisiones, mientras

que MQ esta integrado con Mercurial. Cada parche que usted introduce se representa como un conjunto de cambios

en Mercurial. Si sustrae un parche, el conjunto de cambios desaparece.4

Dado que quilt no se preocupa por las herramientas de control de revisiones, continua siendo una porcion desoftware tremendamente util para aquellas situaciones en las cuales no puede usar Mercurial y MQ.

12.3. La gran ventaja de MQ

No puedo sobreestimar el valor que MQ ofrece en la unificacion de parches y el control de revisiones.

La principal razon por la cual los parches han persistido en el mundo del software libre y de fuentes abiertas–a

pesar de la creciente disponibilidad de herramientas poderosas de control de revisiones– es la agilidad  que ofrecen.

Las herramientas tradicionales de control de revisiones llevan un registro permanente e irreversible de todo lo

que usted hace. A pesar de que esto tiene gran valor, tambien es bastante sutil. Si requiere realizar un experimento

((((wild-eyed)))), debe ser cuidadoso en como lo hace, o puede dejar trazas innecesarias–o peor a un, desconcertantes

o desestabilizantes— de los pasos y errores en el registro de revisiones de forma permanente.

En contraste, con la cohesion de MQ con el control de revisiones distribuidos y los parches, resulta mas sencilloaislar su trabajo. Sus parches viven encima del historial de revisiones normales, y puede hacer que ellos desaparezcan

1N. del T. saca2N. del T. push3N. del T. Mercurial Queues4N. del T. introduce originalmente es push y pop es sustraer en este contexto, usaremos el original en ingl es cuando encontremos que facilita la

comprension

141

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 152/204

o reaparezcan cuando lo desee. Si no le gusta un parche, puede desecharlo. Si un parche no satisface todo lo que usted

desea, puede arreglarlo—tantas veces como lo requiera, hasta que lo haya refinado lo suficiente hacia sus expectativas.

Por ejemplo, la integracion de parches con el control de revisiones hace que el entender los parches y revisar sus

efectos—y sus interacciones con el codigo en el cual estan enlazados— sea mucho mas sencillo. Dado que todo parche

que se aplique tiene un conjunto de cambios asociado, puede usar “ hg log filename” para ver que conjuntos de

cambios y parches afectaron un fichero. Puede usar la orden bisect para hacer una busqueda binaria sobre todos los

conjuntos de cambios y parches aplicados para ver donde se introdujo un fallo o donde fue arreglado. Puede usar laorden “hg annotate” para ver que conjuntos de cambios o parches modificaron una lınea particular de un fichero

fuente. Y mucho mas.

12.4. Entender los parches

Dado que MQ no esconde su naturaleza parche-centrica, es muy util para entender de que se tratan los parches, y

un poco acerca de las herramientas que trabajan con ellos.

La orden de Unix tradicional diff compara dos ficheros, e imprime una lista de diferencias de sus lıneas. La orden

patch entiende esas diferencias como modificaciones para construir un fichero. Vea en la figura 12.1 un ejemplo

sencillo de tales ordenes en accion.

1 $ echo ’this is my original thought’ > oldfile2 $ echo ’i have changed my mind’ > newfile

3 $ diff -u oldfile newfile > tiny.patch

4 $ cat tiny.patch

5 --- oldfile 2009-02-10 18:23:25.000000000 +0000

6 +++ newfile 2009-02-10 18:23:25.000000000 +0000

7 @@ -1 +1 @@

8 -this is my original thought

9 +i have changed my mind

10 $ patch < tiny.patch

11 patching file oldfile

12 $ cat oldfile

13 i have changed my mind

Figura 12.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”; no hay

diferencia entre un parche y un diff. (Usaremos el termino “parche”, dado que es el que mas comunmente se usa.)

Un parche puede comenzar con un texto arbitrario; la orden patch ignora este texto, pero MQ lo usa como el

mensaje de consignacion cuando se crean conjuntos de cambios. Para encontrar el inicio del contenido de un parche,

la orden patch busca la primera lınea que comience con la cadena “diff -”.

MQ trabaja con diffs unificados (patch acepta varios formatos de diff adicionales, pero MQ no). Un diff unificado

contiene dos clases de encabezados. El encabezado de fichero describe el fichero que se esta modificando; contiene el

nombre del fichero a modificar. Cuando patch ve un nuevo encabezado de fichero, busca un fichero con ese nombre

para modificarlo.

Despues del encabezaado vienen varios trozos. Cada trozo comienza con un encabezado; que identifica el rango de

lıneas del fichero que el trozo debe modificar. Despues del encabezado, un trozo comienza y termina con unas pocas

lıneas (usualmente tres) de texto del fichero que no han sido modificadas; las cuales llamamos el contexto del trozo. Si

solamente hay una pequena cantidad de contexto entre trozos sucesivos, diff no imprime un nuevo encabezado para

el trozo, continua integrando los trozos, con unas lıneas de contexto entre las modificaciones.

Cada lınea de contexto comienza con un caracter de espacio. En el trozo, si una l ınea comienza con “-” significa

“elimine esta lınea”, si la lınea comienza con un “+” significa “inserte esta lınea”. Por ejemplo, una lınea que se

142

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 153/204

modifica se representa con una lınea eliminada y una lınea insertada.

Retomaremos aspectos mas sutiles acerca de parches posteriormente (en la seccion 12.6), pero en el momento

usted ya deberıa tener suficiente informacion para usar MQ.

12.5. Comenzar a usar Colas de Mercurial

Dado que MQ esta implementado como una extension, debe habilitarla explıcitamente antes de comenzar a usarla.

(No necesita descargar nada; MQ viene con la distribucion estandar de Mercurial.) Para habilitar MQ, edite su fichero

˜/.hgrc, y anada las lıneas de la figura 12.5.

1 [extensions]

2 hgext.mq =

Figura 12.2: Lıneas a anadir en ˜/.hgrc para habilitar la extension MQ

Cuando la extension este habilitada, apareceran varios comandos. Para verificar que la extension esta trabajando,

puede usar “hg help” para ver si la orden “hg qinit” esta disponible; vea un ejemplo en la figura 12.3.

1 $ hg help qinit

2 hg qinit [-c]

3

4 init a new queue repository

5

6 The queue repository is unversioned by default. If -c is

7 specified, qinit will create a separate nested repository

8 for patches (qinit -c may also be run later to convert

9 an unversioned patch repository into a versioned one).

10 You can use qcommit to commit changes to this queue repository.

11

12 options:

13

14 -c --create-repo create queue repository

15

16 use "hg -v help qinit" to show global options

Figura 12.3: Como verificar que MQ esta habilitado

Puede usar MQ en cualquier  repositorio de Mercurial, y sus comandos solamente operaran con tal repositorio.

Para comenzar, basta con preparar el repositorio con la orden “hg qinit” (ver la figura 12.4). Esta orden crea un

directorio vacıo llamado .hg/patches, donde MQ mantendra sus metadatos. Como otras ordenes de Mercurial, la

orden “hg qinit” no imprime nada cuando es exitosa.

12.5.1. Crear un nuevo parche

Para comenzar a trabajar en un nuevo parche use la orden “hg qnew”. Esta orden recibe un argumento, el nombre

del parche a crear. MQ lo usara como el nombre del fichero en el directorio .hg/patches, como puede apreciarlo en

la figura 12.5.

143

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 154/204

1 $ hg init mq-sandbox

2 $ cd mq-sandbox

3 $ echo ’line 1’ > file1

4 $ echo ’another line 1’ > file2

5 $ hg add file1 file2

6 $ hg commit -m’first change’

7 $ hg qinit

Figura 12.4: Preparar un repositorio para usar MQ

1 $ hg tip

2 changeset: 0:90039acadb36

3 tag: tip

4 user: Bryan O’Sullivan <[email protected]>

5 date: Tue Feb 10 18:23:27 2009 +0000

6 summary: first change

7

8

$ hg qnew first.patch9 $ hg tip

10 changeset: 1:495236f727e1

11 tag: qtip

12 tag: first.patch

13 tag: tip

14 tag: qbase

15 user: Bryan O’Sullivan <[email protected]>

16 date: Tue Feb 10 18:23:27 2009 +0000

17 summary: [mq]: first.patch

18

19 $ ls .hg/patches

20 first.patch series status

Figura 12.5: Crear un nuevo parche

Tambien hay otros dos nuevos ficheros en el directorio .hg/patches: series y status. El fichero series lista

todos los parches de los cuales MQ tiene noticia para este repositorio, con un parche por l ınea. Mercurial usa el fichero

status para mantener registros interns; da seguimiento a todos los parches que MQ ha aplicado en el repositorio.

Nota: En ciertas ocasiones usted querra editar el fichero series a mano; por

ejemplo, cambiar el orden en que se aplican ciertos parches. A pesar de esto, es

una mala idea editar manualmente el fichero status, dado que es f acil desorientar

a MQ acerca de lo que esta pasando.

Una vez que haya creado un nuevo parche, puede editar los ficheros en el directorio de trabajo, como lo harıa

usualmente. Toda las ordenes que de a Mercurial, tales como “hg diff” y “hg annotate”, trabajaran de la mismaforma como lo han hecho antes.

12.5.2. Refrescar un parche

Cuando usted llega a un punto en el cual desea guardar su trabajo, use la orden “ hg qrefresh” (figura 12.5) para

actualizar el parche en el cual esta trabajando. Esta orden almacena los cambios que haya hecho al directorio actual de

144

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 155/204

trabajo en su parche, y almacena el conjunto de cambios correspondiente que contiene los cambios.

1 $ echo ’line 2’ >> file1

2 $ hg diff

3 diff -r 495236f727e1 file1

4 --- a/file1 Tue Feb 10 18:23:27 2009 +0000

5 +++ b/file1 Tue Feb 10 18:23:27 2009 +00006 @@ -1,1 +1,2 @@

7 line 1

8 +line 2

9 $ hg qrefresh

10 $ hg diff

11 $ hg tip --style=compact --patch

12 1[qtip,first.patch,tip,qbase] 131b8ed49ec4 2009-02-10 18:23 +0000 bos

13 [mq]: first.patch

14

15 diff -r 90039acadb36 -r 131b8ed49ec4 file1

16 --- a/file1 Tue Feb 10 18:23:27 2009 +0000

17 +++ b/file1 Tue Feb 10 18:23:27 2009 +0000

18 @@ -1,1 +1,2 @@

19 line 1

20 +line 2

21

Figura 12.6: Refrescar un parche

Puede ejecutar la orden “hg qrefresh” tan seguido como quiera, y es una buena forma de “colocar marcas” a su

trabajo. Refresque su parche en momentos oportunos; intente un experimento; si el experimento no funciona, Use “hg

revert” sobre sus modificaciones para volver al refresco anterior.

12.5.3. Aplicar un parche tras otro y dar seguimiento

Cuando haya terminado de trabajar en un parche, o necesite trabajar en otro, puede usar la orden “ hg qnew” para

crear un nuevo parche. Mercurial aplicara este parche sobre su parche anterior. Para un ejemplo, ver la figura 12.8.

Note que el parche contiene los cambios en nuestro parche anterior como parte de su contexto (lo ver a mas claramente

en la salida de “hg annotate”).

Hasta ahora, con excepcion de “hg qnew” y “hg qrefresh”, hemos sido cuidadosos para aplicar unicamente

ordenes usuaales de Mercurial. De todas maneras, MQ ofrece muchos comandos que son mas sencillos de usar cuando

este pensando acerca de parches, como se puede ver en la figura 12.9:

La orden “hg qseries” lista cada parche del cual MQ tiene noticia en este repositorio, desde el m as antiguo

hasta el mas nuevo (El ultimo creado).

La orden “hg qapplied” lista cada parche que MQ haya aplicado en este repositorio, de nuevo, desde el mas

antiguo hasta el mas nuevo (El aplicado mas recientemente).

12.5.4. Manipular la pila de parches

La discusion previa indico que debe haber una diferencia entre los parches “conocidos” y “aplicados”, y efectiva-

mente la hay. MQ puede manejar un parche sin que este haya sido aplicado al repositorio.

145

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 156/204

1 $ echo ’line 3’ >> file1

2 $ hg status

3 M file1

4 $ hg qrefresh

5 $ hg tip --style=compact --patch

6 1[qtip,first.patch,tip,qbase] 4fef714d728c 2009-02-10 18:23 +0000 bos

7 [mq]: first.patch8

9 diff -r 90039acadb36 -r 4fef714d728c file1

10 --- a/file1 Tue Feb 10 18:23:27 2009 +0000

11 +++ b/file1 Tue Feb 10 18:23:27 2009 +0000

12 @@ -1,1 +1,3 @@

13 line 1

14 +line 2

15 +line 3

16

Figura 12.7: Refrescar un parche muchas veces para acumular cambios

Un parche aplicado tiene su correspondiente conjunto de cambios en el repositorio, y los efectos del parche y

el conjunto de cambios son visibles en el directorio de trabajo. Puede deshacer la aplicacion de un parche con la

orden “hg qpop”. MQ sabe acerca de, o maneja un parche sustraıdo, pero el parche ya no tendra un conjunto de

cambios correspondientes en el repositorio, y el directorio de trabajo no contendra los cambios hechos por el parche.

La figura 12.10 ilustra la diferencia entre parches aplicados y seguidos.

Puede reaplicar un parche no aplicado o sustraıdo con la orden “hg qpush”. Esto crea un nuevo conjunto de

cambios correspondiente al parche, y los cambios del parche estaran presentes de nuevo en el directorio de trabajo.

Vea ejemplos de “hg qpop” y “hg qpush” en accion en la figura 12.11. Vea que hemos sustraıdo uno o dos parches,

la salida de“hg qseries” continua igual, mientras que “hg qapplied” ha cambiado.

12.5.5. Introducir y sustraer muchos parchesMientras que “hg qpush” y “hg qpop” operan sobre un unico parche cada vez, puede introducir y sustraer varios

parches de una vez. La opcion -a de “hg qpush” introduce todos los cambios que no hayan sido aplicados, mientras

que la opcion -a de “hg qpop” sustrae todos los cambios aplicados. (Vea la seccion 12.7 mas adelante en la cual se

explican otras formas de de introducir y sustraer varios cambios.)

12.5.6. Medidas de seguridad y como saltarlas

Muchas ordenes MQ revisan el directorio de trabajo antes de hacer cualquier cosa, y fallan si encuentran alguna

modificacion. Lo hacen para garantizar que usted no pierda cambio alguno de los que haya hecho, pero que no hayan

sido incorporados en algun parche. La figura 12.13 ilusta esto; la orden “hg qnew” no creara un nuevo parche si hay

cambios notorios, causados en este caso por aplicado la orden “hg add” a file3.

Las ordenes que revisan el directorio actual cuentan con una opcion “Se lo que estoy haciendo”, que siempre

esta nombrada como -f. El significado exacto de -f depende de la orden. Por ejemplo, “hg qnew -f” incorporaran

cualquier cambio notorio en el nuevo parche que crea pero “hg qpop -f” revertira las modificaciones a cualquier

fichero que haya sido afectado por el parche que esta siendo sustraıdo. ¡Asegurese de leer la documentacion de la

opcion -f de cada comando antes de usarla!

146

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 157/204

1 $ hg qnew second.patch

2 $ hg log --style=compact --limit=2

3 2[qtip,second.patch,tip] 17da5d88f25b 2009-02-10 18:23 +0000 bos

4 [mq]: second.patch

5

6 1[first.patch,qbase] 4fef714d728c 2009-02-10 18:23 +0000 bos

7 [mq]: first.patch8

9 $ echo ’line 4’ >> file1

10 $ hg qrefresh

11 $ hg tip --style=compact --patch

12 2[qtip,second.patch,tip] 7cf293b98474 2009-02-10 18:23 +0000 bos

13 [mq]: second.patch

14

15 diff -r 4fef714d728c -r 7cf293b98474 file1

16 --- a/file1 Tue Feb 10 18:23:27 2009 +0000

17 +++ b/file1 Tue Feb 10 18:23:28 2009 +0000

18 @@ -1,3 +1,4 @@

19 line 1

20 line 221 line 3

22 +line 4

23

24 $ hg annotate file1

25 0: line 1

26 1: line 2

27 1: line 3

28 2: line 4

Figura 12.8: Aplicar un parche despues del primero

12.5.7. Trabajar con varios parches a la vez

La orden “hg qrefresh” siempre refresca el ´ ultimo parche aplicado. Esto significa que usted puede suspender su

trabajo en un parche (refrescandolo), sustraerlo o introducirlo para lograr que otro parche este de ultimo y trabajar en

ese parche por un rato.

A continuacion un ejemplo que ilustra como puede usar esta habilidad. Digamos que esta desarrollando una nueva

caracterıstica en dos parches. El primero es un cambio en la parte fundamental de su programa, y el segundo–sobre

el primero—cambia la interfaz de usuario para usar el codigo que ha anadido a la parte fundamental. Si ve que hay

un fallo en la parte fundamental mientras esta trabajando en el parche de UI5, es f acil arreglar la parte fundamental.

Simplemente use “hg qrefresh” sobre el parche de la UI para guardar los cambios de su trabajo en progreso, y use

“hg qpop” para sacar sustraer el parche de la parte fundamental. Arregla el fallo sobre 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.

5N. del T. Interfaz de Usuario, User Interface en ingles

147

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 158/204

1 $ hg qseries

2 first.patch

3 second.patch

4 $ hg qapplied

5 first.patch

6 second.patch

Figura 12.9: Entender la pila de parches con “hg qseries” y “hg qapplied”

prevent−compiler−reorder.patch

namespace−cleanup.patch

powerpc−port−fixes.patc

report−devinfo−correctly.patch

{

{

presente en la serie,pero no aplicado

parches aplicados,Conjuntos de cambios presentes

parche aplicadomás recientemente 201ad3209902

126b84e593ae

a655daf15409

e50d59aaea3a

forbid−illegal−params.patch

fix−memory−leak.patc

Figura 12.10: Parches aplicados y no aplicados en la pila de parches de MQ

12.6. Mas acerca de parches

MQ usa la orden GNU patch para aplicar los parches, por lo tanto es util conocer ciertos detalles de como trabaja

patch, y tambien acerca de los parches.

12.6.1. La cantidad de franjas

Si ve el encabezado de un parche, notara que la ruta al fichero tiene un componente adicional al principio, que no

esta presente en la ruta. Esta es una traza de c omo generaba anteriormente los parches la gente (algunos aun lo hacen,

pero es raro con las herramientas de control de revisiones del actuales).

Alicia desempaquetarıa un comprimido, editarıa sus ficheros, y querrıa crear un parche. Por lo tanto ella renom-

brarıa su directorio de trabajo, desempacarıa el comprimido de nuevo (para lo cual necesito el renombramiento), y

usarıa las opciones -r y -N de diff para generar recursivamente un parche entre el directorio original y el modificado.

El resultado serıa que el nombre del directorio original estarıa al principio de toda ruta en cada encabezado de fichero,

y el nombre del directorio modificado estarıa al frente de la porcion derecha de la ruta del fichero.

Como alguien que reciba un parche de Alicia en la red podrıa obtener dos directorios, uno original y el otro modi-

ficado con exactamente los mismos nombres, la orden patch tiene la opcion -p que indica la cantidad de componentes

de la ruta a eliminar cuando se vaya a aplicar el parche. Este numero se llama la cantidad de eliminaciones.

La opcion con “-p1” significa “elimine uno”. Si patch ve un nombre de fichero foo/bar/baz en el encabezadodel fichero, eliminara foo y tratara de parchar un fichero llamado bar/baz. (Hablando estrictamente, la cantidad de

eliminaciones se refiere a la cantidad de separadores de ruta (y los componentes que vayan con ellos) a eliminar. Si el

contador es uno volvera foo/bar en bar, pero /foo/bar (note la barra extra) en foo/bar.)

La cantidad a eliminar“estandar” para parches es uno; casi todos los parches contienen un componente inicial de

la ruta que necesita ser eliminado. La orden “hg diff” de Mercurial genera nombres de ruta de esta forma, y la orden

“hg import” y MQ esperan parches que tengan a uno como cuenta de eliminaciones.

148

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 159/204

1 $ hg qapplied

2 first.patch

3 second.patch

4 $ hg qpop

5 Now at: first.patch

6 $ hg qseries

7 first.patch8 second.patch

9 $ hg qapplied

10 first.patch

11 $ cat file1

12 line 1

13 line 2

14 line 3

Figura 12.11: Modificar la pila de parches aplicados

1

$ hg qpush -a2 applying second.patch

3 Now at: second.patch

4 $ cat file1

5 line 1

6 line 2

7 line 3

8 line 4

Figura 12.12: Pushing all unapplied patches

Si recibe un parche de alguien de quien desea adicionar adicionar a su cola de parches, y el parche necesita unacuenta de eliminacion que no sea uno, no podra aplicar “hg qimport” en primera medida, porque “hg qimport”

no tiene todavıa una opcion -p option (ver Fallo de Mercurial No. 311). Lo mejor que puede hacer es aplicar “hg

qnew” por su cuenta, y despues usar “patch -pN ” para aplicar tal parche, seguido de “hg addremove” para tener en

cuenta cualquier fichero adicionado o eliminado por el parche, seguido de “hg qrefresh”. Esta complejidad puede

ser innecesaria; consulte Fallo de Mercurial No. 311 para mas informacion.

12.6.2. Estrategias para aplicar parches

Cuando patch aplica un trozo, intenta varias estrategias sucesivas que decrecen en precision para intentar aplicarlo.

Esta tecnica de pruebas y error aveces permite que un parche que fue generado contra una version anterior de un

fichero, sea aplicada sobre una version mas nueva del mismo.

Primero patch intenta una correspondencia perfecta donde los numeros de lınea, el contexto y el texto a modificar

deben coincidir perfectamente. Si no lo logra, intenta encontrar una correspondencia exacta del contexto, sin tener encuenta el numero de lınea. Si es exitoso, imprime una lınea indicando que el trozo fue aplicado, pero a un corrimiento

del numero de lınea original.

Si falla la correspondencia por contexto, patch elimina la primera y la ultima lınea del contexto, e intenta una

correspondencia reducida del contexto. Si el trozo con contexto reducido es exitoso, imprime un mensaje indicando

que aplico el trozo con un factor difuso (el numero despues del factor difuso indica cuantas lıneas de contexto patch

tuvo que eliminar antes de aplicar el parche).

149

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 160/204

1 $ echo ’file 3, line 1’ >> file3

2 $ hg qnew add-file3.patch

3 $ hg qnew -f add-file3.patch

4 abort: patch "add-file3.patch" already exists

Figura 12.13: Crear un parche a la fuerza

Cuando ninguna de estas tecnicas funciona, patch imprime un mensaje indicando que el trozo en cuestion se

desecho. Almacena los trozos desechados (tambien llamados “descartados”) en un fichero con el mismo nombre, y la

extension .rej anadida. Tambien almacena una copia igual al fichero original con la extension .orig; la copia del

fichero sin extension contendra cualquier cambio hecho por los trozos que sı se aplicaron sin problema. Si usted tiene

un parche que modifica foo con seis trozos, y uno de ellos falla al aplicarse, tendra : un fichero original foo.orig, un

fichero foo.rej que contiene el trozo, y foo, que contiene los cambios que se aplicaron por los cinco trozos exitosos.

12.6.3. Algunos detalles de la representacion de parches

Hay ciertas cosas utiles por saber acerca de como trabaja patch con los ficheros:

Deberıa ser obvio que patch no puede manipular ficheros binarios.

No se preocupa por el bit ejecutable; crea ficheros nuevos en modo lectura, pero no ejecutable.

patch intenta eliminar un fichero como una diferencia entre el fichero a eliminar y un fichero vac ıo. Y por lo

tanto su idea de “Borre este fichero” deberıa pensarse como “toda lınea de este fichero fue eliminada” en un

parche.

Trata la adicion de un fichero como un diff entre un fichero vacıo y el fichero a ser adicionado. Por lo tanto en

un parche su idea de “Anadı este fichero” se verıa como “toda lınea de este fichero fue anadida”.

Trata el renombramiento de un fichero como la eliminacion del nombre anterior y la adicion del nuevo nombre.

Esto significa que los ficheros renombrados dejan un rastro grande en los parches. (Tenga en cuenta que Mercu-

rial no trata de inferir cuando los ficheros han sido renombrados o copiados en un parche en este momento.)

patch no puede representar ficheros vacıos, por lo tanto no puede usar un parche para representar la nocion

“Anadı este fichero vacıo al arbol”.

12.6.4. Cuidado con los difusos

Cuando aplique un trozo con un corrimiento, o con un factor difuso, aveces ser a taotalmente exitoso, tales tecnicas

inexactas dejan claramente la posibilidad de corromper el fichero parchado. Los casos m as tıpicos involucran aplicar

un parche dos veces o en un sitio incorrecto del fichero. Si patch o “hg qpush” llegan a mencionar un corrimiento o

un factor difuso, deberıa asegurarse que los ficheros modificados esten correctos despues del suceso.

Casi siempre es buena idea refrescar un parche que fue aplicado con un corrimiento o un factor difuso; refrescar el

parche genera nueva informacion de contexto que permitira aplicarlo limpiamente. Digo “casi siempre,” no “siempre”,

puesto que en ciertas ocasiones refrescar un parche lo hara fallar frente a una revision diferente del fichero. En algunos

casos, como por ejemplo, cuando usted esta manteniendo un parche que debe estar encima de multiples revisiones de

un arbol de fuentes, es aceptable tener un parche aplicado algo difuso, siempre que haya verificado los resultados del

proceso de parchar.

150

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 161/204

12.6.5. Manejo de descartes

Si “hg qpush” falla al aplicar un parche, mostrara un texto de error y saldra. Si ha dejado ficheros .rej, es mejor

arreglar los trozos descartados antes de introducir parches adicionales o hacer cualquier otra cosa.

Si su parche sol  ıa aplicarse limpiamente, y ya no lo hace porque ha cambiado c odigo subyacente en el cual se basa

su parche, las Colas de Mercurial pueden ayudar; consulte la seccion 12.8.

Desafortunadamente, no hay grandes tecnicas para tratar los trozos descartados. Casi siempre debera consultar el

fichero .rej y editar el fichero objetivo, aplicando los trozos descartados a mano.

Si es aventurero, Neil Brown, un hacker del n ucleo Linux, escribio una herramienta llamada wiggle [Bro], que es

mas vigorosa que patch en su intento de hacer que se aplique un parche.

Otro hacker del nucleo Linux, Chris Mason (el autor de las Colas de Mercurial), escribio una herramienta similar

llamada mpatch [Mas], que sigue una aproximacion sencilla para automatizar la aplicacion de trozos descartados por

patch. 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.

Un trozo ha perdido cierto contexto al principio o al final.

Un trozo largo podrıa aplicarse mejor—por completo o una parte—si estaba cortado en trozos m as pequenos.

Un trozo remueve lıneas con contenido ligeramente diferente que aquellas que estan presentes en el fichero.

Si usted usa wiggle o mpatch, deberıa ser doblemente cuidadoso al revisar sus resultados cuando haya terminado.

De hecho, mpatch refuerza este metodo de revisar por partida doble su salida, dejandolo a usted en un programa de

fusion cuando la herramienta haya terminado su trabajo, de tal forma que usted pueda verificar lo que ha hecho y

pueda terminar de aplicar cualquier fusion faltante.

12.7. maximizar el rendimiento de MQ

MQ es muy eficiente al tratar con una gran cantidad de parches. Corrı unos experimentos de desempeno a mediados

del 2006 para una charla que dı en la conferencia EuroPython 2006 [O’S06]. Emplee la serie de parches para el nucleo

Linux 2.6.17-mm1, que contaba con 1.738 parches. Los aplique sobre un repositorio del nucleo de Linux con todas

las 27.472 revisiones entre 2.6.12-rc2 y 2.6.17.

En mi portatil antiguo y lento, logre aplicar “hg qpush -a” a los 1.738 parches en 3.5 minutos, y “hg qpop -a”en 30 segundos. (En un portatil mas nuevo, el tiempo para introducir todos los parches, se logro en menos de dos

minutos.) Aplique “hg qrefresh” sobre uno de los parches mas grandes (que hizo 22.779 lıneas de cambios en 287

ficheros) en 6,6 segundos.

Claramente, MQ funciona adecuadamente en arboles grandes, y ademas hay unos trucos que pueden emplearse

para obtener el maximo desempeno.

En primer lugar, trate de hacer “en lote” las operaciones. Cada vez que ejecute “hg qpush” o “hg qpop”, tales

ordenes revisan el directorio de trabajo para asegurarse de que usted no ha hecho cambios y ha olvidado ejecutar “hg

qrefresh”. En un arbol pequeno, el tiempo de esta revision puede ser mınimo, Pero en un arbol mediano (con decenas

de miles de ficheros), puede tomar un segundo o mas.

Las ordenes “hg qpush” y “hg qpop” le permiten introducir o sustraer varios parches en una operacion. Puede

identificar el “parche destino” que desee. Cuando aplique “ hg qpush” con un destino, introducira tantos parches

como sea necesario hasta que el especificado este en el tope de la pila. Cuando emplee “hg qpop” con un destino, MQ

sustraera parches hasta que el parche destino este en el tope.

Puede identificar un parche destino con el nombre del parche o con el numero. Si se refiere al numero, los parches

se contaran desde cero; esto significa que el primer parche es cero, el segundo es uno y as ı sucesivamente.

151

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 162/204

12.8. Actualiar los parches cuando el codigo cambia

Es comun contar con una pila de parches sobre un repositorio que usted no modifica directamente. Si esta traba-

 jando en cambios de codigo de otros, o en una caracterıstica que tarda bastante en desarrollarse comparada con la tasa

de cambio del codigo sobre la cual se esta trabajando, necesitara sincronizarse con el codigo, y ajustar cualquier trozo

en sus parches que ya no esten al dıa. A esto se le llama hacer rebase a su serie de parches.

La vıa mas sencilla de hacerlo es con “hg qpop -a” sobre sus parches, despues hacer “hg pull” de los cambiosen el repositorio, y finalmente hacer “hg qpush -a” con sus parches de nuevo. MQ dejara de de introducir parches

siempre que llegue a un parche que no se pueda aplicar debido a un conflicto, permitiendole a usted arreglarlo, aplicar

“hg qrefresh” al parche afectado y continuar introduciendo hasta que haya arreglado la pila completa.

Esta aproximacion es sencilla y funciona bien si no espera cambios en el codigo original que afecte en gran medida

los parches que usted este aplicando. Si su pila de parches toca codigo que es modificado frecuentemente o de forma

invasiva sobre el codigo subyacente, arreglar trozos manualmente se vuelve desgastante.

Es posible automatizar de forma parcial el proceso de rebase. Si sus parches se aplican limpiamente sobre algunas

revisiones del repositorio subyacente, MQ puede usar esta informaci on para ayudarle a a resolver conflictos entre sus

parches y una revision distinta.

El proceso resulta un poco complejo:

1. Para comenzar, haga “hg qpush -a” sobre todos los parches que usted sepa se aplican limpiamente.

2. Guarde una copia de seguridad de su directorio de parches con “hg qsave -e -c”. Esto imprime el nom-bre del directorio en el cual se han guardado los parches. Guardar a los parches en un directorio llamado

.hg/patches.N , donde N  es un entero pequeno. Tambien consigna un “conjunto de cambios de seguridad”

sobre sus parches aplicados; esto es para mantener el hist orico, y guarda los estados de los ficheros series y

status.

3. Use “hg pull” para traer los nuevos cambios en el repositorio subyacente. (No ejecute “ hg pull -u”; vea mas

adelante por que.)

4. Actualice a la nueva revision punta con “hg update -C” para sobreescribir los parches que haya introducido.

5. Fusione todos los parches con “hg qpush -m -a”. La opcion -m de “hg qpush” le indica a MQ que haga una

fusion que involucra tres fuentes si el parche falla al aplicarse.

Durante el “hg qpush -m”, cada parche en el fichero series se aplica normalmente. Si un parche se aplicadifusamente o se niea a aplicarse, MQ consulta la cola que usted guardo con “hg qsave”, y aplica una fusion de tres

con el correspondiente conjunto de cambios. Esta fusion usa la maquinaria de Mercurial, por lo tanto puede mostrar

una herramienta de fusion GUI para ayudarle a resolver los problemas.

Cuando termine de resolver los efectos de un parche, MQ refrescar a su parche basado en el resultado de la fusion.

Al final de este proceso, su repositorio tendra una cabeza extra de la antigua cola de parches, y una copia de la

cola de parches anterio estara en .hg/patches.N . Puede eliminar la cabeza extra con “hg qpop -a -n patches.N ”

o “hg strip”. Puede eliminar .hg/patches.N  una vez que este seguro de que no lo necesita mas como copia de

seguridad.

12.9. Identificar parches

Las ordenes de MQ le permiten trabajar refiriendose al nombre del parche o al numero. Es obvio hacerlo por elnombre; por ejemplo se pasa el nombre foo.patch a “hg qpush”, que introducira los parches hasta que foo.patch

se aplique.

Para hacerlo mas corto, puede referirse a un parche con un nombre y un corrimiento de n umero; por ejemplo,

foo.patch-2 significa “dos parches antes de foo.patch”, mientras que bar.patch+4 significa “cuatro parches de-

spues de bar.patch”.

152

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 163/204

Referirse a un parche por su ındice no es muy diferente. El primer parche que se imprime en la salida de “ hg

qseries” es el parche cero (si, es el primero en los sistemas que comienzan su conteo en cero); el segundo parche es

uno y ası sucesivamente.

MQ facilita el trabajo cuando esta usando ordenes normales de Mercurial. Cada comando que acepte Identifi-

cadores de conjuntos de cambios tambien aceptara el nombre de un parche aplicado. MQ aumenta las etiquetas nor-

malmente en el repositorio con un distintivo para cada parche aplicado. Adicionalmente, las etiquetas especiales qbase

y qtip identifican los parches “primero” y ultimo, respectivamente.Junto con las capacidades de Mercurial para etiquetar, estas adiciones hacen que trabajar con parches sea muy

sencillo.

¿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 que es una “bomba de parches”? Consulte la seccion 14.4.)

¿Desea ver todos los parches desde que se aplico foo.patch sobre los ficheros de un subdirectorio en su arbol?

1 hg log -r foo.patch:qtip subdir 

Dado que MQ nombra los parches disponibles al resto de Mercurial con su maquinaria de etiquetas interna, usted

no necesita teclear el nombre completo de un parche cuando desea identificarlo por su nombre.

Otra consecuencia deseable al representar los nombres de parches como etiquetas es que cuando ejecute la orden

“hg log”, desplegara el nombre del parche como una etiqueta, usualmente con la salida normal. Esto facilita distinguir

visualmente los parches aplicados de las revisiones “normales”. La figura 12.14 muestra algunos comandos usuales de

Mercurial al trabajar con parches.

12.10. Otra informacion util

Hay una cantidad de aspectos que hacen que el uso de MQ no representen secciones en sı mismas, pero de los

cuales es bueno estar enterado. Los presentamos en aquı:

Usualmente cuando hace “hg qpop” a un parche y vuelve a hacerle “hg qpush”, el conjunto de cambios querepresenta el parche despues de introducir/sustraer tendra una identidad distinta que aquella que representaba el

conjunto de cambios anteriormente. Consulte la secction B.1.13 para obtener informacion del por que de esto.

No es una buena idea aplicar “hg merge” de cambios de otra rama con un conjunto de cambios de parches, por

lo menos si desea mantener la “informacion de parches” de ese conjunto de cambios y los conjuntos de cambios

que se encuentran por debajo en la pila de parches. Si intenta hacerlo, parecer a que ha sido exitoso, pero MQ se

confundira.

12.11. Administrar parches en un repositorio

Dado que el directorio .hg/patches de MQ reside fuera del repositorio de trabajo de Mercurial, el repositorio

“subyacente” de Mercurial no sabe nada acerca de la administraci on o presencia de parches.Esto presenta la interesante posibilidad de administrar los contenidos del directorio de parches como un repositorio

de Mercurial por su cuenta. Puede ser una forma util de trabajar. Por ejemplo, puede trabajar en un parche por un rato,

hacerle “hg qrefresh” y despues hacer “hg commit” al estado actual del parche. Esto le permite “devolverse” a esa

version del parche posteriormente.

Puede tambien compartir diferentes versiones de la misma pila de parches entre varios repositorios subyacentes.

Uso esto cuando estoy desarrollando una caracterıstica del nucleo Linux. Tengo una copia original de las fuentes del

153

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 164/204

1 $ hg qapplied

2 first.patch

3 second.patch

4 $ hg log -r qbase:qtip

5 changeset: 1:b3508ccf62ad

6 tag: first.patch

7 tag: qbase8 user: Bryan O’Sullivan <[email protected]>

9 date: Tue Feb 10 18:23:26 2009 +0000

10 summary: [mq]: first.patch

11

12 changeset: 2:c836697fbf55

13 tag: qtip

14 tag: second.patch

15 tag: tip

16 user: Bryan O’Sullivan <[email protected]>

17 date: Tue Feb 10 18:23:26 2009 +0000

18 summary: [mq]: second.patch

19

20 $ hg export second.patch21 # HG changeset patch

22 # User Bryan O’Sullivan <[email protected]>

23 # Date 1234290206 0

24 # Node ID c836697fbf55654f972d867359527813dbbc5d44

25 # Parent b3508ccf62adb8916c6a7b64105642fa516f5a90

26 [mq]: second.patch

27

28 diff -r b3508ccf62ad -r c836697fbf55 other.c

29 --- /dev/null Thu Jan 01 00:00:00 1970 +0000

30 +++ b/other.c Tue Feb 10 18:23:26 2009 +0000

31 @@ -0,0 +1,1 @@

32 +double u;

Figura 12.14: Uso de las caracterısticas de etiquetamiento al trabajar con MQ

nucleo para varias arquitecturas, y clone un rpositorio en cada una que contiene los parches en los cuales estoy traba-

 jando. Cuando quiero probar un cambio en una arquitectura diferente, introduzco mis parches actuales al repositorio

de parches asociado con el arbol del kernel, sustraigo e introduzco todos mis parches, armo y pruebo el nucleo.

Llevar los parches en un repositorio permite que varios desarrolladores puedan trabajar en la misma serie de

parches sin sobreponerse, todo sobre la fuente base subyacente que pueden o no controlar.

12.11.1. Soporte de MQ para repositorios de parches

MQ le ayuda a trabajar con el directorio .hg/patches como un repositorio; cuando usted prepara un repositorio

para trabajar con parches usando “hg qinit”, puede pasarle la opcion -c para que se cree el directorio .hg/patches

como un repositorio de Mercurial.

154

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 165/204

Nota: Si olvida usar la opcion -c option, puede ir al directorio .hg/patches

en cualquier momento y ejecutar “hg init”. No olvide anadir una entrada en el

fichero status del fichero .hgignore, a pesar de que (“hg qinit -c” hace esto-

do de forma automatica para usted); usted seguro no quiere administrar el fichero

status.

MQ nota convenientemente que el directorio .hg/patches es un repositorio, hara “hg add” automaticamente a

cada parche que usted cree e importe.MQ provee una orden corta, “hg qcommit”, que ejecuta “hg commit” en el directorio .hg/patches. Lo que

ahorra tecleo recurrente.

Finalmente, para administrar convenientemente el directorio de parches, puede definir el alias mq en sistemas Unix.

Por ejemplo, en sistemas Linux con el interprete bash, puede incluir el siguiente recorte de codigo6 en su fichero

˜/.bashrc.

1 alias mq=‘hg -R $(hg root)/.hg/patches’

Puede aplicar las ordenes de la forma “mq pull” al repositorio principal.

12.11.2. 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 automaticamente los cambios que haga al directorio de parches. Si aplica “ hg pull”, edita

manualmente, o hace “hg update” a los parches o el fichero series, tendra que aplicar “hg qpop -a” y despues “hg

qpush -a” en el repositorio subyacente para que los cambios se reflejen all ı. Si olvida hacerlo, puede confundir a MQ

en cuanto a que parches se han aplicado.

12.12. Otras herramientas para trabajar con parches

Cuando haya trabajado por cierto tiempo con parches, deseara herramientas que le ayuden a entender y manipular

los parches con los que este tratando.

La orden diffstat [Dic] genera un histograma de modificaciones hechas a cada fichero en un parche. Provee una

interesante forma de “dar un vistazo” al parche—que ficheros afecta, y cuantos cambios introduce a cada fichero y

en total. (Me ha parecido interesante usar la opcion -p de diffstat, puesto que de otra forma intentara hacer cosasinteligentes con prefijos de ficheros que terminan confundiendome.)

El paquete patchutils [Wau] es invaluable. Provee un conjunto de pequenas utilidades que siguen la “filosof ıa

Unix”; cada una hace una cosa muy bien hecha a un parche. La orden patchutils que mas uso es filterdiff,

que extrae subconjuntos de un fichero de parche. Por ejemplo, dado un parche que modifica centenas de ficheros en

docenas de directorios, una unica invocacion de filterdiff puede generear un parche mas pequeno que solamente

toca aquellos ficheros con un patron. Puede ver otro ejemplo en la seccion 13.9.2.

12.13. Buenas practicas de trabajo con parches

En caso de que este trabajando en una serie de parches para enviar a un proyecto de software libre o de fuentes

abiertas, o en una serie que desea tratar como un conjunto de cambios regular, cuando haya terminado, puede usar

tecnicas sencillas para mantener su trabajo bien organizado.De nombres descriptivos a sus parches. Un buen nombre para un parche podrıa ser rework-device-alloc.patch ,

porque da de forma inmediata una pista del proposito del parche. Los nombres largos no deben ser un problema; no

los estara tecleando repetidamente, pero estar   a ejecutando regularmente ordenes como “hg qapplied” y “hg qtop”.

Los nombres adecuados son especialmente importantes cuando tiene bastantes parches con los cuales trabajar, o si

esta trabajando en diferentes tareas y sus parches toman solamente una porcion de su atencion.

6N. del T. snippet

155

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 166/204

1 $ diffstat -p1 remove-redundant-null-checks.patch

2 drivers/char/agp/sgi-agp.c | 5 ++---

3 drivers/char/hvcs.c | 11 +++++------

4 drivers/message/fusion/mptfc.c | 6 ++----

5 drivers/message/fusion/mptsas.c | 3 +--

6 drivers/net/fs_enet/fs_enet-mii.c | 3 +--

7 drivers/net/wireless/ipw2200.c | 22 ++++++----------------8 drivers/scsi/libata-scsi.c | 4 +---

9 drivers/video/au1100fb.c | 3 +--

10 8 files changed, 19 insertions(+), 38 deletions(-)

11 $ filterdiff -i ’*/video/*’ remove-redundant-null-checks.patch

12 --- a/drivers/video/au1100fb.c˜remove-redundant-null-checks-before-free-in-drivers

13 +++ a/drivers/video/au1100fb.c

14 @@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void)

15 {16 driver_unregister(&au1100fb_driver);

17

18 - if (drv_info.opt_mode)

19 - kfree(drv_info.opt_mode);

20 + kfree(drv_info.opt_mode);21 }22

23 module_init(au1100fb_init);

Figura 12.15: Las ordenes diffstat, filterdiff, y lsdiff

Tenga en cuenta en que parche esta trabajando. Use la orden “hg qtop” para dar un vistazo al texto de sus parches

frecuentemente—por ejemplo, use “hg tip -p”)—para asegurarse en donde esta ubicado. En distintas oportunidades

me sucedio que aplique “hg qrefresh” a un parche distinto al que deseaba hacerlo, y usualmente es complejo migrar

los cambios al parche correcto despues de haberlo hecho mal.

Por este motivo, vale la pena invertir ese poco tiempo para aprender como usar otras herramientas que describı en

la seccion 12.12, particularmente diffstat y filterdiff. La primera le dara una idea de que cambios esta haciendo

su parche, mientras que la segunda permite seleccionar trozos de un parche para colocarlos en otro.

12.14. Recetas de MQ

12.14.1. Administrar parches “triviales”

Puesto que colocar ficheros en un repositorio de Mercurial es tan sencillo, tiene bastante sentido administrar parch-

es de esta forma incluso si desea hacer algunos cambios al paquete de ficheros que descargo.

Para comenzar a descargar y desempaqueter un paquete de ficheros, y volverlo en un repositorio de Mercurial:

1 $ download netplug-1.2.5.tar.bz22 $ tar jxf netplug-1.2.5.tar.bz2

3 $ cd netplug-1.2.5

4 $ hg init

5 $ hg commit -q --addremove --message netplug-1.2.5

6 $ cd ..

7 $ hg clone netplug-1.2.5 netplug

156

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 167/204

8 updating working directory

9 18 files updated, 0 files merged, 0 files removed, 0 files unresolved

Continue creando una pila de parches y haga sus cambios.

1 $ cd netplug

2 $ hg qinit3 $ hg qnew -m ’fix build problem with gcc 4’ build-fix.patch

4 $ perl -pi -e ’s/int addr_len/socklen_t addr_len/’ netlink.c

5 $ hg qrefresh

6 $ hg tip -p

7 changeset: 1:4adf6cb9cc16

8 tag: qtip

9 tag: build-fix.patch

10 tag: tip

11 tag: qbase

12 user: Bryan O’Sullivan <[email protected]>

13 date: Tue Feb 10 18:23:26 2009 +0000

14 summary: fix build problem with gcc 4

15

16 diff -r ca53495653b5 -r 4adf6cb9cc16 netlink.c

17 --- a/netlink.c Tue Feb 10 18:23:26 2009 +0000

18 +++ b/netlink.c Tue Feb 10 18:23:26 2009 +0000

19 @@ -275,7 +275,7 @@

20 exit(1);

21 }22

23 - int addr_len = sizeof(addr);

24 + socklen_t addr_len = sizeof(addr);

25

26 if (getsockname(fd, (struct sockaddr *) &addr, &addr_len) == -1) {27 do_log(LOG_ERR, "Could not get socket details: %m");

28

Digamos que pasan unas semanas o meses, y el autor del paquete libera una nueva version. Primero se traen sus

cambios al repositorio.

1 $ hg qpop -a

2 Patch queue now empty

3 $ cd ..

4 $ download netplug-1.2.8.tar.bz2

5 $ hg clone netplug-1.2.5 netplug-1.2.8

6 updating working directory

7 18 files updated, 0 files merged, 0 files removed, 0 files unresolved

8 $ cd netplug-1.2.8

9 $ hg locate -0 | xargs -0 rm 

10 $ cd ..

11 $ tar jxf netplug-1.2.8.tar.bz2

12 $ cd netplug-1.2.8

13 $ hg commit --addremove --message netplug-1.2.8

La porcion que comienza con “hg locate” mostrada mas arriba, borra todos los ficheros en el directorio de trabajo,

157

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 168/204

ası que la opcion --addremove de “hg commit” puede indicar que ficheros se han eliminado en la nueva version del

arbol de fuentes.

Finalmente, puede aplicar sus parches encima del nuevo arbol de fuentes

1 $ cd ../netplug

2 $ hg pull ../netplug-1.2.8

3

pulling from ../netplug-1.2.84 searching for changes

5 adding changesets

6 adding manifests

7 adding file changes

8 added 1 changesets with 12 changes to 12 files

9 (run ’hg update’ to get a working copy)

10 $ hg qpush -a

11 (working directory not at tip)

12 applying build-fix.patch

13 Now at: build-fix.patch

12.14.2. Combinar parches completosMQ provee la orden “hg qfold” que le permite combinar parches enteros. Se “integran” 7 los parches que ust-

ed nombre, en el orden que especifique, en el ultimo parche aplicado, y concatena sus descripciones al final de su

descripcion. Debera sustraer los cambios para poder integrarlos.

El orden en el que integre los parches importa. Si el parche ultimamente aplicado es foo, e integra “hg qfold”

bar y quux en el, terminara con un parche que tiene el mismo efecto que si hubiera aplicado primero foo, y despues

bar, seguido de quux.

12.14.3. Fusionar una porcion de un parche dentro de otro

Fusionar partes de un parche dentro de otro es mas complejo que combinar completamente dos parches.

Si desea mover cambios de ficheros completos, 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. Usualmente

no necesitara modificar el parche del cual ha fusionado los cambios. En cambio, MQ reportara que hay unos trozos

que se han desechado cuando usted aplique “hg qpush” (de los trozos que haya movido al otro parche), y puede

sencillamente aplicar “hg qrefresh” para eliminar los trozos replicados.

Si tiene un parche que tiene varios trozos que modifican un fichero, y desea mover solamente unos de ellos, el

trabajo es un poco mas enredado, pero puede automatizarlo parcialmente. Use “lsdiff -nvv” para imprimir algunos

metadatos del parche.

1 $ lsdiff -nvv remove-redundant-null-checks.patch

2 22 File #1 a/drivers/char/agp/sgi-agp.c

3 24 Hunk #1 static int __devinit agp_sgi_init(void)

4 37 File #2 a/drivers/char/hvcs.c

5 39 Hunk #1 static struct tty_operations hvcs_ops =

6

53 Hunk #2 static int hvcs_alloc_index_list(int n)7 69 File #3 a/drivers/message/fusion/mptfc.c

8 71 Hunk #1 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in

9 85 File #4 a/drivers/message/fusion/mptsas.c

10 87 Hunk #1 mptsas_probe_hba_phys(MPT_ADAPTER *ioc)

11 98 File #5 a/drivers/net/fs_enet/fs_enet-mii.c

7N. del T. fold

158

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 169/204

12 100 Hunk #1 static struct fs_enet_mii_bus *create_bu

13 111 File #6 a/drivers/net/wireless/ipw2200.c

14 113 Hunk #1 static struct ipw_fw_error *ipw_alloc_er

15 126 Hunk #2 static ssize_t clear_error(struct device

16 140 Hunk #3 static void ipw_irq_tasklet(struct ipw_p

17 150 Hunk #4 static void ipw_pci_remove(struct pci_de

18 164 File #7 a/drivers/scsi/libata-scsi.c19 166 Hunk #1 int ata_cmd_ioctl(struct scsi_device *sc

20 178 File #8 a/drivers/video/au1100fb.c

21 180 Hunk #1 void __exit au1100fb_cleanup(void)

Esta orden imprime tres clases diferentes de numeros:

(en la primera columna) un n´ umero de fichero para identificar cada fichero modificado en el parche;

(En la siguiente lınea, indentado) el numero de lınea dentro de un fichero modificado donde comienza el trozo;

y

(en la misma lınea) un n´ umero de trozo que identifica el trozo.

Tendra que hacer una inspeccion visual, y leer el parche para identificar los n umeros de fichero y trozo que desea,pero puede pasar posteriormente a las opciones --files y --hunks de filterdiff, para seleccionar exactamente el

fichero y el trozo que desea extraer.

Cuando tenga el trozo, puede concatenarlo al final de su parche objetivo y continuar como en la seccion 12.14.2.

12.15. Diferencias entre quilt y MQ

Si le es familiar quilt, MQ provee un conjunto similar de ordenes. Hay algunas diferencias en como funcionan.

Debe haber notado que la mayorıa de comandos de quilt tienen su contraparte en MQ, que simplemente comienzan

con “q”. Las excepciones son las ordenes add y remove de quilt, que realmente son las ordenes “hg add” y “hg

remove” de Mercurial. No hay un equivalente en MQ para la orden edit de quilt.

159

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 170/204

Capıtulo 13

Usos avanzados de las Colas de Mercurial

Auunque es facil aprender los usos mas directos de las Colas de Mercurial, tener algo de disciplina junto con

algunas de las capacidadees menos usadas de MQ hace posible trabajar en entornos de desarrollo complejos.

En este capıtulo, usare como ejemplo una tecnica que he usado para administrar el desarrollo de un controlador de

dispositivo Infiniband para el kernel de Linux. El controlador en cuestion es grande (al menos en lo que se refiere a

controladores), con 25,000 lıneas de codigo esparcidas en 35 ficheros fuente. Es mantenido por un equipo pequeno dedesarrolladores.

Aunque mucho del material en este capıtulo es especıfico de Linux, los mismos principios aplican a cualquier base

de codigo de la que usted no sea el propietario principal, y sobre la que usted necesita hacer un mont on de desarrollo.

13.1. El problema de multiples objetivos

El kernel de Linux cambia con rapidez, y nunca ha sido estable internamente; los desarrolladores hacen cambios

drasticos entre versiones frecuentemente. Esto significa que una version del controlador que funciona bien con una

version particular del kernel ni siquiera compilar´ a correctamente contra, tıpicamente, cualquier otra version.

Para mantener un controlador, debemos tener en cuenta una buena cantidad de versiones de Linux en mente.

Un objetivo es el arbol de desarrollo principal del kernel de Linux. En este caso el mantenimiento del codigo

es compartido parcialmente por otros desarrolladores en la comunidad del kernel, quienes hacen modificaciones

“de-afan” al controlador a medida que desarrollan y refinan subsistemas en el kernel.

Tambien mantenemos algunos “backports” para versiones antiguas del kernel de Linux, para dar soporte a

las necesidades de los clientes que estan corriendo versiones antiguas de Linux que no incorporan nuestros

controladores. (Hacer el backport  de un pedazo de codigo es modificarlo para que trabaje en una version de su

entorno objetivo anterior a aquella para la cual fue escrito.)

Finalmente, nosotros liberamos nuestro software de acuerdo a un cronograma que no necesariamente est a alin-

eado con el que usan los distribuidores de Linux y los desarrolladores del kernel, ası que podemos entregar

nuevas caracterısticas a los clientes sin forzarlos a actualizar kernels completos o distribuciones.

13.1.1. Aproximaciones tentadoras que no funcionan adecuadamente

Hay dos maneras estandar de mantener una porcion de software que debe funcionar en muchos entornos diferentes.

La primera es mantener varias ramas, cada una pensada para un unico entorno. El problema de esta aproximacion

es que usted debe tener una disciplina f errea con el flujo de cambios entre repositorios. Una nueva caracter ıstica o un

arreglo de fallo deben empezar su vida en un repositorio “pr ıstino”, y luego propagarse a cada repositorio de backport.

Los cambios para backports estan mas limitados respecto a las ramas a las que deber ıan propagarse; un cambio para

backport que es aplicado a una rama en la que no corresponde probablemente hara que el controlador no compile.

160

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 171/204

La segunda es mantener un unico arbol de codigo fuente lleno de declaraciones que activen o desactiven secciones

de codigo dependiendo del entorno objetivo. Ya que estos “ifdefs” no est an permitidos en el arbol del kernel de Linux,

debe seguirse algun proceso manual o automatico para eliminarlos y producir un arbol limpio. Una base de codigo

mantenida de esta manera se convierte rapidamente en un nido de ratas de bloques condicionales que son dif ıciles de

entender y mantener.

Ninguno de estos enfoques es adecuado para situaciones en las que usted no es “dueno” de la copia canonica

de un arbol de fuentes. En el caso de un controlador de Linux que es distribuido con el kernel est andar, el arbol deLinux contiene la copia del codigo que sera considerada por el mundo como la canonica. La version oficial de “mi”

controlador puede ser modificada por gente que no conozco, sin que yo siquiera me entere de ello hasta despu es de

que los cambios aparecen en el arbol de Linus.

Estos enfoques tienen la debilidad adicional de dificultar la generacion de parches bien formados para enviarlos a

la version oficial.

En principio, las Colas de Mercurial parecen ser un buen candidato para administrar un escenario de desarrollo

como el de arriba. Aunque este es de hecho el caso, MQ tiene unas cuantas caracter ısticas adicionales que hacen el

trabajo mas agradable.

13.2. Aplicar parches condicionalmente mediante guardias

Tal vez la mejor manera de conservar la cordura con tantos entornos objetivo es poder escoger parches especıficospara aplicar para cada situacion. MQ provee una caracterıstica llamada “guardias” (que se origina del comando guards

de Quilt) que hace precisamente esto. Para empezar, creemos un repositorio sencillo para experimentar.

1 $ hg qinit

2 $ hg qnew hello.patch

3 $ echo hello > hello

4 $ hg add hello

5 $ hg qrefresh

6 $ hg qnew goodbye.patch

7 $ echo goodbye > goodbye

8 $ hg add goodbye

9 $ hg qrefresh

Esto nos brinda un pequeno repositorio que contiene dos parches que no tienen ninguna dependencia respecto al otro,

porque tocan ficheros diferentes.

La idea detras de la aplicacion condicional es que usted puede “etiquetar” un parche con un guardia, que sim-

plemente es una cadena de texto de su eleccion, y luego decirle a MQ que seleccione guardias especıficos para usar

cuando aplique parches. MQ entonces aplicara, u omitira, un parche vigilado, dependiendo de los guardias que usted

haya seleccionado.

Un parche puede tener una cantidad arbitraria de guardias; cada uno es positivo (“aplique el parche si este guardia

es seleccionado”) o negativo (“omita este parche si este guardia es seleccionado”). Un parche sin guardias siempre es

aplicado.

13.3. Controlar los guardias de un parche

El comando “hg qguard” le permite determinar que guardias deben aplicarse a un parche, o mostrar los guardias

que estan en efecto. Sin ningun argumento, el comando muestra los guardias del parche actual de la parte m as alta de

la pila.

1 $ hg qguard

2 goodbye.patch: unguarded

161

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 172/204

Para poner un guardia positivo en un parche, prefije el nombre del guardia con un “+”.

1 $ hg qguard +foo

2 $ hg qguard

3 goodbye.patch: +foo

Para poner un guardia negativo en un parche, prefije el nombre del guardia con un “-”.

1 $ hg qguard hello.patch -quux

2 $ hg qguard hello.patch

3 hello.patch: -quux

Nota: El comando “hg qguard” pone los guardias en un parche; no los modifica.

Esto significa que si usted ejecuta “hg qguard +a +b” sobre un parche, y luego

“hg qguard +c” en el mismo parche, el unico guardia sobre el parche despues del

comando sera +c.

Mercurial almacena los guardias en el fichero series; la forma en que son almacenados es f acil tanto de entender

como de editar a mano. (En otras palabras, usted no tiene que usar el comando “hg qguard” si no lo desea; esta bien

simplemente editar el fichero series)

1 $ cat .hg/patches/series2 hello.patch #-quux

3 goodbye.patch #+foo

13.4. Selecccionar los guardias a usar

El comando “hg qselect” determina que guardias estan activos en cualquier momento. El efecto de esto es

determinar que parches aplicara MQ la proxima vez que usted ejecute “hg qpush”. No tiene ningun otro efecto; en

particular, no hace nada a los parches que ya han sido aplicados.

Sin argumentos, el comando “hg qselect” lista los guardias en efecto actualmente, uno por cada l ınea de salida.

Cada argumento es tratado como el nombre de un guardia a aplicar.

1 $ hg qpop -a

2 Patch queue now empty

3 $ hg qselect

4 no active guards

5 $ hg qselect foo

6 number of unguarded, unapplied patches has changed from 1 to 2

7 $ hg qselect

8 foo

Si esta interesado, los guardias seleccionados actualmente estan almacenados en el fichero guards.

1 $ cat .hg/patches/guards

2 foo

Podemos ver el efecto que tienen los guardias seleccionados cuando ejecutamos “ hg qpush”.

1 $ hg qpush -a

2 applying hello.patch

3 applying goodbye.patch

4 Now at: goodbye.patch

162

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 173/204

Un guardia no puede empezar con un caracter “ +” o “-”. El nombre del guardia no debe contener espacios en

blanco, pero muchos otros caracteres son aceptables. Si usted trata de usar un guardia con un nombre inv alido, MQ se

quejara:

1 $ hg qselect +foo

2 abort: guard ’+foo’ starts with invalid character: ’+’

Cambiar los guardias seleccionados cambia los parches que son aplicados.

1 $ hg qselect quux

2 number of guarded, applied patches has changed from 0 to 2

3 $ hg qpop -a

4 Patch queue now empty

5 $ hg qpush -a

6 patch series already fully applied

Usted puede ver en el ejemplo de abajo que los guardias negativos tienen precedencia sobre los guardias positivos.

1 $ hg qselect foo bar

2 number of unguarded, unapplied patches has changed from 0 to 23 $ hg qpop -a

4 no patches applied

5 $ hg qpush -a

6 applying hello.patch

7 applying goodbye.patch

8 Now at: goodbye.patch

13.5. Reglas de MQ para aplicar parches

Las reglas que MQ usa para decidir si debe aplicar un parche son las siguientes.

Un parche sin guardias es aplicado siempre.

Si el parche tiene algun guardia negativo que corresponda con cualquiera de los guardias seleccionados, se salta

el parche.

Si el parche tiene algun guardia positivo que corresponda con cualquiera de los guardias seleccionados, se aplica

el parche.

Si el parche tiene guardias positivos o negativos, pero ninguno corresponde con cualquiera de los guardias

seleccionados, se salta el parche.

13.6. Podar el entorno de trabajo

En el trabajo del controlador de dispositivo que mencione anteriormente, yo no aplico los parches a un arbolnormal del kernel de Linux. En cambio, uso un repositorio que s olo contiene una instantanea de los ficheros fuente y

de cabecera que son relevantes para el desarrollo de Infiniband. Este repositorio tiene un 1 % del tamano del repositorio

del kernel, por lo que es mas f acil trabajar con el.

Luego escojo una version “base” sobre la cual son aplicados los parches. Es una instantanea del arbol del kernel

de Linux en una revision de mi eleccion. Cuando tomo la instantanea, almaceno el ID de conjunto de cambios en el

mensaje de consignacion. Ya que la instantanea preserva la “forma” y el contenido de las partes relevantes del arbol

del kernel, puedo aplicar mis parches sobre mi pequeno repositorio o sobre un arbol normal del kernel.

163

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 174/204

Normalmente, el arbol base sobre el que se aplican los parches deberıa ser una instantanea de un arbol de desarrollo

muy reciente. Esto facilita mucho el desarrollo de parches que puedan ser enviados al arbol oficial con pocas o ninguna

modificacion.

13.7. Dividir el fichero series

Yo categorizo los parches en el fichero series en una serie de grupos logicos. Cada seccion de parches similares

empieza con un bloque de comentarios que describen el proposito de los parches que le siguen.

La secuencia de grupos de parches que mantengo se muestra a continuaci on. El orden de los grupos es importante;

explicare porque luego de que presente los grupos.

El grupo “aceptado”. Son parches que el equipo de desarrollo ha enviado al mantenedor del subsistema Infini-

band, y que el ha aceptado, pero que no estan presentes en la instantanea en la cual esta basada el repositorio

pequeno. Estos son parches de “solo lectura”, presentes unicamente para transformar el arbol en un estado

similar al del repositorio del mantenedor oficial.

El grupo “revisar”. Parches que yo he enviado, pero sobre los que que el mantenedor oficial ha solicitado

modificaciones antes de aceptarlos.

El grupo “pendiente”. Parches que no he enviado al mantenedor oficial, pero que ya estan terminados. Estosparches seran de “solo lectura” por un buen tiempo. Si el mantenedor oficial los acepta cuando los envıe, los

movere al final del grupo “aceptado”. Si el solicita que modificaciones en alguno de ellos, los movere al principio

del grupo “revisar”.

El grupo “en proceso”. Parches que estan siendo activamente desarrollados, y no deberıan ser enviados a ninguna

parte aun.

El grupo “backport”. Parches que adaptan el arbol de fuentes a versiones antiguas del arbol del kernel.

El grupo “no enviar”. Parches que por alguna razon nunca deben ser enviados al mantenedor oficial del kernel.

Por ejemplo, alguno de esos parches podrıa cambiar las cadenas de identificacion embebidas del controlador

para hacer mas facil la distincion, en pruebas de campo, entre una version del controlador de salida-del-arbol y

una version entregada por un vendedor de alguna distribucion.

Ahora volvemos a las razones para ordenar los grupos de parches en esta manera. Quisieramos que los parches del

fondo de la pila sean tan estables como sea posible, para no tener que revisar parches m as arriba debido a cambios de

contexto. Poner los parches que nunca cambiaran en el primer lugar del fichero series sirve a este proposito.

Tambien desearıamos que los parches que sabemos que debemos modificar sean aplicados sobre un arbol de fuentes

que se parezca al oficial tanto como sea posible. Es por esto que mantenemos los parches aceptados disponibles por

una buena cantidad de tiempo.

Los parches “backport” y “no enviar” flotan al final del fichero series. Los parches de backport deben ser aplica-

dos encima de todos los otros parches, y los parches “no enviar” pueden perfectamente quedarse fuera del camino.

13.8. Mantener la serie de parches

En mi trabajo, uso varios guardias para controlar que parches deben ser aplicados.

Los parches “aceptados” son vigilados con accepted. Yo habilito este guardia la mayorıa de las veces. Cuando

aplico los parches sobre un arbol donde los parches ya estan presentes, puedo desactivar este parche, y los

parches que lo siguen se aplicaran sin problemas.

Los parches que estan “terminados”, pero no han sido enviados, no tienen guardias. Si estoy aplicando la pila

de parches a una copia del arbol oficial, no necesito habilitar ningun guardia para obtener un arbol de fuentes

razonablemente seguro.

164

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 175/204

Los parches que necesitan revision antes de ser reenviados tienen el guardia rework.

Para aquellos parches que aun estan bajo desarrollo, uso devel.

Un parche de backport puede tener varios guardias, uno para cada version del kernel a la que aplica. Por ejemplo,

un parche que hace backport de un segmento de codigo a 2.6.9 tendra un guardia 2.6.9.

La variedad de guardias me brinda una flexibilidad considerable para determinar que tipode arbol de fuentes acabare porobtener. En la mayorıa de las situaciones, la seleccion de guardias apropiados es automatizada durante el proceso de

compilacion, pero puedo ajustar manualmente los guardias a usar para circunstancias poco comunes.

13.8.1. El arte de escribir parches de backport

Al usar MQ, escribir un parche de backport es un proceso simple. Todo lo que dicho parche debe hacer es modificar

una seccion de codigo que usa una caracterıstica del kernel que no esta presente en la version anterior del kernel, para

que el controlador siga funcionando correctamente en esa version anterior.

Una meta util al escribir un buen parche de backport es hacer parecer que el c odigo hubiera sido escrito para la

version vieja del kernel que usted tiene como objetivo. Entre menos intrusivo el parche, mas f acil sera entenderlo y

mantenerlo. Si usted esta escribiendo una coleccion de parches de backport para evitar el efecto de “nido de ratas” de

tener muchos #ifdefs (secciones de codigo fuente que solo son usados condicionalmente) en su codigo, no introduzca

#ifdefs dependientes de versiones especıficas en los parches. En vez de eso, escriba varios parches, cada uno de elloshaciendo cambios incondicionales, y controle su aplicacion usando guardias.

Hay dos razones para ubicar los parches de backport en un grupo diferente, aparte de los parches “regulares”

cuyos efectos son modificados por ellos. La primera es que mezclar los dos hace m as dif ıcil usar herramientas como la

extension patchbomb para automatizar el proceso de enviar los parches a un mantenedor oficial. La segunda es que un

parche de backport puede perturbar el contexto en el que se aplica un parche regular subsecuente, haciendo imposible

aplicar el parche normal limpiamente sin que el parche de backport sea aplicado antes.

13.9. Consejos utiles para hacer desarrollo con MQ

13.9.1. Organizar parches en directorios

Si esta trabajando en un proyecto grande con MQ, no es dif ıcil acumular un gran numero de parches. Por ejemplo,tengo un repositorio de parches que contiene mas de 250 parches.

Si usted puede agrupar estos parches en categorıas logicas separadas, usted puede almacenarlos en diferentes

directorios si lo desea; MQ no tiene problemas manejando nombres de parches que contienen separadores de ruta.

13.9.2. Ver el historial de un parche

Si usted esta desarrollando un conjunto de parches en un perıodo de tiempo grande, es una buena idea mantenerlos

en un repositorio, como se discutio en la seccion 12.11. Si lo hace, notara rapidamente que usar el comando “hg diff”

para mirar el historial del repositorio no es viable. Esto es debido en parte a que usted est a mirando la segunda derivada

del codigo real (el diff de un diff), pero tambien porque MQ anade ruido al proceso al modificar las marcas de tiempo

y los nombres de directorio cuando actualiza un parche.

Sin embargo, usted puede usar la extension extdiff, que es provisto junto con Mercurial, para convertir un diff 

de dos versiones de un parche en algo legible. Para hacer esto, usted necesitar a un paquete de un tercero llamadopatchutils [Wau]. Este paquete provee un comando llamado interdiff, que muestra las diferencias entre dos diffs

como un diff. Al usarlo en dos versiones del mismo diff, genera un diff que representa el diff de la primera a la segunda

version.

Usted puede habilitar la extension extdiff de la manera usual, anadiendo una lınea a la seccion [extensions]

de su hgrc.

165

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 176/204

1 [extensions]

2 extdiff =

El comando interdiff espera recibir los nombres de dos ficheros, pero la extension extdiff le pasa un par de

directorios al programa que ejecuta, cada uno de los cuales puede contener una cantidad arbitraria de ficheros. Por

esto necesitamos un programa pequeno que ejecute interdiff en cada par de ficheros de estos dos directorios.Este programa esta disponible como hg-interdiff en el directorio examples del repositorio de codigo fuente que

acompana a este libro.

1 #!/usr/bin/env python

2 #

3 # Adapter for using interdiff with mercurial’s extdiff extension.

4 #

5 # Copyright 2006 Bryan O’Sullivan <[email protected]>

6 #

7 # This software may be used and distributed according to the terms of

8 # the GNU General Public License, incorporated herein by reference.

9

10 import os, sys11

12 def walk(base):

13 # yield all non-directories below the base path.

14 for root, dirs, files in os.walk(base):

15 for f in files:

16 path = os.path.join(root, f)

17 yield path[len(base)+1:], path

18 else:

19 if os.path.isfile(base):

20 yield ’’, base

21

22 # create list of unique file names under both directories.

23 files = dict(walk(sys.argv[1]))

24 files.update(walk(sys.argv[2]))

25 files = files.keys()

26 files.sort()

27

28 def name(base, f):

29 if f:

30 path = os.path.join(base, f)

31 else:

32 path = base

33 # interdiff requires two files; use /dev/null if one is missing.

34 if os.path.exists(path):

35 return path

36 return ’/dev/null’

37

38 r e t = 0

39

40 for f in files:

41 if os.system(’interdiff "%s" "%s"’ % (name(sys.argv[1], f),

42 name(sys.argv[2], f))):

166

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 177/204

43 r e t = 1

44

45 sys.exit(ret)

Con el programa hg-interdiff en la ruta de busqueda de su interprete de comandos, puede ejecutarlo como

sigue, desde dentro de un directorio de parches MQ:

1 hg extdiff -p hg-interdiff -r A:B my-change.patch

Ya que usted seguramente querra usar este comando tan largo a menudo, puede hacer que hgext lo haga disponible

como un comando normal de Mercurial, editando de nuevo su hgrc.

1 [extdiff]

2 cmd.interdiff = hg-interdiff

Esto le indica a hgext que ponga a disposicion un comando interdiff, con lo que usted puede abreviar la invocacion

anterior de “hg extdiff” a algo un poco mas manejable.

1 hg interdiff -r A:B my-change.patch

Nota: El comando interdiff trabaja bien solo si los ficheros contra los cuales

son generadas las versiones de un parche se mantienen iguales. Si usted crea un

parche, modifica los ficheros subyacentes, y luego regenera el parche, interdiff

podrıa no producir ningun resultado util.

La extension extdiff es util para mas que solamente mejorar la presentacion de los parches MQ. Para leer mas

acerca de esto, vaya a la seccion 14.2.

167

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 178/204

Capıtulo 14

A ˜ nadir funcionalidad con extensiones

A pesar de que el corazon de Mercurial es muy completo desde el punto de vista de funcionalidad, carece de

caracterısticas rimbombantes deliberadamente. Esta aproximacion de preservar la simplicidad mantiene el programa

sencillo tanto para mantenedores como para usuarios.

Si embargo Mercurial no le cierra las posibilidades a un conjunto inflexible de ordenes: usted puede anadir carac-

terısticas como extensiones (aveces llamadas a˜ nadidos1

). Ya hemos discutido algunas de estas extensiones en capıtulosanteriores:

La seccion 3.3 cubre la extension fetch; que combina jalar cambios y fusionarlos con los cambios locales en

una sola orden: “hg fetch”.

En el capıtulo 10, cubrimos muchas extensiones que son utiles en funcionalidades relacionadas con ganchos:

Los acl anaden listas de control de acceso; bugzilla anade integracion con el sistema de seguimiento de fallos

Bugzilla; y notify envıa notificaciones por correo de nuevos cambios.

La extension de administracion de parches MQ es tan invaluable que amerita dos capıtulos y un apendice por

sı misma. El capıtulo 12 cubre lo basico; el capıtulo 13 discute temas avanzados; y el apendice B muestra en

detalle cada orden.

En este capıtulo cubriremos algunas extensiones adicionales disponibles para Mercurial, y daremos un vistazo a lamaquinaria que necesita conocer en caso de que desee escribir una extension.

En la seccion 14.1, discutiremos la posibilidad de mejorar el desempeno en gran medida con la extension

inotify.

14.1. Mejorar el desempe ˜ no con la extension inotify

¿Desea lograr que las operaciones mas comunmente usadas de Mercurial se ejecuten centenas de veces mas rapido?

¡A leer!

Mercurial tiene gran desempeno bajo circunstancias normales. Por ejemplo, cuando ejecuta la orden “hg status”,

Mercurial tiene que revisar casi todos los ficheros y directorios en su repositorio de forma que pueda desplegar el estado

de los ficheros. Muchas otras ordenes tienen que hacer tal trabajo tras bambalinas; por ejemplo la orden “ hg diff”

usa la maquinaria de estado para evitar hacer operaciones de comparacion costosas en ficheros que obviamente no hancambiado.

Dado que obtener el estado de los ficheros es crucial para obtener buen desempeno, los autores de Mercurial han

optimizado este codigo en la medida de lo posible. Sin embargo, no puede obviarse el hecho de que cuando ejecuta

“hg status”, Mercurial tendra que hacer por lo menos una costosa llamada al sistema por cada fichero administrado

1N. del T. plugins

168

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 179/204

para determinar si ha cambiado desde la ultima vez que se consigno. Para un repositorio suficientemente grande, puede

tardar bastante tiempo.

Para mostrar en numeros la magnitud de este efect, cree un repositorio que contenıa 150.000 ficheros administrador.

Tardo diez segundos para ejecutar “hg status”, a pesar de que ninguno de los ficheros habıa sido modificado.

Muchos sistemas operativos modernos contienen una facilidad de notificacion de ficheros. Si un programa se

registra con un servicio apropiado, el sistema operativo le notificara siempre que un fichero de interes haya sido

creado, modificado o borrado. En sistemas Linux, el componente del nucleo que lo hace se llama inotify.La extension inotify habla con el componente inotify del nucleo para optimizar las ordenes de “hg status”.

La extension tiene dos componentes. Un daemonio esta en el fondo recibiendo notificaciones del subsistema inotify.

Tambien escucha conexiones de una orden regular de Mercurial. La extension modifica el comportamiento de Mercu-

rial de tal forma que, en lugar de revisar el sistema de ficheros, le pregunta al daemonio. Dado que el daemonio tiene

informacion perfecta acerca del estado del repositorio, puede responder instantaneamente con el resultado, evitando la

necesidad de revisar cada directorio y fichero del repositorio.

Retomando los diez segundos que medı al ejecutar la orden “hg status” de Mercurial sobre un repositorio de

150.000 ficheros. Con la extension inotify habilitada, el tiempo se disipo a 0.1 seconds, un factor cien veces mas

rapido.

Antes de continuar, tenga en cuenta algunos detalles:

La extension inotify es especıfica de Linux. Porque se enlaza directamente con el subsistema inotify del

nucleo Linux, no funciona en otros sistemas operativos.

Deberıa funcionar en cualquier distribucion Linux a partir de comienzos del 2005. Las distribuciones mas an-

tiguas deben tener un kernel sin inotify, o una version de glibc que no tiene necesariamente el soporte para

la interfaz.

No todos los sistemas de ficheros pueden usarse con la extension inotify. Los sistemas de ficheros tales como

NFS no lo soportan, por ejemplo, si esta corriendo Mercurial en vaios sistemas, montados todos sobre el mismo

sistema de ficheros en red. El sistema inotify del kernel no tiene forma de saber acerca de los cambios hechos

en otro sistema. La mayorıa de sistemas de ficheros locales (p.e. ext3, XFS, ReiserFS) deberıan funcionar bien.

Hacia mayo de 2007 la extension inotify no venıa de forma predeterminada en Mercurial2, y es un poco mas

compleja de activar que otras extensiones. Pero la mejora en el desempe no bien vale la pena!

La extension venıa en dos partes: un conjunto de parches al codigo fuente de Mercurial, y una librerıa de interfaces

de Python hacia el subsistema inotify.

Nota: Hay dos librerıas de enlace de Python hacia inotify. Una de ellasse llama pyinotify, y en algunas distribuciones de Linux se encuentra como

python-inotify. Esta es la que no necesita, puesto que tiene muchos fallos, y

es ineficiente para ser practica.

Para comenzar, es mejor tener una copia de Mercurial funcional instalada:

Nota: Si sigue las instrucciones a continuacion, esta

biendo cualquier instalacion previa de Mercurial qu

de Mercurial “mas reciente y peligrosa”. No diga qu

1. Clone el repositorio de interfaz entre Python e inotify. Armelo e instalelo:

1 hg clone http://hg.kublai.com/python/inotify

2 cd inotify

3 python setup.py build --force

4 sudo python setup.py install --skip-build

2. Clone el repositorio crew de Mercurial. Clone el repositorio de parches de inotify de forma tal que las colas

de Mercurial puedan aplicar los parches sobre el repositorio crew.

2N. del T. Desde el 2008 para kernels 2.6 viene en Mercurial, pero no esta activada de forma predeterminada

169

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 180/204

1 hg clone http://hg.intevation.org/mercurial/crew

2 hg clone crew inotify

3 hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches

3. Asegurese de instalar la extension Colas de Mercurial mq y que esten habilitadas. Si nunca ha usado MQ, lea la

seccion 12.5 para poder comenzar rapidamente.

4. Vaya al repositorio de inotify y aplique todos los parches de inotify con la opcion -a de la orden “hg

qpush”.

1 cd inotify

2 hg qpush -a

Si obtiene un mensaje de error de “hg qpush”, no deberıa continuar. Mejor pida ayuda.

5. Arme e instale la version parchada de Mercurial.

1 python setup.py build --force

2 sudo python setup.py install --skip-build

Una vez que haya armado una version funcional parchada de Mercurial, todo lo que necesita es habilitar la extension

inotify colocando una entrada en su hgrc.

1 [extensions]

2 inotify =

Cuando la extension inotify este habilitada, Mercurial iniciara transparente y automaticamente el daemonio de es-

tado la primera vez que ejecute un comando que requiera estado del repositorio. Ejecuta un daemonio de estado por

repositorio.

El daemonio de estado se inicia silenciosamente y se ejecuta en el fondo. Si mira a la lista de procesos en ejecucion

despues de habilitar la extension inotify y ejecuta unos pocos comandos en diferentes repositorios, vera que hay

algunos procesos de hg por ahı, esperando actualizaciones del kernel y solicitudes de Mercurial.La primera vez que ejecuta un comando de Mercurial en un repositorio cuando tiene la extensi on inotify ha-

bilitada, correra casi con el mismo desempeno que una orden usual de Mercurial. Esto es debido a que el estado del

daemonio necesita aplicar una busqueda normal sobre el estado para poder tener una lınea de partida frente a la cual

aplicar posteriormente actualizaciones del nucleo. De todas formas, todo comando posterior que haga cualquier clase

de revision del estado deberıa ser notablemente mas rapido en repositorios con incluso un tamano modesto. Aun mejor,

a medida que su repositorio sea mas grande, mejor desempeno vera. El daemonio inotify hace operaciones de estado

de forma casi instantanea en repositorios de todos los tamanos!

Si lo desea, puede iniciar manualmente un daemonio de estado con la orden “hg inserve”. Esto le da un control

un poco mas fino acerca de como deberıa ejecutarse el daemonio. Esta orden solamente estara disponible cuando haya

habilitado la extension inotify.

Cuando este usando la extension inotify, no deberıa ver diferencia en el comportamiento de Mercurial, con

la unica excepcion de que los comandos relacionados con el estado deberıan ejectuarse mucho mas rapido que co-

mo solıan hacerlo. Deberıa esperar especıficamente que las ordenes no deberıan ofrecer salidas distintas; ni ofrecerresultados diferentes. Si alguna de estas situaciones ocurre, por favor reporte el fallo.

14.2. Soporte flexible de diff con la extension extdiff

La orden predeterminada “hg diff” de Mercurial despliega diffs en texto plano unificadas.

170

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 181/204

1 $ hg diff

2 diff -r d6e1fbefacc8 myfile

3 --- a/myfile Tue Feb 10 18:23:22 2009 +0000

4 +++ b/myfile Tue Feb 10 18:23:22 2009 +0000

5 @@ -1,1 +1,2 @@

6 The first line.7 +The second line.

Si dese emplear una herramienta externa para desplegar las modificaciones, querra usar la extension extdiff. Esta le

permitira usar por ejemplo una herramienta grafica de diff.

La extension extdiff viene con Mercurial, y es f acil configurar. En la seccion [extensions] de su hgrc, basta

con anadir una entrada de una lınea para habilitar la extension.

1 [extensions]

2 extdiff =

Esto introduce una orden llamada “hg extdiff”, 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”.

1 $ hg extdiff

2 --- a.d6e1fbefacc8/myfile 2009-02-10 18:23:22.000000000 +0000

3 +++ /tmp/extdiff83LA2p/a/myfile 2009-02-10 18:23:22.000000000 +0000

4 @@ -1 +1,2 @@

5 The first line.

6 +The second line.

El resultado no sera exactamente el mismo que con la orden interna “hg diff”, puesto que la salida de diff varıa de

un sistema a otro, incluso pasando las mismas opciones.

Como lo indican las lıneas“making snapshot”, la orden “hg extdiff” funciona creando dos instantaneas de

su arbol de fuentes. La primera instantanea es la revision fuente; la segunda es la revision objetivo del directorio

de trabajo. La orden “hg extdiff” genera estas instantaneas en un directorio temporal, pasa el nombre de cada

directorio a un visor de diffs temporal y borra los directorios temporales. Por cuestiones de eficiencia solamentegenera instantaneas de los directorios y ficheros que han cambiado entre dos revisiones.

Los nombres de los directorios de instantaneas tienen los mismos nombres base de su repositorio. Si su repositorio

tiene por ruta /quux/bar/foo, foo sera el nombre de cada instantanea de directorio. Cada instantanea de directorio

tiene sus identificadores de conjuntos de cambios al final del nombre en caso de que sea apropiado. Si una instant anea

viene de la revision a631aca1083f, el directorio se llamara foo.a631aca1083f . Una instantanea del directorio de

trabajo no tendra el identificador del conjunto de cambios, y por lo tanto sera solamente foo en este ejemplo. Para ver

como luce en la practica, veamos de nuevo el ejemplo “hg extdiff” antes mencionado. Tenga en cuenta que los diffs

tienen los nombres de las instantaneas de directorio dentro de su encabezado.

La orden “hg extdiff” acepta dos opciones importantes. La opcion -p le permite elegir un programa para ver las

diferencias, en lugar de diff. Con la opcion -o puede cambiar las opciones que “hg extdiff” pasa a tal programa

(de forma predeterminada las opciones son“-Npru”, que tienen sentido unicamente si esta usando diff). En otros

aspectos, la orden “hg extdiff” actua de forma similar a como lo hace la orden “ hg diff” de Mercurial: usted usa

los mismos nombres de opciones, sintaxis y argumentos para especificar las revisiones y los ficheros que quiere, yası sucesivamente.

Por ejemplo, para ejecutar la orden usual del sistema diff, para lograr que se generen diferencias de contexto

(con la opcion -c) en lugar de diferencias unificadas, y cinco lıneas de contexto en lugar de las tres predeterminadas

(pasando 5 como argumento a la opcion -C).

1 $ hg extdiff -o -NprcC5

2 *** a.d6e1fbefacc8/myfile Tue Feb 10 18:23:22 2009

171

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 182/204

3 --- /tmp/extdiff83LA2p/a/myfile Tue Feb 10 18:23:22 2009

4 ***************

5 *** 1 ****

6 --- 1,2 ----

7 The first line.

8 + The second line.

Es sencillo lanzar unas herramienta usual de diferencias. Para lanzar el visor kdiff3:

1 hg extdiff -p kdiff3 -o ’’

Si su orden para visualizar diferencias no puede tratar con directorios, puede usar un poco de scripting para lograrlo.

Un ejemplo de un script con la extension mq junto con la orden interdiff esta en la seccion 13.9.2.

14.2.1. Definicion de alias de comandos

Acordarse de todas las opciones de las ordenes “hg extdiff” y el visor de diferencias de su preferencia puede

ser dispendioso, y por lo tanto la extension extdiff le permite definir nuevas ordenes que invocaran su visor de

diferencias con las opciones exactas.

Basta con editar su fichero hgrc, y anadir una seccion llamada [extdiff]. Dentro de esta seccion puede definirvarias ordenes. Mostraremos como anadir la orden kdiff3. Despues de definido, puede teclear “hg kdiff3” y la

extension a extdiff ejecutara la orden kdiff3.

1 [extdiff]

2 cmd.kdiff3 =

Si deja vacıa la porcion derecha de la definicion, como en el ejemplo, la extension extdiff usa el nombre de la

orden se definira como el nombre del programa externo a ejecutar. Pero tales nombres no tienen por qu e ser iguales.

Definimos ahora la orden llamada “hg wibble”, que ejecuta kdiff3.

1 [extdiff]

2 cmd.wibble = kdiff3

Tambien puede especificar las opciones predeterminadas con las cuales desea invocar el visor de diferencias. Se

usa el prefijo “opts.”, seguido por el nombre de la orden a la cual se aplican las opciones. En este ejemplos se define

la orden “hg vimdiff” que ejecuta la extension DirDiff del editor vim.

1 [extdiff]

2 cmd.vimdiff = vim

3 opts.vimdiff = -f ’+next’ ’+execute "DirDiff" argv(0) argv(1)’

14.3. Uso de la extension transplant para seleccionar

Need to have a long chat with Brendan about this.

14.4. Enviar cambios vıa correo electronico con la extension patchbomb

Varios proyectos tienen la cultura de “revision de cambios”, en la cual la gente envıa sus modificaciones a una lista

de correo para que otros las lean y comenten antes de consignar la version final a un repositorio compartido. Algunos

proyectos tienen personas que actuan como cancerberos; ellos aplican los cambios de otras personas a un repositorio

para aquellos que no tienen acceso.

172

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 183/204

Mercurial facilita enviar cambios por correo para revision o aplicacion gracias a su extension patchbomb. La

extension es tan popular porque los cambios se formatean como parches y es usual que se envıa un conjunto de

cambios por cada correo. Enviar una gran cantidad de cambios por correos se llama por tanto “bombardear” el buz on

de entrada del destinatario, de ahı su nombre “bombardeo de parches”.

Como es usual, la configuracion basica de la extension patchbomb consta de una o dos lıneas en su hgrc.

1

[extensions]2 patchbomb =

Cuando haya habilitado la extension, dispondra de una nueva orden, llamada “hg email”.

La forma mejor y mas segura para invocar la orden “hg email” es ejecutarla siempre con la opcion -n; que le

mostrara lo que la orden enviarıa, sin enviar nada. Una vez que haya dado un vistazo a los cambios y verificado que

esta enviando los correctos, puede volver a ejecutar la misma orden, sin la opcion -n.

La orden “hg email” acepta la misma clase de sintaxis de revisiones como cualquier otra orden de Mercurial. Por

ejemplo, enviara todas las revisiones entre la 7 y la punta, inclusive.

1 hg email -n 7:tip

Tambien puede especificar un repositorio para comparar. Si indica un repositoro sin revisiones, la orden “ hg email”

enviara todas las revisiones en el repositorio local que no estan presentes en el repositorio remoto. Si especificarevisiones adicionalmente o el nombre de una rama (la ultima con la opcion -b), respetara las revisiones enviadas.

Ejecutar la orden “hg email” sin los nombres de aquellas personas a las cuales desea enviar el correo es comple-

tamente seguro: si lo hace, solicitara tales valores de forma interactiva. (Si esta usando Linux o un sistema tipo Unix,

tendra capacidades estilo–readline aumentadas cuando ingrese tales encabezados, lo cual es sumamente util.)

Cuando envıe una sola revision, la orden “hg email” de forma predeterminada usara la primera lınea de descrip-

cion del conjunto de cambios como el tema del unico mensaje que se enviara.

Si envıa varias revisiones, la orden “hg email” enviara normalmente un mensaje por conjunto de cambios. Colo-

cara como prefacio un mensaje introductorio en el cual usted deberıa describir el proposito de la serie de cambios que

esta enviando.

14.4.1. Cambiar el comportamiento de las bombas de parches

Cada proyecto tiene sus propias convenciones para enviar cambios en un correo electronico; la extension patchbomb

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 opcin -s. Toma un argumento:

el tema del mensaje a usar.

Para cambiar el correo electronico del campo del cual se origina, use la opcion -f. Toma un argumento, el correo

electronico a usar.

El comportamiento predeterminado es enviar diferencias unificadas (consulte la seccion 12.4 si desea una de-

scripcion del formato), una por mensaje. Puede enviar un conjunto binario3 con la opcion -b.

Las diferencias unificadas estan precedidas por un encabezado de metadatos. Puede omitirlo, y enviar diferencias

sin adornos con la opcion --plain.

Las diferencias usualmente se envıan “en lınea”, como parte del cuerpo del mensaje con la descripcion del

parche. Que facilita a a la mayor cantidad de lectores citar y responder partes de un diff, dado que algunos

clientes de correo solamente citaran la primera parte MIME del cuerpo de un mensaje. Si prefiere enviar la

descripcion y el diff en partes separadas del cuerpo, use la opcion -a.

3N. del T. binary bundle

173

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 184/204

En lugar de enviar mensajes de correo puede escribirlos a un fichero con formato- mbox- con la opcion -m. La

opcion recibe un argumento, el nombre del fichero en el cual escribir.

Si desea anadir un resumen con formato-diffstat en cada parche, y uno como mensaje introductorio, use la

opcion -d. La orden diffstat despliega una tabla que contiene el nombre de cada fichero parchado, el numero

de lıneas afectadas, y un historgrama mostrando cuanto ha sido modificado cada fichero. Lo cual ofrece a los

lectores una mirada cuantitativa de cuan complejo es el parche.

174

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 185/204

Apendice A

Referencia de Ordenes

A.1. “hg add”—A ˜ nade ficheros en la proxima consignacion

--include, tambien -I

--exclude, tambien -X--dry-run, tambien -n

A.2. “hg diff”—imprime los cambios en el historial o el directorio actual

Mostrar las diferencias entre revisiones para ficheros especificados o directorios, con el formato unificado diff. Si

desea ver una descripcion del formato unificado diff, ver la seccion 12.4.

De forma predeterminada, esta orden no imprime las diferencias para los ficheros binarios que Mercurial est e sigu-

iendo. Para controlar este comportamiento, vea las opciones -a y --git.

A.2.1. Options

opcion --nodates

Omite la fecha y hora cuando se muestran los encabezados de las diferencias.

--ignore-blank-lines, tambien -B

No imprime los cambios que solamente insertan o eliminan lıneas en blanco. Una lınea que contiene espacios en

blanco no se considera como una lınea en blanco.

--include, tambien -I

Incluye ficheros y directorios cuyos nombres coinciden con los patrones elegidos.

--exclude, tambien -X

Excluye los ficheros y directorios cuyos nombres coinciden con los patrones elegidos.

--text, tambien -a

Si no especifica esta opcion, “hg diff” no mostrara las diferencias de los ficheros que detecte como binarios. Al

especificar -a se forza a “hg diff” a tratar los ficheros como texto, y generar diferencias para todos.

175

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 186/204

Esta opcion es util para los ficherso que son “texto en mayor medida” pero que tienen caracteres NUL. Si lo usa

en ficheros que contienen muchos datos binarios, la salida sera incomprensible.

--ignore-space-change, tambien -b

No imprime si el unico cambio que en la lınea es la cantidad de espacio en blanco.

--git, tambien -g

Mostrar diferencias compatibles con git. XXX reference a format description.

--show-function, tambien -p

Mostrar el nombre de la funcion que contiene elcodigo en una porcion del encabzado usando una heurıstica simple.

Esta funcionalidad se habilita de forma predeterminada, ası que la opcion -p no tiene efectos a menos que cambie el

valor de showfunc en la configuracion, como en el ejemplo siguiente.

1 $ echo ’[diff]’ >> $HGRC

2 $ echo ’showfunc = False’ >> $HGRC

3 $ hg diff

4 diff -r a38a6c74a605 myfile.c

5 --- a/myfile.c Tue Feb 10 18:23:18 2009 +0000

6 +++ b/myfile.c Tue Feb 10 18:23:18 2009 +0000

7 @@ -1,4 +1,4 @@

8 int myfunc()

9 {10 - return 1;

11 + return 10;

12 }13 $ hg diff -p

14 diff -r a38a6c74a605 myfile.c

15 --- a/myfile.c Tue Feb 10 18:23:18 2009 +0000

16 +++ b/myfile.c Tue Feb 10 18:23:18 2009 +0000

17 @@ -1,4 +1,4 @@ int myfunc()

18 int myfunc()

19 {20 - return 1;

21 + return 10;

22 }

--rev, tambien -r

Especifique una o mas revisiones para comparar. La orden “hg diff” acepta hasta dos opciones -r para especificar

las revisiones a comparar.

1. Despliega las diferencias entre la revision padre y del directorio de trabajo.

2. Despliega las diferencias entre el conjunto de cambios especificados y el directorio de trabajo.

3. Despliega las diferencias entre dos conjuntos de cambios especificados.

Puede especificar dos revisiones usando o bien sea las opciones -r o la notacion de rango. Por ejemplo, las dos

especificaciones de revisiones a continuacion son equivalentes:

176

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 187/204

1 hg diff -r 10 -r 20

2 hg diff -r10:20

Cuando especifica dos revisiones, esto tiene significado para Mercurial. Esto significa que “hg diff -r10:20”

producira un diff que transformara los ficheros desde los contenidos en la revision 10 a los contenidos de la revision

20, mientras que “hg diff -r20:10” significa lo opuesto: el diff que transformar ıa los contenidos de los ficheros dela revision 20 a los contenidos de la revision 10. No puede invertir el orden de esta forma si esta haciendo un diff frente

al directorio de trabajo.

--ignore-all-space, tambien -w

A.3. “hg version”—imprime la informacion de version y derechos de re-

produccion

Esta orden despliega la version de Mercurial que esta usando, y su nota de derechos de reproduccion. Hay cuatro

clases de cadenas de version posibles:

La cadena “unknown”. Esta version de Mercurial no fue construida en un repositorio de Mercurial, y no puede

determinar su propia version.

Una cadena numerica corta, tal como “1.1”. Esta es una construccion de una version de Mercurial que se iden-

tifica con una etiqueta especıfica en el repositorio en el cual fue armada (Esto no significa necesariamente que

esta ejecutando una version oficial; alguien pudo haber anadido tal etiqueta a cualquier version del repositorio

en el cual armaron Mercurial).

Una cadena hexadecimal, tal como “875489e31abe”. Esta es una construccion de una revision dada de Mercu-

rial.

Una cadena hexadecimal seguida por una fecha, tal como “ 875489e31abe+20070205 ”. Esta construccion de la

revision de Mercurial fue la construccion de un repositorio que tuvo cambios locales que no han sido consigna-

dos.

A.3.1. Consejos y trucos

¿Por que difieren los resultados de “hg diff” y “hg status”?

Cuando ejecuta la orden “hg status”, vera una lista de ficheros para los cuales Mercurial almacenara cambios la

proxima vez que consigne. Si ejecuta la orden “hg diff”, vera que imprime diferencias solamente para un subconjunto

de los ficheros que “hg status” liste. Hay dos posibles razones para este comportamiento:

La primera es que “hg status” imprime cierta clase de modificaciones que “hg diff” no despliega normalmente.

La orden “hg diff” usualmente despliega diferencias unificadas, las cuales no tienen la habilidad de representar

algunos cambios que Mercurial puede seguir. Lo mas notable es que las diferencias tradicionales no pueden representar

un cambio acerca de la ejecutabilidad de un fichero, pero Mercurial sı almacena esta informacion.

Si usa la opcion --git de “hg diff”, mostrara diferencias compatibles con git que pueden desplegar esta infor-

macion adicional.

La segunda razon posible para que “hg diff” este imprimiendo diferencias para un subconjunto de ficheros delo que muestra “hg status” es que si usted le invoca sin argumento alguno, “ hg diff” imprime diferencias frente

al primer padre del directorio de trabajo. Si ha ejecutado “hg merge” para fusionar dos conjuntos de cambios, pero

no ha consignado aun los resultados de la fusion, su directorio de trabajo tiene dos padres (use “hg parents” para

verlos). Mientras que “hg status” imprime modificaciones relativas a ambos padres despues de una fusion que no

se ha consignado, “hg diff” opera aun relativo solamente al primer padre. Puede lograr que imprima las diferencias

relativas al segundo padre especificando tal padre con la opcion -r. No hay forma de hacer que imprima las diferencias

relativas a los dos padres.

177

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 188/204

Generar diferencias seguras en binarios

Si usa la opcion -a para forzar que Mercurial imprima las diferencias de los ficheros que so o bien “casi comple-

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”, use la opcion “hg diff”–git cuando genere el parche. La orden patch del sistema no puede tratar con

parches binarios.

178

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 189/204

Apendice B

Referencia de las Colas de Mercurial

B.1. Referencia de ordenes MQ

Si desea dar un vistazo a las ordenes que ofrece MQ, use la orden “hg help mq”.

B.1.1. “hg qapplied”—imprimir los parches aplicados

La orden “hg qapplied” imprime la pila actual de parches aplicados. Los parches se imprimen en orden de

antiguedad, primero los mas antiguos y despues los mas recientes, por lo tanto el ultimo parche de la lista es el que

esta en el “tope”.

B.1.2. “hg qcommit”—consignar cambios en la cola del repositorio

La orden “hg qcommit” consigna cualquier cambio sobresaliente en el repositorio .hg/patches. Esta orden so-

lamente funciona si el directorio .hg/patches es un repositorio, p.e. usted creo el directorio con “hg qinit -c” o

ejecuto “hg init” en el directorio despues de correr “hg qinit”.

Esta orden es un atajo para “hg commit --cwd .hg/patches”.

B.1.3. “hg qdelete”—eliminar un parche del fichero series

La orden “hg qdelete” elimina la entrada del fichero series para el parche en el directorio .hg/patches. No

sca el parche si ha sido aplicado. De forma predeterminada no borra el fichero del parche; use la opci on -f para

hacerlo.

Opciones:

-f Elimina el fichero del parche.

B.1.4. “hg qdiff”—imprimir la diferencia del ultimo parche aplicado

La orden “hg qdiff” imprime un diff del parche mas recientemente aplicado. Es equivalente a “hg diff -r-2:-1”.

B.1.5. “hg qfold”—fusionar (“integrar”) varios parches en uno solo

La orden “hg qfold” fusiona muchos parches en el ultimo parche aplicado, de tal forma que el ultimo parche

aplicado es la union de todos los cambios de los parches en cuestion.

Los parches a fusionar no deben haber sido aplicados; “hg qfold” saldra indicando un error si alguno ha sido

aplicado. El orden en el cual los parches se pliegan es significativo; “hg qfold a b” significa “aplique el parche mas

reciente, seguido de a, y seguido de b”.

179

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 190/204

Los comentarios de los parches integrados se colocan al final de los comentarios del parche destino, con cada

bloque de comentarios separado con tres asteriscos (“*”). Se usa la opcion -e para editar el mensaje de consignacion

para el conjunto de cambios/parches despues de completarse el pliegue.

Opciones:

-e Edita el mensaje de consignacion y la descripcion del parche del parche que se ha integrado.

-l Usa los contenidos del fichero dado como el nuevo mensaje de consignacion y descripcion del parche para elparche a integrar.

-m Usa el texto dado como el mensaje de consignacion y descripcion del parche para el parche integrado.

B.1.6. “hg qheader”—desplegar el encabezado/descripcion de un parche

La orden “hg qheader” imprime el encabezado o descripcion de un parche. De forma predeterminada, imprime

el encabezado del ultimo parche aplicado. Si se da un argumento, imprime el encabezado del parche referenciado.

B.1.7. “hg qimport”—importar el parche de un tercero en la cola

La orden “hg qimport” anade una entrada de un parche externo al fichero series y copia el parche en el directorio

.hg/patches. Anade la entrada inmediatamente despues del ultimo parche aplicado, pero no introduce el parche.

Si el directorio .hg/patches es un repositorio, “hg qimport” automaticamente hace un “hg add” del parche

importado.

B.1.8. “hg qinit”—preparar un repositorio para trabajar con MQ

La orden “hg qinit” prepara un repositorio para trabajar con MQ. Crea un directorio llamado .hg/patches.

Opciones:

-c Crea .hg/patches como un repositorio por sı mismo. Tambien crea un fichero .hgignore que ignorara el

fichero status.

Cuando el directorio .hg/patches es un repositorio, las ordenes “hg qimport” y “hg qnew” hacen “hg add”

automaticamente a los parches nuevos.

B.1.9. “hg qnew”—crear un parche nuevo

La orden “hg qnew” crea un parche nuevo. Exige un argumento, el nombre que se usara para tal parche. El parche

recien creado esta vacıo inicialmente. Se anade al fichero series despues del ultimo parche aplicado, y se introduce

en el tope de ese parche.

Si “hg qnew” encuentra ficheros modificados en el directorio de trabajo, rehusara crear un parche nuevo a meos

que se emplee -f la opcion (ver mas adelante). Este comportamiento le permite hacer “hg qrefresh” al ultimo parche

aplicado antes de aplicar un parche nuevo encima de este.

Opciones:

-f Crea un parche nuevo si los contenidos del directorio actual han sido modificados. Cualquier modificaci on

significativa se anade al parche recientemente creado, de tal forma que al finalizar la orden, el directorio de

trabajo no lucira modificado.

-m Usa el texto dado como el mensaje de consignacion. Este texto se almacenara al principio del fichero del parche,

antes de los datos del parche.

B.1.10. “hg qnext”—imprimir el nombre del proximo parche

La orden “hg qnext” imprime el nombre del siguiente parche en el fichero series a continuacion del ultimo

parche aplicado. Este parche serıa el proximo parche a aplicar si se ejecutara la orden “hg qpush”.

180

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 191/204

B.1.11. “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 predetermi-

nada solamente remueve un parche.

Esta orden elimina los conjuntos de cambios que representan los parches sustraıdos del repositorio, y actualiza el

directorio de trabajo para deshacer los efectos de los parches.

Esta orden toma un argumento opcional, que usa como el nombre o el ındice del parche que desea sustraer. Si se da

el nombre, sustraera los parches hasta que el parche nombrado sea el ultimo parche aplicado. Si se da un numero, “hg

qpop” lo trata como un ındice dentro del fichero series, contando desde cero (no cuenta las lıneas vacıas o aquellas

que sean unicamente comentarios). Sustrae los parches hasta que el parche identificado por el ındice sea el ultimo

parche aplicado.

La orden “hg qpop” no lee o escribe parches en el fichero series. “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.

En los dos ultimos casos, use el nombre del parche tal como lo hizo cuando lo aplico.

De forma predeterminada, la orden “hg qpop” no sustraera parche alguno si el directorio de trabajo ha sido modi-

ficado. Puede modificar este comportamiento con la opcion -f, que revierte todas las modificaciones del directorio de

trabajo.

Opciones:

-a Sustrae todos los parches aplicados. Restaura el repositorio al estado antes de haber aplicado parche alguno.

-f Revertir forzadamente cualquier modificacion del directorio de trabajo cuando se hace sustracciones.

-n Sustraer un parche de la cola dado un nombre.

La orden “hg qpop” elimina una lınea del final del fichero status por cada parche que se sustrae.

B.1.12. “hg qprev”—imprimir el nombre del parche anterior

La orden “hg qprev” imprime el nombre del parche en el fichero series que esta antes del ultimo parche aplicado.

Este se volvera el ultimo parche aplicado si ejecuta “hg qpop”.

B.1.13. “hg qpush”—introducir parches a la pila

La orden “hg qpush” anade parches a la pila. De forma predeterminada anade solamente un parche.

Esta orden crea un conjunto de cambios que representa cada parche aplicado y actualiza el directorio de trabajo

aplicando los efectos de los parches.

Los datos predeterminados cuando se crea un conjunto de cambios corresponde a:

La fecha de consignacion y zona horaria corresponden a la hora actual de la zona. Dado que tales datos se

usan para computar la identidad de un conjunto de cambios, significa que si hace “hg qpop” a un parche y

“hg qpush” de nuevo, el conjunto de cambios que introduzca tendra una identidad distinta a la del conjunto de

cambios que sustrajo.

El autor es el mismo que el predeterminado usado por la orden “hg commit”.

El mensaje de consignacion es cualquier texto del fichero del parche que viene antes del primer encabezado del

diff. Si no hay tal texto, un mensaje predeterminado se sua para identificar el nombre del parche.Su un parche contiene un encabezado de parche de Mercurial (XXX add link), la informacion en el encabezado del

parche tiene precedencia sobre el predeterminado.

Opciones:

-a Introduce todos los parches que no han sido aplicados del fichero series hasta que no haya nada mas para

introducir.

181

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 192/204

-l Anade el nombre del parche al final del mensaje de consignacion

-m Si un parche no se aplica limpiamente, usa la entrada para un parche en otra cola almacenada para computar los

parametros en una fusion de tres, y aplica una fusion de tres fuentes usando la maquinaria usual de Mercurial.

Usa la resolucion de la fusion como el contenido del parche nuevo.

-n Usa la cola mencionada si se esta fusionando en la introduccion.

La orden “hg qpush” lee, pero no modifica el fichero series. Anade al final del fichero “hg status” una lınea

por cada parche que se introduce.

B.1.14. “hg qrefresh”—actualiza el ultimo parche aplicado

La orden “hg qrefresh” actualiza el ultimo parche aplicado. Modifica el parche, elimina el ultimo conjunto de

cambios que represento el parche, y crea un nuevo conjunto de cambios para representar el parche modificado.

La orden “hg qrefresh” busca las siguientes modificaciones:

Los cambios al mensaje de consignacion, p.e. el texto antes del primer encabezado de diff en el fichero del

parche, se replejan en el nuevo conjunto de cambios que representa el parche.

Las modificaciones a los ficheros a los que se les da seguimiento en el directorio de trabajo se a nade al parche.

Los cambios a los ficheros a los que se les da seguimiento con “hg add”, “hg copy”, “hg remove”, o “hg

rename”. Se anaden al parche los ficheros anadidos, copiados y renombrados, mientras que los ficheros elimi-

nados y las fuentes renombradas se eliminan.

Incluso si “hg qrefresh” no detecta cambios, de todas maneras recrea el conjunto de cambios que representa el

cambio. Esto causa que la identidad del conjunto de cambios difiera del conjunto de cambios previo que identific o al

parche.

Opciones:

-e Modificar la descripcion de la consignacion y el parche con el editor de texto preferido.

-m Modificar el mensaje de consignacion y la descripcion del parche con el texto dado.

-l Modificar el mensaje de consignacion y la descripcion del parche con el texto del fichero dado.

B.1.15. “hg qrename”—renombrar un parche

La orden “hg qrename” renombra un parche y cambia la entrada del parche en el fichero series.

Con un argumento sencillo, “hg qrename” renombra el ultimo parche aplicado. Con dos argumentos, renombra el

primer argumento con el segundo.

B.1.16. “hg qrestore”—restaurar el estado almacenado de la cola

XXX No idea what this does.

B.1.17. “hg qsave”—almacena el estado actual de la cola

XXX Likewise.

B.1.18. “hg qseries”—imprime la serie completa de parches

La orden “hg qseries” imprime la serie completa de parches del fichero series. Imprime solamente los nombres

de los parches sin las lıneas en blanco o comentarios. Imprime primero el primero y de ultimo, el ultimo aplicado.

182

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 193/204

B.1.19. “hg qtop”—imprime el nombre del parche actual

“hg qtop” imprime el nombre del ultimo parche aplicado.

B.1.20. “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. Los imprime de acuerdo al orden en el cual serıan introducidos.

B.1.21. “hg strip”—remover una revision y sus descendientes

La orden “hg strip” remueve una revision, y todos sus descendientes del repositorio. Deshace los efectos de las

revisiones removidas del repositorio, y actualiza el directorio de trabajo hasta el primer padre de la revision removida.

La orden “hg strip” almacena una copia de segurida de los conjuntos de cambios en un agrupamiento, de forma

tal que puedan ser reaplicados en caso de que se hayan removido por equivocacion.

Opciones:

-b Almacenar conjuntos de cambios no relacionados que se han mezclado con los conjuntos de cambios que estan

en franjas con el agrupamiento de copia de seguridad.

-f Si una rama tiene varias ramas principales remueve todos los frentes. XXX This should be renamed, y usa -fpara desagrupar revisiones cuando hay cambios pendientes.

-n No almacene la copia de seguridad agrupada.

B.2. Referencia de ficheros de MQ

B.2.1. El fichero series

El fichero series contiene una lista de los nombres de todos los parches que MQ puede aplicar. Se representa

como una lista de nombres, uno por l ınea. Se ignora el espacio en blanco al principio y al final.

Las lıneas pueden contener comentario. Un comentario comienza con el caracter “#”, y va hasta el final de la lınea.

Se ignoran las lıneas vacıas y las que solamente contengan comentarios.

En algun momento podrıa editar el fichero series a mano, por tal motivo se admiten comentarios y l ıneas enblanco como se menciono anteriormente. Por ejemplo, puede poner en comentario un parche temporalmente y “ hg

qpush” omitira tal parche cuando los aplique. Tambien puede cambiar el orden en el cual se aplican los parches,

reordenando las entradas en el fichero series.

Tambien es posible colocar el fichero series bajo control de revisiones; tambien es favorable colocar todos los

parches que refiera bajo control de revisiones. Si crea un directorio de parches con la opci on -c de “hg qinit”, esto

se hara automaticamente.

B.2.2. 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. A diferencia del fichero series, este NO ha sido disenado para ser editado. No deberıa colocar este fichero

bajo el control de revisiones o modificarlo de forma alguna. MQ lo usa estrictamente para administraci on interna.

183

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 194/204

Apendice C

Instalar Mercurial desde las fuentes

C.1. En un sistema tipo Unix

Si usa un sistema tipo Unix que tiene una version suficientemente reciente de Python (2.3 o superior) disponible,

es f acil instalar Mercurial desde las fuentes.

1. Descargue un paquete fuente reciente de http://www.selenic.com/mercurial/download .

2. Descomprımalo:

1 gzip -dc mercurial-version.tar.gz | tar xf -

3. Vaya al directorio fuente y ejecute el guion de instalacion. Esto armara Mercurial y lo instalara en su directorio

casa:

1 cd mercurial-version

2 python setup.py install --force --home=$HOME

Cuando termine la instalacion, Mercurial estara en el subdirectorio bin de su directorio casa. No olvide asegurarse deque este directorio este presente en el camino de busqueda de su interprete de ordenes.

Probablemente necesitara establecer la variable de ambiente PYTHONPATH de tal forma que los ejecutables de Mer-

curial puedan encontrar el resto de los paquetes de Mercurial. Por ejemplo, en mi portatil, la establecıa a /home/bos/lib/pytho

La ruta exacta que usted use dependera de como ha sido construıdo Python en su sistema, pero deberıa ser facil de-

ducirla. Si no esta seguro, mire lo que haya mostrado el script en el paso anterior, y vea donde se instalaron los

contenidos del directorio mercurial se instalaron.

C.2. En Windows

Armar e instalar Mercurial en Windows requiere una variedad de herramientas, cierta suficiencia tecnica y pacien-

cia considerable. Personalmente, no le recomiendo hacerlo si es un “usuario casual”. A menos que intente hacer hacks

a Mercurial, le recomiendo que mejor use un paquete binario.Si esta decidido a construir Mercurial desde las fuentes en Windows, siga el “camino dif ıcil” indicado en el wiki de

Mercurial en http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall , y espere que el proceso

sea realmente un trabajo duro.

184

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 195/204

Apendice D

Licencia de Publicacion Abierta

Version 1.0, 8 Junio de 1999

D.1. Requerimientos en versiones modificadas y no modificadas

Los trabajos bajo Publicacion Abierta pueden reproducirse y distribuirse enteros o en porciones, en cualquier

medio fısico o electronico, siempre y cuando se respeten los terminos de esta licencia, y se incorpore esta licencia o

su referencia (con cualquiera de las opciones elegidas por el autor y el editor) en la reproduccion.

A continuacion mostramos la forma correcta de incorporar por referencia:

Copyright (c) a˜ no por nombre del autor o designado. Este material puede distribuirse solamente bajo los

terminos y condiciones especificados por la Licencia de Publicacion Abierta, v x.y o posterior (la ultima

version disponible esta en http://www.opencontent.org/openpub/ ).

La referencia debe estar seguida inmediatamente por cualquier opcion elegida por el(os) autor(es) y/o editor(es)

del documento (consulte la seccion D.6).

Se permite la redistribucion comercial de los materiales sujetos a la Publicacion Abierta.

Cualquier publicacion en forma estandar de libro (papel) requerira citar al editor y autor original. Los nombres

del editor y el autor apareceran en todas las superficies externas del libro. En todas las superficies externas el nombre

del editor debera aparecer en tamano de la misma medida que el tıtulo del trabajo y sera citado como poseedor con

respecto al tıtulo.

D.2. Derechos de reproduccion

El derecho de reproduccion de cada Publicacion Abierta pertenece al(os) autor(es) o designados.

D.3. Alcance de la licencia

Los terminos de licencia dsecritos aplican a todos los trabajos bajo licencia de publicaci on abierta a menos que se

indique de otra forma en este documento.La simple agregacion de trabajos de Publicacion Abierta o una porcion de trabajos de Publicacion Abierta con otros

trabajos o programas en el mismo medio no causaran que esta licencia se aplique a los otros trabajos. Los agregados

deberan contener una nota que especifique la inclusion de matrial de Publicacion Abierta y una nota de derechos de

reproduccion acorde.

Separabilidad. Si cualquier porcion de esta licencia no es aplicable en alguna jurisdicci on, las porciones restantes

se mantienen.

185

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 196/204

Sin garantıa. Los trabajos de Publicacion Abierta se licencian y ofrecen “como estan” sin garantıa de ninguna

clase, expresa o implıcita, incluyendo, pero no limitados a las garantıas de mercabilidad y adaptabilidad para un

proposito particular o garantıa de no infraccion.

D.4. Requerimientos sobre trabajos modificados

Todas las versiones modificadas de documentos cubiertos por esta licencia, incluyendo traducciones, antologıas,

compilaciones y documentos parciales, deben seguir estos requerimientos:

1. La version modificada debe estar etiquetada como tal.

2. La persona que hace la modificacion debe estar identificada y la modificacion con fecha.

3. El dar credito al autor original y al editor si se requiere de acuerdo a las pr acticas academicas de citas.

4. Debe identificarse el lugar del documento original sin modificacion.

5. No puede usarse el(os) nombre(s) del autor (de los autores) para implicar relacion alguna con el documento

resultante sin el permiso explıcito del autor (o de los autores).

D.5. Recomendaciones de buenas practicas

Adicional a los requerimientos de esta licencia, se solicita a los redistribuidores y se recomienda en gran medida

que:

1. Si esta distribuyendo trabajaos de Publicacion Abierta en copia dura o CD-ROM, envıe una notificacion por

correo a los autores acerca de su intencion de redistribuir por lo menos con treinta dıas antes de que su manuscrito

o el medio se congelen, para permitir a los autores tiempo para proveer documentos actualizados. Esta notifi-

cacion deberıa describir las modificaciones, en caso de que haya, al documento.

2. Todas las modificaciones sustanciales (incluyendo eliminaciones) deben estar marcadas claramente en el docu-

mento o si no descritas en un adjunto del documento.

3. Finalmente, aunque no es obligatorio bajo esta licencia, se considera de buenos modales enviar una copia gratis

de cualquier expresion en copia dura o CD-ROM de un trabajo licenciado con Publicacion Abierta a el(os)

autor(es).

D.6. Opciones de licencia

El(os) autor(es) y/o editor de un documento licenciado con Publicacion Abierta pueden elegir ciertas opciones

anadiendo informacion a la referencia o a la copia de la licencia. Estas opciones se consideran parte de la instancia de

la licencia y deben incluirse con la licencia (o su incorporacion con referencia) en trabajos derivados.

A Prohibir la distribucion de versiones substancialmente modificadas sin el permiso explıcito del(os) autor(es). Se

definen “modificaciones substanciales” como cambios en el contenido semantico del documento, y se excluyen

simples cambios en el formato o correcciones tipograficas.

Para lograr esto, anada la frase “Se prohibe la distribucion de versiones substancialmente modificadas de este

documento sin el permiso explıcito del dueno de los derechos de reproduccion.” a la referencia de la licencia o a la

copia.

186

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 197/204

B Esta prohibido prohibir cualquier publicacion de este trabajo o derivados como un todo o una parte en libros estandar

(de papel) con propositos comerciales a menos que se obtenga un permiso previo del dueno de los derechos de

reproduccion.

Para lograrlo, anada la frase “La distribucion del trabajo o derivados en cualquier libro estandar (papel) se prohibe

a menos que se obtenga un permiso previo del dueno de los derechos de reproduccion.” a la referencia de la licencia

o la copia.

187

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 198/204

Bibliograf ıa

[AG] Jean Delvare Andreas Gruenbacher, Martin Quinson. Patchwork quilt. http://savannah.nongnu.org/

projects/quilt.

[BI] Ronald Oussoren Bob Ippolito. Universal macpython. http://bob.pythonmac.org/archives/2006/04/

10/python-and-universal-binaries-on-mac-os-x/.

[Bro] Neil Brown. wiggle–apply conflicting patches. http://cgi.cse.unsw.edu.au/ ˜neilb/source/

wiggle/.

[Dic] Thomas Dickey. diffstat–make a histogram of  diff output. http://dickey.his.com/diffstat/diffstat.html.

[Dus] Andy Dustman. Mysql for python. http://sourceforge.net/projects/mysql-python.

[Gru05] Andreas Gruenbacher. How to survive with many patches (introduction to quilt). http://www.suse.de/

˜agruen/quilt.pdf , June 2005.

[Mas] Chris Mason. mpatch–help solve patch rejects. http://oss.oracle.com/ ˜mason/mpatch/.

[O’S06] Bryan O’Sullivan. Achieving high performance in mercurial. In EuroPython Conference, July 2006. XXX.

[Pyt] Python.org. ConfigParser—configuration file parser. http://docs.python.org/lib/

module-ConfigParser.html.

[RS] GNU Project volunteers Richard Stallman. Gnu coding standards—change logs. http://www.gnu.org/

prep/standards/html_node/Change-Logs.html.

[Tat] Simon Tatham. Putty—open source ssh client for windows. http://www.chiark.greenend.org.uk/

˜sgtatham/putty/.

[Wau] Tim Waugh. patchutils–programs that operate on patch files. http://cyberelk.net/tim/

patchutils/.

188

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 199/204

Indice alfabetico

.hg/hgrc, fichero, 73, 74, 110

.hg/localtags, fichero, 84, 128, 129

.hg/patches.N , directorio, 152

.hg/patches, directorio, 143, 144, 153–155, 178, 179

.hg/store/data, directorio, 36

.hgignore, fichero, 155, 179

.hgrc, fichero, 20, 35

.hgtags, fichero, 83, 84, 128, 129

.orig, fichero, 150

.rej, fichero, 150, 151

.ssh/config, fichero, 69

.ssh, directorio, 67, 68

EMAIL, variable de entorno, 20

HGMERGE, variable de entorno, 31, 33

HGUSER, variable de entorno, 20

HG NODE, variable de entorno, 112, 124

HG PARENT1, variable de entorno, 124

HG PARENT2, variable de entorno, 124

HG SOURCE, variable de entorno, 125

HG URL, variable de entorno, 124, 125

Mercurial.ini, fichero de configuracion, 66

PATH, variable de entorno, 68

PYTHONPATH, variable de entorno, 68, 71, 115, 183acl, extension, 117, 118, 168

acl, gancho, 118

addbreaks, filtro de plantilla, 134

addremove, comando, 52, 149

add, comando, 44, 49–51, 54, 58, 75, 77, 91, 92, 94, 146,

155, 159, 174, 179, 181

opcion --dry-run, 174

opcion --exclude, 174

opcion --include, 174

opcion -I, 174

opcion -n, 174

opcion -X, 174

age, filtro de plantilla, 134annotate, comando, 142, 144, 145

authorized keys, fichero, 67, 68

author, palabra clave de plantilla, 132, 134, 135

filtro domain, 134

filtro email, 134

filtro person, 135

filtro user, 135

backout, comando, 95–102

opcion --merge, 96, 98, 101

opcion -m, 96

basename, filtro de plantilla, 134

bash, comando de sistema, 155

bisect, comando, 102–108

bisect, extension, 2, 142

branches, comando, 86

branches, palabra clave de plantilla, 132

branch, comando, 87, 88

bugzilla, extension, 119–122, 168

bugzilla, gancho, 119, 120

bundle, comando, 126

changegroup, gancho, 109, 112, 125–128

chmod, comando de sistema, 70

clone, comando, 13, 18, 65, 73, 84

opcion -r, 84

commit, comando, 19–21, 30, 41, 49, 52, 86, 112, 116,

117, 153, 155, 158, 178, 180

opcion --addremove, 158

opcion -A, 52

opcion -l, 117opcion -u, 20

commit, gancho, 109, 112, 113, 126, 127, 129

config, comando, 110

convert, comando (extension conver), 10

convert, extension, 10

conver, extension

comando convert, 10

copy, comando, 44, 52–56, 95, 181

opcion --after, 55

cp, comando, 54

cp, comando de sistema, 54

date, filtro de plantilla, 134

date, palabra clave de plantilla, 132, 134, 135filtro age, 134

filtro date, 134

filtro hgdate, 134

filtro isodate, 134, 135

filtro rfc822date, 135

filtro shortdate, 135

189

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 200/204

desc, palabra clave de plantilla, 132, 135

diffstat, comando

opcion -p, 155

diffstat, comando de sistema, 155, 156, 173

diff, comando, 19, 21, 144, 148, 165, 168, 170, 171,

174–178

opcion --exclude, 174opcion --git, 174–176

opcion --ignore-all-space , 176

opcion --ignore-blank-lines , 174

opcion --ignore-space-change , 175

opcion --include, 174

opcion --nodates, 174

opcion --rev, 175

opcion --show-function , 175

opcion --text, 174

opcion -a, 174, 177

opcion -B, 174

opcion -b, 175

opcion -C, 171opcion -c, 171

opcion -g, 175

opcion -I, 174

opcion -N, 148

opcion -p, 175

opcion -r, 148, 175, 176

opcion -w, 176

opcion -X, 174

diff, comando de sistema, 140, 142, 148, 171

domain, filtro de plantilla, 134

email, comando (extension patchbomb), 173

email, comando (extension patchbomb)

opcion --plain, 173opcion -a, 173

opcion -b, 173

opcion -d, 173

opcion -f, 173

opcion -m, 173

opcion -n, 173

opcion -s, 173

email, filtro de plantilla, 134

escape, filtro de plantilla, 134

export, comando, 101

extdiff, comando (extension extdiff), 167, 171, 172

extdiff, comando (extension extdiff)

opcion -o, 171

opcion -p, 171

extdiff, extension, 165–167, 170–172

comando extdiff, 167, 171, 172

extdiff, extension

comando extdiff

opcion-o, 171

opcion-p, 171

fetch, comando, 35

fetch, comando (extension fetch), 168

fetch, extension, 35, 168

comando fetch, 168

ficheros, palabra clave de plantilla, 134

file adds, palabra clave de plantilla, 133file dels, palabra clave de plantilla, 133

files, palabra clave de plantilla, 133

fill68, filtro de plantilla, 134

fill76, filtro de plantilla, 134

filterdiff, comando

opcion --files, 159

opcion --hunks, 159

opcion -i, 158

opcion -x, 158

filterdiff, comando de sistema, 155, 156, 158, 159

firstline, filtro de plantilla, 134

foo, comando, 88

git, comando de sistema, 63, 175, 176grep, comando de sistema, 105, 107

guards, fichero, 162

header, palabra clave de plantilla, 139

heads, comando, 28

help, comando, 12, 13, 143, 178

hg-interdiff, fichero, 166, 167

hgdate, filtro de plantilla, 134

hgext, extension, 167

hgmerge, comando de sistema, 31, 33, 129

hgrc, fichero

seccion acl.allow, 118

seccion acl.deny, 118

seccion acl, 118entrada bundle, 118

entrada pull, 118

entrada push, 118

entrada serve, 118

entrada sources, 118

seccion bugzilla, 119, 121

entrada db, 120

entrada host, 119

entrada notify, 120

entrada password, 120

entrada usermap, 120

entrada user, 120

entrada version, 119

seccion diff

entrada showfunc, 175

seccion extdiff, 172

seccion extensions, 35, 165, 171

seccion hooks, 112

seccion notify, 122

190

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 201/204

entrada config, 122

entrada maxdiff, 123

entrada sources, 123

entrada strip, 122

entrada template, 123

entrada test, 122, 124

seccion uientrada username, 20

entrada verbose, 113

seccion usermap, 120, 122

seccion web, 73, 74, 121, 123

entrada accesslog, 74

entrada address, 74

entrada allow archive, 73

entrada allowpull, 73

entrada baseurl, 121, 123

entrada contact, 73

entrada description, 74

entrada errorlog, 74

entrada ipv6, 74entrada maxchanges, 73

entrada maxfiles, 73

entrada motd, 74

entrada name, 74

entrada port, 74

entrada stripes, 73

entrada style, 73, 74

entrada templates, 74

hgrc, fichero de configuracion, 69, 73, 74, 90, 110–112,

114, 115, 118–122, 131, 165, 167, 170–172

hgweb.cgi, fichero, 70–74

hgweb.config, fichero, 72, 74

hgwebdir.cgi, fichero, 72–74hg, comando de sistema, 68

import, comando, 148, 177

incoming, comando, 22, 65, 110, 131

incoming, gancho, 109, 119, 125–128

init, comando, 155, 178

inotify, extension, 168–170

comando inserve, 170

inserve, comando (extension inotify), 170

interdiff, comando de sistema, 165–167, 172

isodate, filtro de plantilla, 134, 135

kdiff3, comando de sistema, 31, 32, 172

locate, comando, 157

log, comando, 14–18, 20, 21, 82, 83, 87, 88, 96, 131, 132,

142, 153

opcion --patch, 17

opcion --rev, 16, 18

opcion --template, 132, 135

opcion -p, 17

opcion -r, 16, 18

lsdiff comando de sistema, 158

lsdiff, comando de sistema, 156

mercurial.localrepo , modulo

clase localrepository , 115, 124

mercurial.node, modulo

funcion bin, 124

mercurial.ui, moduloclase ui, 115, 124

merge, comando, 29, 35, 40–42, 80, 90, 153, 176

merge, comando de sistema, 33, 34

mpatch, comando de sistema, 151

mq comando de sistema, 155

mq, comando de sistema, 155

mq, extension, 170, 172

comando qapplied, 145, 146, 148, 155, 178

comando qcommit, 155, 178

comando qdelete, 178

comando qdiff, 178

comando qfold, 158, 178

comando qguard, 161, 162comando qheader, 179

comando qimport, 149, 179

comando qinit, 143, 154, 178, 179, 182

comando qnew, 143, 145, 146, 149, 179

comando qnext, 179

comando qpop, 146, 147, 151, 153, 180

comando qprev, 180

comando qpush, 146, 147, 150–153, 158, 162, 170,

179–182

comando qrefresh, 144, 145, 147, 149, 151–153,

156, 158, 179, 181

comando qrename, 181

comando qrestore, 181comando qsave, 152, 181

comando qselect, 162

comando qseries, 145, 146, 148, 153, 181

comando qtop, 155, 156, 182

comando qunapplied, 182

mq, extension

comando qdel

opcion-f, 178

comando qfold

opcion-e, 179

opcion-l, 179

opcion-m, 179

comando qinit

opcion-c, 154, 155, 178, 179, 182

comando qnew

opcion-f, 146, 179

opcion-m, 179

comando qpop

opcion-a, 146, 151, 152, 155, 180

191

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 202/204

opcion-f, 146, 180

opcion-n, 152, 180

comando qpush

opcion-a, 146, 151, 152, 155, 170, 180

opcion-l, 181

opcion-m, 152, 181

opcion-n, 181comando qrefresh

opcion-e, 181

opcion-l, 181

opcion-m, 181

comando qsave

opcion-c, 152

opcion-e, 152

node, palabra clave de plantilla, 133

filtro short, 135

notify, extension, 122–124, 168

obfuscate, filtro de plantilla, 135

outgoing, comando, 24, 131

outgoing, gancho, 109, 110, 126, 127pageant, comando de sistema, 67, 68

parents, comando, 24, 29, 30, 40, 176

parents, palabra clave de plantilla, 133

patchbomb, extension, 165, 172, 173

comando email, 173

patchbomb, extension

comando email

opcion--plain, 173

opcion-a, 173

opcion-b, 173

opcion-d, 173

opcion-f, 173

opcion-m, 173opcion-n, 173

opcion-s, 173

patchutils, paquete, 155, 165

patch comando de sistema, 149

patch, comando

opcion --reverse, 101

opcion -p, 148

patch, comando de sistema, 101, 102, 140, 142, 148–151,

177

perl, comando de sistema, 117

person, filtro de plantilla, 135

plink, comando de sistema, 66, 69

prechangegroup, gancho, 109, 125–128

precommit, gancho, 109, 116, 126–129

preoutgoing, gancho, 109, 112, 126, 127

pretag, gancho, 109, 128, 129

pretxnchangegroup , gancho, 90, 109, 111, 112, 118, 125–

128

pretxncommit, gancho, 109, 111, 113–116, 119, 126–

128

preupdate, gancho, 109, 129

pull, comando, 22–25, 28, 35, 41, 65, 73, 80, 88, 92, 110,

125, 128, 152, 155

opcion -u, 23, 24

push, comando, 25, 80, 125, 126, 128puttygen, comando de sistema, 67

putty, comando de sistema, 67

qapplied, comando (extension mq), 145, 146, 148, 155,

178

qcommit, comando (extension mq), 155, 178

qdelete, comando (extension mq), 178

qdel, comando (extension mq)

opcion -f, 178

qdiff, comando (extension mq), 178

qfold, comando, 178

qfold, comando (extension mq), 158, 178

qfold, comando (extension mq)

opcion -e, 179opcion -l, 179

opcion -m, 179

qguard, comando, 162

qguard, comando (extension mq), 161, 162

qheader, comando (extension mq), 179

qimport, comando (extension mq), 149, 179

qinit, comando, 155, 178

qinit, comando (extension mq), 143, 154, 178, 179, 182

qinit, comando (extension mq)

opcion -c, 154, 155, 178, 179, 182

qnew, comando, 146

qnew, comando (extension mq), 143, 145, 146, 149, 179

qnew, comando (extension mq)opcion -f, 146, 179

opcion -m, 179

qnext, comando (extension mq), 179

qpop, comando, 146, 151, 152, 155

qpop, comando (extension mq), 146, 147, 151, 153, 180

qpop, comando (extension mq)

opcion -a, 146, 151, 152, 155, 180

opcion -f, 146, 180

opcion -n, 152, 180

qprev, comando (extension mq), 180

qpush, comando, 151, 152, 155

qpush, comando (extension mq), 146, 147, 150–153, 158,

162, 170, 179–182

qpush, comando (extension mq)

opcion -a, 146, 151, 152, 155, 170, 180

opcion -l, 181

opcion -m, 152, 181

opcion -n, 181

192

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 203/204

qrefresh, comando (extension mq), 144, 145, 147, 149,

151–153, 156, 158, 179, 181

qrefresh, comando (extension mq)

opcion -e, 181

opcion -l, 181

opcion -m, 181

qrename, comando (extension mq), 181qrestore, comando (extension mq), 181

qsave, comando, 152

qsave, comando (extension mq), 152, 181

qsave, comando (extension mq)

opcion -c, 152

opcion -e, 152

qselect, comando (extension mq), 162

qseries, comando (extension mq), 145, 146, 148, 153,

181

qtop, comando (extension mq), 155, 156, 182

qunapplied, comando (extension mq), 182

remove, comando, 44, 51, 52, 56, 76, 94, 159, 181

opcion --after, 52rename, comando, 44, 55, 56, 80, 95, 181

opcion --after, 56

revert, comando, 52, 58, 93–95, 101, 145

rev, palabra clave de plantilla, 133

rfc822date, filtro de plantilla, 135

rollback, comando, 91, 92, 102

root, comando, 76

sed, comando de sistema, 19

series, fichero, 144, 152, 155, 162, 164, 178–182

serve, comando, 59, 60, 65, 73, 74

opcion -p, 65

shortdate, filtro de plantilla, 135

short, filtro de plantilla, 135ssh-add, comando de sistema, 67, 68

ssh-agent, comando de sistema, 67

ssh-keygen, comando de sistema, 67

ssh, comando

opcion -C, 69

ssh, comando de sistema, 42, 60, 66–69

status, comando, 19, 21, 49, 51–53, 55, 76, 87, 91, 95,

101, 168, 169, 176, 181

opcion -C, 53, 55

status, fichero, 144, 152, 155, 179, 180, 182

strip, comando, 152, 182

opcion -b, 182

opcion -f, 182

opcion -n, 182

strip, filtro de plantilla, 135

sudo apt-get install mercurial-py25, comando de

sistema, 12

sudo port install mercurial, comando de sistema,

12

sudo, comando de sistema, 121

tabindent, filtro de plantilla, 134, 135

tabindent, palabra clave de plantilla, 135

tags, comando, 82, 83

tags, palabra clave de plantilla, 133

tag, comando, 61, 81, 83, 84

opcion -f, 83opcion -l, 84

tag, gancho, 109, 128, 129

tar, comando de sistema, 73

tip, comando, 21, 23, 87, 131, 156

opcion -p, 156

transplant, extension, 172

unbundle, comando, 125, 128

update, comando, 23, 24, 29, 35, 40, 61, 80, 88–90, 101,

152, 155

opcion -C, 88, 152

update, gancho, 110, 129

urlescape, filtro de plantilla, 135

user, filtro de plantilla, 135version, comando, 12, 68, 176

vim, comando de sistema, 172

wiggle, comando de sistema, 151

zip, comando de sistema, 73

Base de datos de fallos de Mercurial

fallo 29, 57

fallo 311, 149

fichero de configuracion

Mercurial.ini (Windows), 66

hgrc (Linux/Unix), 69, 73, 74, 90, 110–112, 114,

115, 118–122, 131, 165, 167, 170–172filtros de plantilla

addbreaks, 134

age, 134

basename, 134

date, 134

domain, 134

email, 134

escape, 134

fill68, 134

fill76, 134

firstline, 134

hgdate, 134

isodate, 134, 135obfuscate, 135

person, 135

rfc822date, 135

shortdate, 135

short, 135

strip, 135

193

7/11/2019 Control Distribuido de Revisiones Con Mercurial

http://slidepdf.com/reader/full/control-distribuido-de-revisiones-con-mercurial 204/204

tabindent, 134, 135

urlescape, 135

user, 135

ganchos

acl, 118

bugzilla, 119, 120changegroup, 109, 112, 125–128

commit, 109, 112, 113, 126, 127, 129

incoming, 109, 119, 125–128

outgoing, 109, 110, 126, 127

prechangegroup, 109, 125–128

precommit, 109, 116, 126–129

preoutgoing, 109, 112, 126, 127

pretag, 109, 128, 129

pretxnchangegroup , 90, 109, 111, 112, 118, 125–

128

pretxncommit, 109, 111, 113–116, 119, 126–128

preupdate 109 129

qtip, 153

variables de entorno

EMAIL, 20

HGMERGE, 31, 33

HGUSER, 20

HG NODE, 112, 124HG PARENT1, 124

HG PARENT2, 124

HG SOURCE, 125

HG URL, 124, 125

PATH, 68

PYTHONPATH, 68, 71, 115, 183