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. |