CVS
Introducción
CVS (Concurrent Versions System) es un sistema de control de versiones para mantener código fuente por parte de un grupo de desarrolladores que trabajen en un proyecto común. El fin de CVS es doble, por un lado se encarga de guardar un registro de cambios, y por otro lado posibilita la colaboración de un grupo de personas en el desarrollo de un proyecto.
CVS permite trabajar y modificar concurrentemente ficheros organizados en proyectos. Es decir, dos o más personas pueden modificar un mismo fichero sin que se pierda el trabajo de ninguna. Además, CVS guarda las versiones antiguas de los ficheros, lo que permite recuperar en cualquier momento versiones anteriores a la actual.
Con CVS se puede trabajar de forma local (repositorio y copias de trabajo en el mismo sistema) o remota (el repositorio está en un sistema servidor y la copia local en un sistema cliente). Esta última es la forma de trabajo habitual ya que es la que ofrece más ventajas.
CVS trabaja con ficheros ASCII, por lo que se puede utilizar para trabajar con código fuente, o bien para trabajar con documentos en formato texto, como ficheros sgml o xml.
Conceptos básicos
- Módulo (proyecto) Árbol de directorios que forma parte del repositorio; cuenta con un nombre identificador gracias al cual podremos bajárnoslo de forma selectiva.
- Repositorio (almacén) Jerarquía de directorios alojada en el servidor formada por los distintos módulos. Copia maestra en la que CVS guarda el historial de revisiones al completo efectuadas en un proyecto. Cada proyecto tiene exactamente un repositorio.
- Revisión Cambio aplicado y registrado en el historial de un fichero o
conjunto de ficheros. Una revisión es una instantánea de un
proyecto que cambia constantemente. - Copia de trabajo La copia en la que puede de hecho hacer cambios al proyecto. Puede haber muchas copias de trabajo de un proyecto dado. Por regla general, cada desarrollador tiene su propia copia de trabajo.
- Obtener una copia (check out) Solicitar una copia de trabajo al repositorio. Su copia de trabajo refleja el estado del proyecto en el momento de obtenerla; cuando Ud. y otros desarrolladores hacen cambios, deben enviarlos (
commit
) y actualizarlos (update
) tanto para publicar sus cambios como para ver los que han hecho los demás. - Enviar (commit) Enviar cambios de su copia local al repositorio central. También conocido como check-in.
- Informe de cambios Comentario que se adjunta a una revisión cuando ésta se envía, describiendo los cambios realizados. Otros pueden leer los informes de cambios para obtener un resumen de lo que ha estado sucediendo en un proyecto.
- Actualizar (update) Incorporar a su copia de trabajo los cambios que otros han hecho y están presentes en el repositorio, y comprobar si su copia de trabajo tiene algún cambio que no ha enviado todavía. Lo que hace una actualización es sincronizar su copia de trabajo con la copia presente en el repositorio.
- Conflicto Situación que se da cuando dos desarrolladores intentan enviar cambios que han hecho al mismo pasaje de un fichero. CVS se da cuenta de ello e informa del conflicto, pero son los desarrolladores quienes tienen que resolverlo.
Funcionamiento de CVS
CVS permite a los desarrolladores editar el código de forma simultánea, asume la tarea de integrar todos los cambios, y guarda un registro de todos los conflictos que vayan surgiendo. El proceso utiliza el modelo copiar-modificar-fusionar, que funciona de la forma siguiente:
- El desarrollador A solicita a CVS una copia de trabajo, esto es, un árbol de directorios que contiene los ficheros que conforman el proyecto. Esta operación es también conocida como obtener una copia (comando checkout), y es como tomar un libro prestado de una biblioteca.
- El desarrollador A edita libremente su copia de trabajo. Al mismo tiempo, otros desarrolladores pueden estar atareados con sus propias copias de trabajo. Puesto que todas son copias separadas, no hay interferencias: es como si todos los desarrolladores tuvieran su propia copia del mismo libro, y todos estuvieran trabajando anotando comentarios en los márgenes o reescribiendo determinadas páginas de forma independiente.
- El desarrollador A termina sus cambios y los envía (comando commit) a CVS junto con un informe de cambios, que es un comentario que explica la naturaleza y propósito de los cambios que ha realizado. Esto es el equivalente a informar a la biblioteca de los cambios que ha hecho al libro y el porqué de los mismos. Entonces, la biblioteca incorpora estos cambios a la copia maestra, donde se guardan de forma permanente.
- Mientras tanto, y también por medio de CVS, otros desarrolladores pueden consultar a la biblioteca para ver si la copia maestra ha cambiado recientemente, en cuyo caso CVS actualizará automáticamente sus copias de trabajo personales.
Por lo que concierne a CVS, todos los desarrolladores de un proyecto son iguales. La decisión de cuándo actualizar o cuándo enviar al almacén es un tema de preferencias personales o de política establecida entre los miembros que participan en el proyecto. Una de las estrategias más comunes para proyectos de programación es la de siempre actualizar antes de empezar a trabajar en un cambio importante, y enviar los cambios sólo cuando éstos hayan sido finalizados y probados, a fin de que la copia principal se mantenga en todo momento en un estado ejecutable.
Uso de CVS
Invocación de CVS
CVS es un solo programa, según con qué opciones se invoque hará unas cosas u otras (como pueden ser, actualizar, enviar, etc.). El formato de invocación de cvs es de la forma:
cvs opciones_globales comando opciones_comando
por ejemplo,
cvs -Q update -p
Acceso al repositorio
Antes de hacer nada, tenemos que decirle a CVS dónde se encuentra el repositorio al que deseamos acceder. Esto no será necesario si ya tenemos una copia de trabajo de ese repositorio, dado que cualquier copia de trabajo sabe de qué repositorio procede, con lo cual CVS puede deducir automáticamente el repositorio al que corresponde una copia de trabajo cualquiera. Sin embargo, si no disponemos todavía de una copia de trabajo habrá que decirle a CVS explícitamente dónde ir. Esto se hace con la opción global -d
(de directorio), seguido por la ruta que apunta al repositorio.
Por ejemplo, si el repositorio se encuentra en el sistema local en /usr/local/cvs,
cvs -d /usr/local/cvs comando
Si el repositorio está en un servidor y no en la máquina local, será necesario autenticarse.
En el caso de pserver primero habrá que autenticarse, de la forma:
cvs -d :pserver:USUARIO@SERVIDOR:DIRECTORIO login
por ejemplo,
cvs -d :pserver:pepe@cvs.pp.com:/usr/local/cvs login
Una vez que nos hemos autenticado podemos ejecutar cualquier comando de la forma
cvs -d :pserver:USUARIO@SERVIDOR:DIRECTORIO comando
Sólo es necesario autenticarse una vez ante un servidor CVS. Una vez que el proceso de autentificación tiene éxito, CVS guarda la contraseña en el directorio personal, en un fichero llamado .cvspass. CVS consultará este fichero cada vez que se conecte al repositorio a través del método pserver.
Autenticación
La autenticación contra el cvs cuando se trabaja en remoto se puede hacer de dos formas: vía pserver (password server) y vía ssh.
pserver
- exportar la variable
CVSROOT
export CVSROOT=":pserver:USUARIO@servidor:directorio"
- autenticarse contra el servidor
cvs login
ssh
exportar las variable CVSROOT
y CVS_RSH
export CVSROOT=":ext:USUARIO@servidor:directorio"
export CVS_RSH=/usr/bin/ssh
Modo de trabajo
Antes de cada sesión de trabajo es conveniente hacer una actualización (cvs update
) para asegurarnos de que trabajamos con las últimas versiones.
Al terminar la sesión de trabajo habría que hacer un commit (cvs ci
) para que todas nuestras modificaciones se propaguen al servidor.
Comenzar un nuevo proyecto
Operaciones básicas
Crear un módulo
-
Nos conectamos al CVS.
-
Hacemos un ‘checkout’ del cvs:
$ export CVSROOT=directorio_repositorio
$ cvs co CVSROOT
- Editamos CVSROOT/modules y añadimos una entrada para la
aplicación, de la forma:
aplicacion aplicacion
- Publicamos la modificación de modules.
$ cvs commit modules
Con esto se creará una jerarquía de directorios donde se almacenará el módulo.
No hay que modificar nunca los subdirectorios creados por el cvs.
Actualizar cambios
Para actualizar la copia local del módulo con los cambios que hayan podido hacer otros usuarios y que yan han sido enviados al repositorio deberemos hacer:
$ cd directorio-módulo
$ cvs update
cvs muestra información sobre lo que hace con cada fichero según la siguiente lista de códigos:
U
: Se ha bajado un fichero nuevo.
P
: Se ha bajado una modificación del fichero y ahora éste está
actualizado.A
: El fichero lo ha añadido usted pero no lo ha subido todavía al
repositorio.R
: El fichero ha sido borrado (pero podría recuperarse del histórico
que se almacena en el repositorio).C
: Hay un conflicto: otra persona ha modificado antes las mismas
partes del fichero y es necesario revisarlo manualmente antes de
poder subir los cambios de ese fichero.M
: Usted ha modificado el fichero pero aún no lo ha subido al
repositorio.?
: El fichero no está registrado. No hace nada con él.
Publicar modificaciones
Se usa la orden commit:
$ cd directorio-módulo
$ cvs ci
Entonces se abrirá un editor de textos en el que podremos describir el cambio.
Resolución de conflictos
Cuando varias personas modifican simultáneamente las mismas partes de un fichero surgen conflictos.
Para solventarlos editamos el fichero y en él encontraremos algo como
[...]
>>>>>>>>>>>>>>
modificación 1
===========
modificación 2
<<<<<<<<<<<<<<
[...]
donde el texto entre marcas es el que produce el conflicto. Nos quedamos con la modificación correcta y borramos lo demás (la otra modificación y las marcas).
Después se vuelve a hacer commit.
Añadir ficheros al módulo
Hay que recordar que cvs controla sólo los ficheros que se le hayan indicado expresamente. Cualquier otro fichero en el directorio cvs será ignorado.
Para añadir un nuevo fichero o directorio al módulo cvs se hace:
$ cd directorio-módulo
$ cvs add fichero
$ cvs ci
Si el fichero fuera binario se haría (1):
$ cd directorio-módulo
$ cvs add -kb fichero
$ cvs ci
Eliminar ficheros del módulo
Si ya hemos borrado el fichero hay que hacer:
$ cd directorio-módulo
$ cvs remove fichero
Para eliminar el fichero del módulo y, a un tiempo, borrarlo físicamente:
$ cd directorio-módulo
$ cvs remove -f fichero
Administración
Administración del repositorio
Iniciando un repositorio
Creación del repositorio
La orden para crear un nuevo repositorio es
cvs -d directorio_repositorio init
por ejemplo,
cvs -d /usr/local/apl init
Debajo del directorio que le hayamos indicado se habrá creado el subdirectorio CVSROOT, que contiene varios ficheros de administración que controlan el comportamiento de CVS (2).
Permisos del repositorio
CVS sólo necesita tener permisos de escritura en el repositorio. Sin embargo, tanto por seguridad como por simplificar la administración, es conveniente seguir los siguientes pasos:
- Añadir un grupo de Unix para el repositorio, como puede ser cvs. Cualquier usuario que necesite acceder al repositorio debería estar en el grupo.
- Hacer que el grupo creado anteriormente sea el grupo propietario del directorio (y de todos los subdirectorios y ficheros) donde está el repositorio.
- Dar al grupo permisos de escritura, lectura y ejecución en el directorio del repositorio y en el subdirectorio CVSROOT.
El servidor de autenticacion de contraseñas
Cuando un cliente remoto CVS usa el método pserver para conectarse a un repositorio, el cliente está contactando en realidad con un número de puerto específico en la máquina servidora (por defecto, el 2401).
Para permiter que se pueda acceder al repositorio sin conocer usuarios reales del sistema se utilizan las contraseñas especiales de CVS, distintas de las de sistema. El fichero de contraseñas de CVS es CVSROOT/passwd, cuyo formato es el siguiente:
<usuario-cvs>:<contraseña_cifrada>:<usuario-sistema>
Si se indica usuario-sistema
(que es opcional) las conexiones autenticadas con usuario-cvs
se ejecutarán con los permisos de usuario-sistema
. Si no se indica un usuario de sistema, el nombre de usuario-cvs
deberá coincidir con un usuario real del sistema.
El siguiente script en Perl que se puede utilizar para encriptar contraseñas:
#!/usr/bin/perl
srand (time());
my $randletter = "(int (rand (26)) + (int (rand (1) + .5) % 2 ? 65 : 97))";
my $salt = sprintf ("%c%c", eval $randletter, eval $randletter);
my $plaintext = shift;
my $crypttext = crypt ($plaintext, $salt);
print "${crypttext}\n";
Autenticación por proyectos
Aunque el fichero passwd autentifica para todo el repositorio, se puede conseguir proporcionar acceso específico de proyecto con el siguiente método.
Supongamos que queremos proporcionar acceso a algunos desarrolladores remotos al proyecto ‘aplica1’, y a otros acceso al proyecto ‘aplica2’, y no queremos que los desarrolladores de un proyecto tengan acceso al envío de cambios al otro. Para ello se pueden crear cuentas de usuario y grupo específico de proyecto en el sistema ("usuarios reales") y luego referirse a esas cuentas en el fichero CVSROOT/passwd ("usuarios lógicos").
En /etc/passwd tendríamos lo siguiente:
aplica1:*:600:600:Cuenta CVS para APLICA1:/usr/local/cvs:/bin/false
aplica2:*:601:601:Cuenta CVS para APLICA2:/usr/local/cvs:/bin/false
y en /etc/group:
aplica1:*:600:aplica1
aplica2:*:601:aplica2
Por último, en CVSROOT/passwd:
juan:rKa5jzULzmhOo:aplica1
jose:tGX1fS8sun6rY:aplica2
marta:cAXVPNZN6uFH2:aplica2
carmen:qp5lsf7nzRzfs:aplica1
Acceso anónimo
El acceso anónimo a CVS se logra mediante los ficheros CVSROOT/readers
y CVSROOT/writers
. El primero contiene la lista de usuarios que pueden leer el repositorio y el segundo la lista de los que pueden leer y escribir.
Si sólo existe el fichero CVSROOT/readers
, los usuarios listados tendrán acceso de sólo lectura a todos los proyectos del repositorio. Si existe el fichero CVSROOT/writers
los usuarios en éste fichero tendrán acceso de lectura y escritura a todos los proyectos del repositorio; los demás usuarios (estén en CVSROOT/readers
o no) tendrán acceso de sólo lectura al repositorio.
Los usuarios contenidos en estos ficheros son usuarios de CVS, no usuarios reales de sistema.
Referencias
Ismael Olea
. Micro-cómo empezar a trabajar con cvsKarl Fogel
. Desarrollo de Código Abierto con CVSThe Coriolis Group]
. Desarrollo de Código Abierto con CVSPer Cederqvist
Página info de cvs (Cederqvist).
1. Aunque el cvs puede gestionar ficheros binarios, no hace control de versiones. Sólo guarda la última versión
2. No hay que confundir la variable de entorno CVSROOT con este subdirectorio CVSROOT del repositorio. No tienen nada que ver, la primera es una forma de evitarles a los usuarios tener que teclear -d <situación-del-repositorio>
cada vez que usen CVS; el segundo es el directorio de administración de un repositorio.