Acerca de
Tutoriales
Comunidad
Actualidad
Enlaces





En macprogramadores.org
En Internet

Trucos

Control de versiones en Xcode con CVS



CVS (Concurrent Version System) es una herramienta de control de versiones diseñada para facilitar el que varios programadores puedan estar trabajando en un mismo proyecto al mismo tiempo. Xcode incorpora una interfaz gráfica para el programa cliente de CVS que facilita al programador el acceso al repositorio.

En este truco se explica cómo podemos usar la interfaz que proporciona Xcode para acceder a un repositorio CVS.


Introducción

Los sistemas de control de versiones usan el modelo cliente/servidor donde un servidor almacena los ficheros de uno o más proyectos, y varios clientes se conectan a él para bajar los ficheros (check out), modificarlos, y subir los cambios (check in).

Actualmente Xcode proporciona acceso a varias herramientas de gestión de versiones (Perforce, Subversions y CVS), en este truco sólo veremos como utilizar Xcode en CVS, que actualmente es la herramienta de control de versiones más utilizada en todo el mundo. Xcode no proporciona una interfaz para el servidor de CVS, sólo actúa como una interfaz gráfica de acceso a los comandos cliente de CVS.

En este truco supondremos que el lector sabe manejar la interfaz de comandos de CVS (en caso contrario le recomendamos leer primero el tutorial sobre Gestión de configuraciones software con RCS y CVS). Aun así a lo largo de este documento vamos a ir detallando los pasos para crear un repositorio CVS de ejemplo (usando la línea de comandos) con lo que un lector que no conozca (o que no recuerde) la interfaz de comandos de CVS debería poder seguir este tutorial.

Un repositorio de ejemplo

Para empezar necesitamos disponer de un repositorio donde aprender a manejar CVS desde Xcode. Aunque si el lector forma parte de una organización es posible que ya tenga uno configurado, en este truco vamos a crear un pequeño repositorio donde realizar nuestras pruebas.

Inicializar el repositorio

Un repositorio puede estar en la misma máquina o en otra máquina, en ambos casos la ubicación del servidor CVS se indica en la variable de entorno CVSROOT1. Para nuestros ejemplos bastará con disponer de un repositorio local.

Una vez tomada esta decisión vamos a proceder a crear un repositorio. En nuestro caso hemos decidido crear el repositorio directamente en el directorio home del usuario fernando, para lo cual ejecutamos desde el terminal los comandos:

$ cd
$ mkdir repositorio

Ahora debemos exportar la variable de entorno CVSROOT con la ubicación del repositorio:

$ export CVSROOT=/Users/fernando/repositorio/

E inicializamos el repositorio:

$ cvs init

En el directorio repositorio deberá de haberse creado el subdirectorio CVSROOT con metainformación sobre el recién creado repositorio:

$ ls repositorio
CVSROOT

Crear un proyecto de ejemplo

El siguiente paso es crearnos una carpeta para el proyecto que queremos exportar. Debido a que CVS es independiente del lenguaje de programación podríamos crear un proyecto en cualquier lenguaje, pero en este caso hemos elegido el lenguaje Java para nuestros ejemplos. En concreto vamos a crear un directorio en el home del usuario llamado Mate con un sólo fichero Aritmetica.java donde vamos a implementar varias operaciones aritméticas:

$ mkdir Mate
$ cd Mate

$ vi Aritmetica.java

El contenido de ejemplo de Aritmetica.java es el siguiente:

$ cat Aritmetica.java
public class Aritmetica
{
 public static double suma(int a, int b)
        {
         return a+b;
        }
}

Importar el proyecto

Una vez tenemos nuestro proyecto de ejemplo debemos de exportarlo al repositorio, para lo cual desde el directorio del proyecto ejecutamos los comandos:

$ cd Mate
$ cvs import Matematicas rama_principal version_inicial
N Matematicas/Aritmetica.java
No conflicts created by this import

El comando import importa todos los ficheros del directorio actual y sus subdirectorios al repositorio creando en el repositorio un proyecto con el nombre Matematicas .Observe que el nombre del proyecto en el repositorio no tiene porque coincidir con el nombre de la carpeta donde tenemos guardado el proyecto. Además al comando debemos pasarle dos tag, el primero rama_principal es el nombre de la rama dentro del proyecto, el segundo version_inicial es el nombre de un tag que ponemos a los ficheros exportados.

Crear un sandbox para el repositorio

Una vez tengamos exportado el proyecto hemos acabado nuestro trabajo como administrador, ahora pasamos a ejecutar el role de un programador que se baja el repositorio a su máquina para trabajar con él.

El lugar donde un programador se baja un proyecto del repositorio es una carpeta que se suele conocer como sandbox. Auque no es necesario que así sea, lo normal es que el nombre del directorio del sandbox coincida con el nombre que puso el comando import al proyecto del repositorio cuando lo creó.

Vamos a bajarnos el repositorio directamente al directorio home con los comandos:

$ cd
$ cvs checkout Matematicas
cvs checkout: Updating Matematicas
U Matematicas/Aritmetica.java

El comando checkout recibe como argumento el nombre del proyecto en el repositorio y lo baja a un directorio con el mismo nombre:

$ ls -l Matematicas
-rw-r--r-- 1 fernando admin 109 Apr 22 18:19 Aritmetica.java
drwxr-xr-x 5 fernando admin 170 Apr 22 18:34 CVS

En cada directorio del sandbox siempre existirá un subdirectorio con el nombre CVS donde se almacena metainformación sobre el sandbox.

Crear un proyecto Xcode que accede al sandbox

Ya tenemos en el sandbox el proyecto, ahora debemos de crear un proyecto con Xcode que debe crearse sobre la carpeta del sandbox. Esto es así porque el subdirectorio CVS es el que le sirve a Xcode para poder conectarse al sandbox. Actualmente Xcode no es capaz de crear un sandbox haciendo algo equivalente a lo que el comando checkout ha hecho.

Para proceder a crear el proyecto desde Xcode, use la opción de menú File|New Project...|Java Tool, y cree un proyecto llamado igual que el sandbox para que se cree en la misma carpeta (véase Figura 1).


Figura 1: Crear un proyecto en el sandbox


Configurar el acceso al repositorio

Una vez tengamos creado el proyecto Xcode en el sandbox, lo siguiente que debemos hacer, antes de poder acceder a las opciones de repositorio desde Xcode, es configurar el SCM (Source Code Managenment). Para acceder a las opciones de SCM desde Xcode tiene una persiana de menú llamada SCM.

Antes de estar configurado el SCM la única opción de menú que tenemos es SCM|Configure SCM... Usando esta opción debemos de activar la opción Enable SCM e indicar el tipo de sistema de SCM en el campo SCM System. La Figura 2 muestra estas opciones.

También muchas veces resulta útil apartar los ficheros intermedios y los ficheros finales del sandbox, en este caso puede usar las opciones Place Build Product In y Place Intermediate Build Files para indicar otra ruta donde depositar estos ficheros.


Figura 2: Activar SCM en un proyecto

 

Activar o desactivar el acceso al repositorio

Si está trabajando en un lugar donde no tiene red quizá le convenga desactivar temporalmente el SCM usando la opción de menú SCM|Go Offline. Cuando vuelva a tener acceso al repositorio puede volver a activar el SCM con SCM|Go Online.

Trabajar con el repositorio

Ver el estado del repositorio

El smart group SCM (véase Figura 3) nos muestra el estado de los ficheros usando una sola letra para indicar su estado de acuerdo a la nomenclatura común de CVS (blanco actualizado ? desconocido, A listo para añadir, U hay una versión más moderna en el repositorio, M ha sido modificado en local y puede subirse al repositorio, C conflicto debido a que ha sido modificado en local y por alguien más en el repositorio, R Listo para ser borrado del repositorio). De momento todos los ficheros aparecen marcados con ? porque ninguno de ellos forma parte del repositorio (el subdirectorio CVS le sirve a Xcode para conocer esto).


Figura 3: Estado de los ficheros del repositorio


Como muestra la Figura 4, también podemos ver la información de SCM de un fichero en las columnas de detalle del fichero, pero la columna que da esta información no aparece visible por defecto y debemos usar la opción de menú View|Detail View Columns|SCM para que aparezca.


Figura 4: Vista de detalle de un fichero con la columna SCM activada

Nota: Puede que Xcode no le actualice correctamente la vista del estado de los ficheros, en ese caso puede usar la opción de menú SCM|Refresh Entire Project.

Añadir ficheros al repositorio

En este momento el repositorio está activo, pero el único fichero que ha generado el proyecto de Xcode (el fichero Matematicas.java) no está en el repositorio, para añadirlo podemos seleccionar el fichero y usar la opción de menú SCM|Add to Repository. En este momento el fichero aparecerá marcado con una A, que significa que el fichero está listo para ser añadido al repositorio la próxima vez que hagamos un commit.

A continuación puede seleccionar el fichero y usar la opción de menú SCM|Commit Changes... para subir el fichero al repositorio. Se le pedirá que introduzca un comentario de commit que describa los cambios. Este comentario se almacena junto a la versión inicial del fichero. Más abajo veremos como consultar estos comentarios.

Una vez añadido el fichero al repositorio el campo de detalle de SCM aparecerá banco indicando que el fichero está actualizado y el fichero habrá desaparecido del SCM smart group. Si se pregunta por qué Apple ha implementado el extraño comportamiento de que los ficheros actualizados desaparecen del smart group SCM, la razón procede de que el comando cvs -n update no devuelve información sobre los ficheros actualizados, es decir en nuestro ejemplo el comando devuelve1:

$ cvs -n update
? Manifest
? Matematicas.1
? Matematicas.xcodeproj

Recuerde que en el repositorio inicial que creamos al principio de este documento creamos un fichero llamado Aritmetica.java que actualmente no forma parte del proyecto. Para que pase a formar parte del proyecto podemos usar la opción de menú Project|Add to project... El fichero debería aparecer marcado como actualizado ya que estaba correctamente subido al repositorio.

Bajar ficheros del repositorio

Cuando un fichero de nuestro proyecto aparece marcado con U significa que otro programador ha modificado el fichero y en este caso necesitamos actualizar los cambios en nuestro sandbox. Podemos actualizar el fichero de dos formas:

  • Seleccionando el fichero y usando la opción SCM|Update To|Latest...
  • Usando la opción SCM|Update Entire Project que actualiza todos los ficheros del proyecto existentes en el CVS.

Consultar las operaciones realizadas por Xcode sobre CVS

Podemos usar la opción de menú SCM|SCM Results para ver las operaciones a nivel de interfaz de comandos que Xcode ha realizado sobre el CVS (véase Figura 5). Para obtener una vista detallada de los comandos ejecutados puede necesitar tener que usar el botón que aparece abajo a la derecha. Observe que el comando que Xcode ejecuta no es cvs sino ocvs. El comando ocvs se creó cuando CVS no soportaba wrappers, los cuales permitían tratar una carpeta marcada con el atributo de paquete como un sólo fichero. Actualmente CVS soporta esta opción con lo que ocvs y cvs son equivalentes.


Figura 5: Vista de SCM Results


Ver las revisiones

Puede consultar las revisiones de un fichero colocado el en repositorio seleccionándole y usando la combinación de teclas Command+I, o bien con la opción de menú SCM|SCM Info (véase Figura 7). En el panel de SCM aparecerá para cada revisión información sobre el número de revisión, autor, fecha y mensaje de commit. Si selecciona una determinada revisión debajo obtendrá una información más detallada.

Subir los cambios

Vamos a ver cómo se suben cambios a un fichero del proyecto. Para ello, tal como aparece en la Figura 6, vamos a eliminar los comentarios del fichero Matematicas.java que por defecto introdujo Xcode cuando creó el proyecto.

Luego podemos subir los cambios al repositorio con la opción de menú SCM|Commit Changes...


Figura 6: Fichero Matematicas.java modificado

Si ahora volvemos a ver las revisiones del fichero Matematicas.java (con Command+I) en la Figura 7 podemos ver el resultado, donde apreciamos que existen dos revisiones.


Figura 7: Revisiones de un fichero

Comparar revisiones

Xcode nos permite ver las diferencias entre dos revisiones de un fichero, para ello podemos usar dos herramientas: O bien la opción SCM|Compare With..., o bien la opción SCM|Diff With... Ambas opciones de comparación se pueden ejecutar también desde el panel de propiedades de la Figura 7. En ambos casos la forma de comparar es la misma, seleccionamos un fichero y pedimos comparar la versión actual del sandbox con otra revisión.

La opción de comparar es la más visual (véase Figura 8). Por defecto se ejecuta una herramienta visual que viene con Xcode llamada FileMerge, aunque modificar la herramienta de comparación a usar en las preferencias de Xcode, por ejemplo para usar BBedit.


Figura 8: Comparación de revisiones con FileMerge

La otra forma de comparar es obteniendo el resultado del comando cvs diff1, tal como muestra la Figura 9.


Figura 9: Comparación de revisiones con Diff


Borrar ficheros del repositorio

Si pedimos borrar un fichero del proyecto (usando la opción Edit|Delete) aparecerá un diálogo como el de la Figura 10 (a), entonces tenemos dos opciones:

  • Delete References nos permite borrar sólo la referencia que hace el proyecto al fichero, pero no borra el fichero del disco.
  • Delete References & Files borraría tanto la referencia que hace el proyecto al fichero como el propio fichero.

En este segundo caso, si el fichero está bajo control de un SCM aparecerá un segundo diálogo como el de la Figura 10 (b) donde se nos preguntará si queremos borrar también el fichero del repositorio.

Si pedimos borrar el fichero del repositorio el fichero quedará marcado con una R y sombreado en gris, como muestra la Figura 10 (c), de forma que para borrarlo definitivamente del repositorio deberemos hacer un commit (con la opción SCM|Commit Changes...), o bien podremos cancelar el borrado y recuperar el fichero con la opción SCM|Add to repository.


(a)


(b)


(c)

Figura 10: Borrar ficheros del repositorio

Renombrar ficheros

Cuando renombramos un fichero bajo control de CVS, el fichero original es marcado con R indicando que será borrado del repositorio y el fichero nuevo será marcado con A indicando que el fichero será añadido al repositorio. Además renombrar un fichero inevitablemente hace que se pierda la información de log del fichero antiguo.

Para renombrar un fichero del proyecto puede usar la opción de menú File|Rename, en cuyo caso un mensaje de advertencia como el de la Figura 11 (a) le indicará que el fichero está bajo control de un SCM y que si renombra el fichero inevitablemente la información histórica de revisiones del fichero se perderá. Si aceptamos, y por ejemplo cambiamos el nombre de Aritmetica.java por Algebra.java, obtendremos el fichero antiguo marcado con R y el nuevo marcado con A, tal como muestra la Figura 11 (b), después podemos usar la opción de menú SCM|Commit changes... para que los cambios se ejecuten definitivamente en el repositorio.


(a)


(b)

Figura 11: Renombrar un fichero bajo control de CVS


Subir el proyecto al repositorio

No sólo es posible subir los ficheros de código fuente a un repositorio, sino que otros ficheros como los de documentación también es muy común tenerlos en el repositorio.

Si usted trabaja en un proyecto donde algunos programadores usan Xcode y otros usan otra herramienta quizá no convenga que coloque el proyecto en el repositorio, pero si todos los programadores trabajan con Xcode sí que puede resultar útil compartir el proyecto, de esta forma cuando un programador añade un fichero al proyecto o cambia una opción de éste, todos los programadores se beneficiarán automáticamente del cambio. Debido a que los proyectos de Xcode (ficheros del bundle .xcodeproj) están escritos en texto plano, CVS gestiona bien los cambios cuando más de un programador cambia el proyecto a la vez. En este último apartado vamos a ver cómo se comparten los ficheros de proyecto en el repositorio.

El paquete de proyecto

Xcode guarda metainformación sobre el proyecto en un directorio con el atributo de paquete con la extensión .xcodeproj2. Por ejemplo, en nuestro ejemplo el proyecto Matematicas.xcodeproj tiene los ficheros que muestra la Figura 123.


Figura 12: Ficheros de un paquete de proyecto

Este paquete contiene dos ficheros a los que debemos prestar especial atención si queremos colocar un proyecto en el repositorio4: El fichero de proyecto y el fichero de usuario.

  • El fichero de proyecto (que tiene el nombre project.pbxproj) almacena información referente al proyecto como los ficheros que le componen, los targets, y opciones de compilación. Este fichero puede ser compartido por todos los programadores, y normalmente sí que se deberá poner en el repositorio si queremos compartir el proyecto.
  • El fichero de usuario (que tiene el nombre fernando.pbxuser) almacena información de personalización del usuario, como por ejemplo sus bookmarks, su target activo, o sus preferencias de edición. Cuando creamos un proyecto Xcode crea un fichero como éste con el nombre de la cuenta del usuario. Este fichero no debe ser compartido por los programadores, aunque opcionalmente se puede colocar en el repositorio si queremos poder trabajar con el mismo proyecto desde varias máquinas. Al existir uno por cada nombre de usuario no deberían de producirse conflictos.

Referencias

"Xcode User Guide". Apple Inc.


1 Puede consultar el tutorial sobre Gestión de versiones con CVS y Subversion para ver cómo se hace esto.

2 En versiones anteriores estos ficheros tuvieron las extensiones .xcode, .pbproj, .pbxproj.

3 Puede abrir un directorio con el atributo de paquete desde Finder pulsando con el botón derecho y eligiendo la opción Show Package Contents.

4 Todos estos ficheros pueden ser editados con la herramienta Property List Editor.