Node:Marcar un momento en el tiempo (marcas), Previous:Formatos de fecha permitidos, Up:Otros comandos útiles de CVS
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.