Node:Marcar un momento en el tiempo (marcas), Previous:Formatos de fecha permitidos, Up:Otros comandos útiles de CVS



Marcar un momento en el tiempo (marcas)

Pedir ficheros según una fecha concreta es útil cuando el mero paso del tiempo es su principal preocupación. Pero normalmente lo que realmente querrá será obtener el proyecto tal y como estaba al producirse un determinado evento concreto: quizás el día de hacer una distribución pública, un punto en el que el proyecto se encontraba en su momento más estable, o la vez que se añadió o eliminó cierta característica importante.

Intentar recordar la fecha en la que tuvo lugar un evento en concreto o deducir la fecha a partir de los informes de cambios sería un proceso muy tedioso. Presumiblemente, el evento, en caso de que fuese realmente importante, se marcó como tal en el historial formal de revisiones. El método que ofrece CVS para crear este tipo de marcas se conoce como marcado.

Las marcas ("tags", N. del T.) se diferencian de los envíos corrientes en que no registran ningún cambio particular en el texto de los ficheros, sino más bien un cambio en la forma en que los desarrolladores contemplan los ficheros. Lo que hace una marca es poner una etiqueta al conjunto de revisiones representadas por la copia de trabajo de un desarrollador (lo normal es que la copia de trabajo está completamente al día, así que el nombre de la marca se pone a las revisiones "más recientes y brillantes" presentes en el repositorio).

Poner una marca es tan sencillo como ésto:

floss$ cvs -q tag Release-1999_05_01
T README.txt
T hello.c
T a-subdir/loquesea.c
T a-subdir/subsubdir/fish.c
T b-subdir/random.c
floss$

Este comando asocia el nombre simbólico "Release-1999_05_01" a la instantánea representada por esta copia de trabajo. Definida formalmente, una "instantánea" es un conjunto de ficheros del proyecto y los números de revisión asociados con ellos. Estos números de revisión no tienen por qué ser los mismos entre varios ficheros, y de hecho no suelen serlo. Por ejemplo, suponiendo que la marca se hubiera puesto en el mismo directorio "miproyecto" que hemos estado utilizando en este capítulo y que la copia de trabajo estuviese completamente al día, el nombre simbólico "Release-1999_05_01" se asociaría a la revisión 1.5 de hello.c, a la revisión 1.2 de fish.c, a la revisión 1.2 de random.c, y a la revisión 1.1 de todo lo demás.

Quizás le ayude el pensar en una marca como en una senda o cadena que une varias revisiones de ficheros del proyecto. En la Figura 2.1, una cadena imaginaria pasa por el número de revisión marcado en cada fichero del proyecto.

     Fichero A   Fichero B   Fichero C   Fichero D   Fichero E
     ---------   ---------   ---------   ---------   ---------
     1.1         1.1         1.1         1.1         1.1
 ----1.2-.       1.2         1.2         1.2         1.2
     1.3 |       1.3         1.3         1.3         1.3
          \      1.4       .-1.4-.       1.4         1.4
           \     1.5      /  1.5  \      1.5         1.5
            \    1.6     /   1.6   |     1.6         1.6
             \   1.7    /          |     1.7         1.7
              \  1.8   /           |     1.8       .-1.8------->
               \ 1.9  /            |     1.9      /  1.9
                `1.10'             |     1.10    /   1.10
                 1.11              |     1.11    |
                                   |     1.12    |
                                   |     1.13    |
                                    \    1.14    |
                                     \   1.15   /
                                      \  1.16  /
                                       `-1.17-'

[Figura 2.1: La relación que puede haber entre una marca y determinadas
revisiones de los ficheros.]

Ahora, si estira la cadena y la observa de forma longitudinal, podrá ver un momento específico en el historial del proyecto; concretamente, el momento en el que se fijó la marca (Figura 2.2).

     Fichero A   Fichero B   Fichero C   Fichero D   Fichero E
     ---------   ---------   ---------   ---------   ---------
                                         1.1
                                         1.2
                                         1.3
                                         1.4
                                         1.5
                                         1.6
                                         1.7
                 1.1                     1.8
                 1.2                     1.9
                 1.3                     1.10        1.1
                 1.4                     1.11        1.2
                 1.5                     1.12        1.3
                 1.6                     1.13        1.4
                 1.7         1.1         1.14        1.5
                 1.8         1.2         1.15        1.6
     1.1         1.9         1.3         1.16        1.7
 ----1.2---------1.10--------1.4---------1.17--------1.8------->
     1.3         1.11        1.5         1.17        1.9
                             1.6         1.17        1.10

[Figura 2.2: La misma marca vista longitudinalmente respecto al historial
de revisiones.]


A medida que sigue editando ficheros y enviando cambios, la marca *no* se moverá de su sitio a pesar de que los números de revisión se vayan incrementando. Permanece fija, "pegada" al número de revisión de cada fichero al que fue asociada.

Dada su importancia como elementos descriptivos, es una pena que los informes de cambios no puedan ser incluidos con las marcas, y que las marcas en sí no puedan ser párrafos de texto reales. En el ejemplo anterior, la marca indica de forma bastante obvia que el proyecto se encontraba en un estado "publicable" en una fecha determinada. Sin embargo, a veces querrá hacer instantáneas de un estado más complejo, lo que puede dar lugar a nombres de marcas un tanto extraños, como:

floss$ cvs tag testing-release-3_pre-19990525-public-release

Por regla general, debería intentar mantener las marcas lo más simples posible al tiempo que incluye toda la información necesaria sobre el evento que está intentando registrar. En caso de duda, es mejor pecar de demasiado descriptivos - lo agradecerá más tarde cuando sea capaz de determinar gracias a una marca extremadamente descriptiva exactamente qué circunstancia se registró con ella.

Posiblemente se haya dado cuenta de que no se han usado puntos ni espacios en el nombre de las marcas. CVS es bastante estricto en lo que atañe a nombres válidos de marcas: las reglas son que deben comenzar con una letra y tener letras, dígitos, guiones ("-"), y signos de subrayado ("_"). No se pueden utilizar espacios, puntos, signos de dos puntos, comas ni ningún otro símbolo.

Para obtener una instantánea haciendo referencia a una marca, deberá usar el nombre de esta marca como si fuera un número de revisión. Hay dos formas de obtener instantáneas: puede obtener una copia de trabajo nueva con una determinada marca, o bien puede cambiar una copia de trabajo ya existente por una marca. Ambos métodos tienen como resultado una copia de trabajo en la que las revisiones de los ficheros son los asociados a la marca dada.

La mayor parte de las veces, lo que querrá hacer es echar un vistazo al proyecto tal como éste se encontraba en el momento de hacer la instantánea. No necesariamente querrá hacer esto en su copia de trabajo principal, donde posiblemente tenga cambios aún sin enviar y otras cosas importantes que preferirá salvaguardar, así que vamos a suponer que simplemente desea obtener una copia de trabajo por separado, con la marca. Así es cómo se hace (¡asegúrese de invocar este comando desde cualquier otro lugar que no sea su copia de trabajo actual o su directorio padre!):

floss$ cvs checkout -r Release-1999_05_01 miproyecto
cvs checkout: Updating miproyecto
U miproyecto/README.txt
U miproyecto/hello.c
cvs checkout: Updating miproyecto/a-subdir
U miproyecto/a-subdir/loquesea.c
cvs checkout: Updating miproyecto/a-subdir/subsubdir
U miproyecto/a-subdir/subsubdir/fish.c
cvs checkout: Updating miproyecto/b-subdir
U miproyecto/b-subdir/random.c
cvs checkout: Updating miproyecto/c-subdir

Anteriormente hemos visto cómo se utilizaba la opción -r con el comando "update", donde precedía a un número de revisión. En muchos aspectos, una marca es como un número de revisión, porque, para cada fichero, cada marca se corresponde exactamente con *un* número de revisión concreto (es ilegal, y generalmente imposible, tener dos marcas con el mismo nombre en el mismo proyecto). De hecho, en cualquier lugar donde pueda utilizar un número de revisión como argumento de un comando de CVS, podrá también utilizar el nombre de una marca, siempre y cuando esa marca se haya creado antes. Si quiere ver las diferencias entre el estado actual de un fichero y el estado en el que se encontraba en el momento de realizar la última distribución pública, puede hacer esto:

floss$ cvs diff -c -r Release-1999_05_01 hello.c

Y si quiere volver atrás temporalmente a aquella revisión, puede hacer esto:

floss$ cvs update -r Release-1999_05_01 hello.c

La posibilidad de intercambiar nombres de marcas y números de revisión explica algunas de las estrictas reglas que definen qué nombre de marca es válido y cuál no. Imagine por un momento que los puntos fueran legales en los nombres de las marcas; podría tener una marca llamada "1.3" asociada a un número real de revisión como puede ser el "1.47". Si ahora emplease el comando

floss$ cvs update -r 1.3 hello.c

¿cómo podría CVS saber si se refiere a la marca llamada "1.3", o a la mucho más antigua revisión 1.3 de hello.c? Es por esto por lo que existen este tipo de restricciones en los nombres de las marcas, de forma que siempre puedan distinguirse fácilmente de los números de revisión. Un número de revisión tiene un punto; el nombre de una marca no. (También hay motivos para las demás restricciones, generalmente para permitir que los nombres de las marcas sean fáciles de interpretar para CVS.)

Como posiblemente habrá ya adivinado, el segundo método para obtener una instantánea -esto es, pasar un directorio de trabajo ya existente a las revisiones marcadas- también se realiza por medio de una actualización:

floss$ cvs update -r Release-1999_05_01
cvs update: Updating .
cvs update: Updating a-subdir
cvs update: Updating a-subdir/subsubdir
cvs update: Updating b-subdir
cvs update: Updating c-subdir
floss$

Este comando es similar al que utilizamos para devolver hello.c al estado en el que se encontraba en Release-1999_05_01, con la salvedad de que se omite el nombre del fichero dado que queremos volver atrás el proyecto al completo (si lo desea, puede hacer volver atrás solamente un sub-árbol del proyecto, invocando este comando mientras se encuentra en ese subdirectorio en lugar de hacerlo desde el nivel más alto, aunque muy pocas veces querrá hacer esto).

Observe que, a juzgar por los resultados del comando, no parece que haya cambiado ningún fichero. La copia de trabajo estaba completamente al día cuando pusimos la marca, y no se había enviado ningún cambio desde entonces.

Sin embargo, esto no significa que no haya habido ningún cambio en absoluto. La copia de trabajo sabe ahora que responde a una revisión marcada. Cuando hagamos un cambio e intentemos enviarlo al repositorio (supongamos que hemos modificado hello.c):

floss$ cvs -q update
M hello.c
floss$ cvs -q ci -m "intentando enviar desde una copia de trabajo marcada"
cvs commit: sticky tag 'Release-1999_05_01' for file 'hello.c' is not a branch
cvs [commit aborted]: correct above errors first!
floss$

... CVS impide que el envío llegue a producirse (no se preocupe de momento por lo que significa el mensaje de error - más adelante y en este mismo capítulo trataremos el tema de las "branches", o ramas para entendernos). Poco importa si la copia de trabajo llegó a tener una marca a través de la obtención de una copia de trabajo ("checkout") o una simple actualización; la cuestión es que, una vez que está marcada, CVS considera la copia de trabajo como una instantánea estática de un momento particular de la historia, y CVS no le permitirá cambiar la historia, o cuando menos no se lo pondrá fácil. Si ejecuta "cvs status" o examina los ficheros CVS/Entries, podrá ver que hay una marca pegada a cada fichero. Por ejemplo, aquí tiene el fichero Entries del directorio raíz:

floss$ cat CVS/Entries
D/a-subdir////
D/b-subdir////
D/c-subdir////
/README.txt/1.1.1.1/Sun Apr 18 18:18:22 1999//TRelease-1999_05_01
/hello.c/1.5/Tue Apr 20 07:24:10 1999//TRelease-1999_05_01
floss$

Las marcas, como otras propiedades de carácter "pegadizo", pueden eliminarse con la opción -A durante una actualización:

floss$ cvs -q update -A
M hello.c
floss$

Sin embargo, la modificación de hello.c no ha desaparecido; CVS todavía sabe que el fichero ha cambiado respecto a su homónimo en el repositorio:

floss$ cvs -q diff -c hello.c
Index: hello.c
===================================================================
RCS file: /usr/local/cvs/miproyecto/hello.c,v
retrieving revision 1.5
diff -c -r1.5 hello.c
*** hello.c   1999/04/20 06:12:56     1.5
--- hello.c   1999/05/04 20:09:17
***************
*** 6,9 ****
--- 6,10 --
    printf ("¡Hola, mundo!\n");
    printf ("entre hola y adiós\n");
    printf ("¡Adiós, mundo!\n");
+   /* un comentario en la última línea */
  }
floss$

Ahora que ha puesto las cosas en orden por medio de la actualización, CVS aceptará hacer un envío:

floss$ cvs ci -m "añadido un comentario al final de la función main"
cvs commit: Examining .
cvs commit: Examining a-subdir
cvs commit: Examining a-subdir/subsubdir
cvs commit: Examining b-subdir
cvs commit: Examining c-subdir
Checking in hello.c;
/usr/local/cvs/miproyecto/hello.c,v  <-  hello.c
new revision: 1.6; previous revision: 1.5
done
floss$

Por supuesto, la marca Release-1999_05_01 sigue estando asociada a la revisión 1.5. Compare el estado del fichero de como estaba antes a como está después de eliminar la marca:

floss$ cvs -q status hello.c
===================================================================
File: hello.c                 Status: Up-to-date
   Working revision:  1.6     Tue May  4 20:09:17 1999
   Repository revision:       1.6     /usr/local/cvs/miproyecto/hello.c,v
   Sticky Tag:                (none)
   Sticky Date:               (none)
   Sticky Options:            (none)
floss$ cvs -q update -r Release-1999_05_01
U hello.c
floss$ cvs -q status hello.c
===================================================================
File: hello.c                 Status: Up-to-date
   Working revision:  1.5     Tue May  4 20:21:12 1999
   Repository revision:       1.5     /usr/local/cvs/miproyecto/hello.c,v
   Sticky Tag:                Release-1999_05_01 (revision: 1.5)
   Sticky Date:               (none)
   Sticky Options:            (none)
floss$

Y ahora que vengo de decirle que CVS no le permite cambiar la historia, le enseñaré precisamente cómo cambiarla.