Node:Formato RCS, Next:, Previous:Estructura del repositorio, Up:Administracion del Repositorio



Formato RCS

No necesita conocer nada del formato RCS para usar CVS (aunque hay un escrito excelente incluido en la distribución fuente, vea doc/RCSFILES). Sin embargo, una comprensión básica del formato puede ser de inmensa ayuda para resolver problemas con CVS, así que echaremos un pequeño vistazo a uno de los ficheros, hello.c,v. Aquí está su contenido:

head     1.1;
branch   1.1.1;
access   ;
symbols  start:1.1.1.1 jluis:1.1.1;
locks    ; strict;
comment  @ * @;

1.1
date     99.06.20.17.47.26;  author jluis;  state Exp;
branches 1.1.1.1;
next;

1.1.1.1
date     99.06.20.17.47.26;  author jluis;  state Exp;
branches ;
next;

desc
@@

1.1
log
@Initial revision
@
text
@#include <stdio.h>

void
main ()
{
  printf ("¡Hola, mundo!\n");
}
@

1.1.1.1
log
@importación inicial a CVS
@
text
@@

¡Uff! La mayoría de esto se puede ignorar; no hace falta que se preocupe de la relación entre 1.1 y 1.1.1.1, por ejemplo, o de la rama implicada 1.1.1 - en realidad no son significativas, desde un punto de vista del usuario o incluso del administrador. Lo que debería comprender es el formato en general. Al comienzo hay una colección de cabeceras:

head     1.1;
branch   1.1.1;
access   ;
symbols  start:1.1.1.1 jluis:1.1.1;
locks    ; strict;
comment  @ * @;

Más abajo hay grupos de metainformación sobre cada revisión (pero aún sin mostrar el contenido de esa revisión), como:

1.1
date     99.06.20.17.47.26;  author jluis;  state Exp;
branches 1.1.1.1;
next     ;

Y finalmente, el informe de cambios ("log message", N. del T.) y texto de una revisión real:

1.1
log
@Initial revision
@
text
@#include <stdio.h>

void
main ()
{
  printf ("¡Hola, mundo!\n");
}
@

1.1.1.1
log
@importación inicial a CVS
@
text
@@

Si lo mira de cerca verá que el contenido de la primera revisión se guarda bajo la cabecera 1.1, pero en ella el informe de cambios es "Initial revision", mientras que el mensaje que usamos en realidad a la hora de importar fue "importación inicial a CVS". No es necesario que se preocupe por esta discrepancia ahora. Ocurre porque las importaciones son circunstancias especiales: para que importaciones repetidas en el mismo proyecto tengan un efecto útil, la importación en realidad coloca la revisión inicial en el tronco principal y en una rama especial (las razones para ello se aclararán cuando veamos derivaciones comerciales en CVS avanzado). Por ahora puede tratar 1.1 y 1.1.1.1 como la misma cosa.

El fichero se vuelve aún más revelador después de que enviemos con commit la primera modificación a hello.c:

floss$ cvs -Q co miproyecto
floss$ cd miproyecto
floss$ emacs hello.c
    (haga algunos cambios al fichero)

floss$ cvs ci -m "ahora también dice adiós"
cvs commit: Examining .
cvs commit: Examining a-subdir
cvs commit: Examining a-subdir/subsubdir
cvs commit: Examining b-subdir
Checking in hello.c;
/usr/local/nuevorepos/miproyecto/hello.c,v  <--  hello.c
new revision: 1.2; previous revision: 1.1
done

Si mira en el repositorio a hello.c,v verá el efecto del envío de cambios:

head  1.2;
access;
symbols
      start:1.1.1.1 jluis:1.1.1;
locks; strict;
comment   @ * @;

1.2
date   99.06.21.01.49.40;   author jluis;   state Exp;
branches;
next   1.1;

1.1
date   99.06.20.17.47.26;   author jluis;   state Exp;
branches
       1.1.1.1;
next   ;

1.1.1.1
date   99.06.20.17.47.26;   author jluis;   state Exp;
branches;
next   ;

desc
@@

1.2
log
@ahora también dice adiós
@
text
@#include <stdio.h>

void
main ()
{
  printf ("¡Hola, mundo!\n");
  printf ("¡Adiós, mundo!\n");
}
@

1.1
log
@Initial revision
@
text
@d7 1
@

1.1.1.1
log
@importación inicial a CVS
@
text
@@

Ahora el contenido completo de la revisión 1.2 está guardado en el fichero, y el texto para la revisión 1.1 ha sido reemplazado por la fórmula críptica:

d7 1

El d7 1 es un código diff que quiere decir "empezando en la línea 7, borrar 1 línea". En otras palabras, ¡para obtener la Revisión 1.1, borre la línea 7 de la Revisión 1.2! Pruébelo usted mismo. Verá que de hecho produce la Revisión 1.1 - simplemente se deshace de la línea que añadimos al fichero.

Esto demuestra el principio básico del formato RCS: Almacena sólo las diferencias entre revisiones, ahorrando con ello un montón de espacio comparado con guardar cada revisión entera. Para volver desde la última revisión a la anterior, parchea la última revisión usando el diff almacenado. Por supuesto, esto significa que cuanto más hacia atrás viaje en la historia de revisiones, habrá que realizar más operaciones de parcheo (por ejemplo, si el fichero está en la Revisión 1.7 y a CVS se le pide que muestre la Revisión 1.4, tendrá que producir la 1.6 parcheando hacia atrás la 1.7, luego la 1.5 parcheando la 1.6, y finalmente la 1.4 parcheando la 1.5). Por suerte, las revisiones antiguas son además las menos solicitadas, así que el sistema RCS funciona bastante bien en la práctica: Cuanto más reciente sea una revisión, más "barata" es de obtener.

En cuanto a la información de cabecera al principio del fichero, no necesita saber lo que significa todo ello. Sin embargo, los efectos de ciertas operaciones se muestran muy claramente en las cabeceras, y una pequeña familiaridad con ellas puede resultar útil.

Cuando envía cambios de una nueva revisión al tronco, la etiqueta head se actualiza (note cómo cambió a 1.2 en el ejemplo anterior, cuando se envió el cambio de la segunda revisión a hello.c). Cuando añade un fichero como binario o lo marca, esas operaciones se registran también en las cabeceras. Como ejemplo, vamos a añadir foo.jpg como fichero binario para después marcarlo un par de veces:

floss$ cvs add -kb foo.jpg
cvs add: scheduling file 'foo.jpg' for addition
cvs add: use 'cvs commit' to add this file permanently
floss$ cvs -q commit -m "añadida una imagen aleatoria; pregunte a \
   jluis@red-bean.com el motivo"
RCS file: /usr/local/nuevorepos/miproyecto/foo.jpg,v
done
Checking in foo.jpg;
/usr/local/nuevorepos/miproyecto/foo.jpg,v  <--  foo.jpg
initial revision: 1.1
done
floss$ cvs tag alguna_marca_aleatoria foo.jpg
T foo.jpg
floss$ cvs tag OTRA-MARCA foo.jpg
T foo.jpg
floss$

Examine ahora la sección "header" de foo.jpg,v en el repositorio:

head   1.1;
access;
symbols
      OTRA-MARCA:1.1
      alguna_marca_aleatoria:1.1;
locks; strict;
comment   @# @;
expand	@b@;

Fíjese en la b en la línea "expand" del final - se debe a haber usado el parámetro -kb al añadir el fichero, y quiere decir que el fichero no sufrirá expansiones de palabra clave o nueva línea, que ocurrirían normalmente durante obtenciones de copia y actualizaciones si fuera un fichero de texto normal. Las marcas aparecen en la sección "symbols", una por línea - ambas están asociadas a la primera revisión, puesto que eso es lo que se marcó ambas veces. (Esto también ayuda a explicar por qué los nombres de marca pueden sólo contener letras, números, guiones y guiones bajos. Si la propia marca contuviera puntos o comas, su registro RCS podría ser ambiguo, porque no habría forma de encontrar el enlace textual entre la marca y la revisión a la que está asociada.)

El formato RCS siempre va entre signos @

El símbolo @ se usa como delimitador de campos en los ficheros RCS, lo que significa que si aparece alguno en el texto de un fichero o en un informe de cambios, deberá estar comentado (de lo contrario, CVS interpretaría incorrectamente que está marcando el final de ese campo). Se comenta poniéndolo doble - es decir, CVS siempre interpreta @@ como un "signo @ literal", nunca como un "fin de campo actual". Cuando enviamos los cambios a foo.jpg, el informe de cambios fue

"añadida una imagen aleatoria; pregunte a jluis@red-bean.com el motivo"

que se almacena en foo.jpg,v así:

1.1
log
@añadida una imagen aleatoria; pregunte a jluis@@red-bean.com el motivo
@

El signo @ en jluis@@red-bean.com se descomentará automáticamente cada vez que CVS obtenga el informe de cambios:

floss$ cvs log foo.jpg
RCS file: /usr/local/nuevorepos/miproyecto/foo.jpg,v
Working file: foo.jpg
head: 1.1
branch:
locks: strict
access list:
symbolic names:
      OTRA-MARCA: 1.1
      alguna_marca_aleatoria: 1.1
keyword substitution: b
total revisions: 1;	selected revisions: 1
description:
----------------------------
revision 1.1
date: 1999/06/21 02:56:18;  author: jluis;  state: Exp;
añadida una imagen aleatoria: pregunte a jluis@red-bean.com el motivo
============================================================================

floss$

El único motivo por el que debería preocuparse es por si alguna vez tiene que editar a mano ficheros RCS (una circunstancia rara, aunque le ha pasado a más de uno) Debe acordarse entonces de usar signos dobles @ en contenidos de la revisión e informes de cambios. Si no lo hace, el fichero RCS estará corrupto y probablemente tendrá un comportamiento extraño e indeseable.

Hablando de editar a mano ficheros RCS, no se deje engañar por los permisos en el repositorio:

floss$ ls -l
total 6
-r--r--r--   1 jluis   users         410 Jun 20 12:47 README.txt,v
drwxrwxr-x   3 jluis   users        1024 Jun 20 21:56 a-subdir/
drwxrwxr-x   2 jluis   users        1024 Jun 20 21:56 b-subdir/
-r--r--r--   1 jluis   users         937 Jun 20 21:56 foo.jpg,v
-r--r--r--   1 jluis   users         564 Jun 20 21:11 hello.c,v

floss$

(Para los que no estén familiarizados con la salida de "ls" en Unix, las líneas -r--r--r-- de la izquierda básicamente quieren decir que los ficheros se pueden leer pero no cambiar.) Aunque los ficheros parecen ser de sólo lectura para todos, también hay que tener en cuenta los permisos de directorio:

floss$ ls -ld .
drwxrwxr-x   4 jluis   users        1024 Jun 20 22:16 ./
floss$

El propio directorio miproyecto/ - y sus subdirectorios - es accesible para escritura por el propietario (jluis) y el grupo (users). Esto significa que CVS (ejecutándose como jluis o como cualquiera del grupo users) puede crear y borrar ficheros en esos directorios, incluso si no puede editar directamente los ficheros a presentes. CVS edita un fichero RCS haciendo una copia separada de él, de forma que usted haga todos sus cambios en una copia temporal, y luego reemplaza el fichero RCS existente con el nuevo. (Pero por favor, no pregunte por qué los ficheros son de sólo lectura - hay razones históricas para ello, relacionadas con la forma en que RCS trabaja cuando se ejecuta como programa en solitario.)

Por cierto, puede que usted no desee que el grupo de los ficheros sea users, considerando que el directorio raíz del repositorio se le asignó explícitamente el grupo cvs. Puede corregir el problema ejecutando esta orden dentro del repositorio:

floss$ cd /usr/local/nuevorepos
floss$ chgrp -R cvs miproyecto

Las reglas habituales Unix de creación de ficheros rigen qué grupo se asigna a los nuevos ficheros que aparecen en el repositorio, así que de vez en cuando puede que necesite ejecutar "chgrp" o "chmod" en ciertos ficheros o directorios del repositorio (ajustar el bit SGID con chmod g+s es a menudo una buena estrategia: hace que los hijos de un directorio hereden el grupo propietario del directorio, que por lo general es lo que quiere que pase en el repositorio). No hay reglas rápidas acerca de cómo debería estructurar los permisos del repositorio; depende de quién esté trabajando en qué proyectos.