Instalación

La distribución de Subversion incluye un cliente remoto (svn), un servidor (svnserve), y varias utilidades. En este documento se ilustra el uso de Apache como servidor porque permite más posibilidades que svnserve. La única ventaja de svnserve es que se configura más fácilmente que Apache. Por ejemplo, asegurar la comunicación en Apache requiere certificados SSL, mientras que con svnserve basta usar SSH.

Instalar Subversion

Puedes encontrar paquetes para Windows, Debian, RedHat, SuSE, Mandrake, pkgsrc ({Net,Open,Free}BSD, Linux, Solaris, etc.), Solaris, y OSX, a través de la página http://subversion.tigris.org/project_packages.html.

Aquí se describe la instalación en Debian y Windows. Tras este paso podremos usar Subversion desde consola. Más adelante activaremos el acceso HTTP que nos permitirá compartir el repositorio con otros desarrolladores, y acceder con programas que usan este protocolo (Eclipse, TortoiseSVN, etc.).

Debian

Existe un paquete subversion versión 1.0.5-1 unstable y 1.0.0-1 testing. La última versión liberada del proyecto a 27 de julio es 1.1.0-rc1. Hay una versión 1.0.5-0 portada a woody aquí.

Aviso

Las versiones hasta la 1.0.5 (incluida) presentan una vulnerabilidad en el módulo mod_authz_svn. En la versión 1.0.5-1 ya esta solucionado.

Aviso

La instalación unstable y testing requiere libc6.1 (2.3.2.ds1-11), una biblioteca usada por multitud de programas del sistema. Dependiendo de lo actualizado que este tu sistema, podría requerir una actualización masiva.

En cualquier caso, la instalación es la misma:

debian:/mnt# wajig install subversion

Reading Package Lists... Done
Building Dependency Tree... Done
The following extra packages will be installed:
  db4.2-util libapr0 libneon24 libsvn0 libswig1.3.21
Suggested packages:
  subversion-tools
The following NEW packages will be installed:
  db4.2-util libapr0 libneon24 libsvn0 libswig1.3.21 subversion
0 upgraded, 6 newly installed, 0 to remove and 233 not upgraded.
Need to get 1304kB of archives.
After unpacking 3711kB of additional disk space will be used.
Do you want to continue? [Y/n]
Get:1 http://ftp.us.debian.org unstable/main db4.2-util 4.2.52-16 [60,6kB]
Get:2 http://ftp.us.debian.org unstable/main libapr0 2.0.50-5 [124kB]
Get:3 http://ftp.us.debian.org unstable/main libneon24 0.24.6.dfsg-1 [80,4kB]
Get:4 http://ftp.us.debian.org unstable/main libswig1.3.21 1.3.21-5 [160kB]

Nota

wajig es un frontend simplificado para varios comandos apt-* y dpkg. Prueba apt-get install wajig y wajig help. O si no quieres complicarte, usa el apt-get install de toda la vida.

Opcionalmente podemos instalar subversion-tools, unos scripts que facilitan la administración del repositorio:

debian:/# wajig install subversion-tools

Reading Package Lists... Done
Building Dependency Tree... Done
The following extra packages will be installed:
  libconfig-inifiles-perl python2.3-subversion rcs
The following NEW packages will be installed:
  libconfig-inifiles-perl python2.3-subversion rcs subversion-tools
0 upgraded, 4 newly installed, 0 to remove and 233 not upgraded.
Need to get 1095kB of archives.
After unpacking 3346kB of additional disk space will be used.

Windows

De la página de descarga, hay dos versiones:

  • "Windows installer with the basic Subversion Win32 binaries". Versión autoinstalable.

  • svn-win32-x.x.x.zip. Versión en zip, probablemente más reciente. Para instalarla es necesario descomprimir, añadir el directorio bin al PATH, y establecer esta variable de entorno: APR_ICONV_PATH=D:\programas\Subversion\iconv.

Aviso

Como regla general, evita los directorios con espacios cuando uses versiones Windows de herramientas Unix. Casi siempre deberían funcionar sin problemas, yo lo he hecho por probar y funciona, pero no es recomendable.

Aviso

Si usas Windows XP necesitas el Service Pack 1.

Tras instalar deberíamos poder abrir una consola tras la instalación y operar con Subversion en local:

D:\>svn
Type 'svn help' for usage.

Crear un repositorio

El repositorio es el árbol de directorios donde Subversion almacena nuestros ficheros y cambios.

Para crear un repositorio vacío usamos la herramienta de administración svnadmin:

  • Debian:

    mkdir -p /var/local/repos
    svnadmin create /var/local/repos
    
    # doy permisos al servidor web
    chown -R www-data:www-data /var/local/repos

  • Windows:

    # en Windows quiero crearlo en d:\repositorio, así que me pongo en d:\ y ejecuto:
    svnadmin create repositorio

Si no hay problemas tampoco veremos aparecer mensajes por consola. Esto puede sorprender a usuarios Windows, pero en Unix, muchos comandos se comportan así.

El repositorio tiene este aspecto en el sistema de ficheros de Debian:

debian:/# ls -la /var/local/repos
total 36
drwxr-sr-x    7 www-data www-data     4096 2004-07-27 20:00 .
drwxrwsr-x    3 root     staff        4096 2004-07-27 20:00 ..
drwxr-sr-t    2 www-data www-data     4096 2004-07-27 20:00 conf
drwxr-sr-t    2 www-data www-data     4096 2004-07-27 20:00 dav
drwxr-sr-t    2 www-data www-data     4096 2004-07-27 20:00 db
-r--r--r--    1 www-data www-data        2 2004-07-27 20:00 format
drwxr-sr-t    2 www-data www-data     4096 2004-07-27 20:00 hooks
drwxr-sr-t    2 www-data www-data     4096 2004-07-27 20:00 locks
-rw-r--r--    1 www-data www-data      376 2004-07-27 20:00 README.txt

Lo que vemos son ficheros y directorios de una instancia de la base de datos Berkeley. Esta es una novedad frente al CVS: los proyectos no se guardan en el sistema de ficheros, sino en una base de datos. Esto asegura que cualquier transacción que realicemos

  • es atómica,

  • sus resultados consistentes,

  • aislados (independientes de otras transacciones),

  • y duraderos (su efecto es permanente).

O dicho de otro modo, cualquier operación con Subversion posee las propiedades ACID (Atomic, Consistent, Isolated, Durable) propias de toda base de datos.

Nota

La información esta más segura en una Base de Datos que en un sistema de ficheros. Pero si llegados a este punto te asusta no ver físicamente tus ficheros, espero que eso refuerce en ti la sana costumbre de hacer backups. :-)

NUNCA será necesario operar manualmente sobre el contenido del repositorio. En su lugar debemos usar las herramientas que proporciona Subversion. Por tanto, no realizaremos más visitas a este directorio.

Acceso remoto con Apache

Apache es un servidor web que podemos configurar para acceder al repositorio usando el protocolo HTTP. El acceso remoto con Apache ofrece mayor flexibilidad que svnserve, porque podemos usar todos los módulos y scripts para Apache, como por ejemplo ViewCVS (que sí, también funciona con Subversion).

Instalar Apache

Debian

En Debian Apache viene en sabores moderno, tradicional, y suicida:

  • apache2-mpm-worker: High speed threaded model for Apache2.

    The worker MPM provides a threaded implementation for Apache2. It is considerably faster than the traditional model, and is the recommended MPM. Worker generally is a good choice for high-traffic servers because it has a smaller memory footprint than the prefork MPM.

  • apache2-mpm-prefork: Traditional model for Apache2.

    This Multi-Processing Module (MPM) implements a non-threaded, pre-forking web server that handles requests in a manner similar to Apache 1.3. It is appropriate for sites that need to avoid threading for compatibility with non-thread-safe libraries. It is also the best MPM for isolating each request, so that a problem with a single request will not affect any other. It is not as fast, but is considered to be more stable.

  • apache2-mpm-perchild: Experimental High speed perchild threaded model for Apache2.

    Perchild is the grown up, mac daddy version of suexec for apache2. Rather than execute a cgi script as a given user, perchild forks a process for each vhost, then su's to the correct user/group for that vhost. Each process then uses a thread model similar to that of the worker mpm. THIS MPM IS NOT CURRENTLY EXPECTED TO WORK CORRECTLY, IF AT ALL. IT IS UNDER VERY HEAVY DEVELOPMENT. This mpm is still highly experimental, and should be used with care.

Yo he escogido la opción moderna:

debian:/# wajig install apache2-mpm-prefork

Reading Package Lists... Done
Building Dependency Tree... Done
The following extra packages will be installed:
  apache2-common
Suggested packages:
  apache2-doc
The following NEW packages will be installed:
  apache2-common apache2-mpm-prefork
0 upgraded, 2 newly installed, 0 to remove and 233 not upgraded.
Need to get 1062kB of archives.
After unpacking 3830kB of additional disk space will be used.
Do you want to continue? [Y/n]

Para que apache transforme las operaciones HTTP de los clientes de Subversion, en operaciones sobre el repositorio, es necesario instalar el módulo libapache2-svn:

debian:/# wajig install libapache2-svn

Reading Package Lists... Done
Building Dependency Tree... Done
The following NEW packages will be installed:
  libapache2-svn
0 upgraded, 1 newly installed, 0 to remove and 233 not upgraded.
Need to get 57.0kB of archives.
After unpacking 229kB of additional disk space will be used.

Windows

Para acceder al repositorio usando un cliente HTTP (por ejemplo el plugin subclipse de Eclipse), necesitaremos instalar Apache2.0.48 (no valen el 1.x ni el 2.0.46). La instalación es trivial, descarga y ejecuta apache_2.0.48-win32-x86-no_ssl.msi. Siempre se instala en un directorio Apache2, por tanto, si lo quieres en d:\httpd\Apache2, indica c:\httpd como directorio de instalación. Por defecto se añadirá como servicio y al iniciar Windows veremos aparecer un monitor de Apache la bandeja, al lado del reloj.

Configurar Apache

Aquí se explica como configurar el módulo para que opere con nuestro repositorio, y como restringir el acceso usando autentificación básica.

Apache permite otras posibilidades que aquí no se mencionan, como por ejemplo, comprobar los passwords contra base de datos, crear grupos de usuarios, permitir el acceso de los usuarios solo a ciertas ramas del repositorio, autentificar por IP, y otras. Para más información sobre restricciones de acceso podemos consultar el apartado seguridad en algún tutorial acerca de Apache.

Debian

Para configurar el módulo mod_dav_svn, edita /etc/apache2/mods-available/dav_svn.conf. Comenta estas líneas:

#<Location /svn>
#</Location>
y añade estas otras:
<Location /repos>
    DAV svn
    SVNPath /var/local/repos
</Location>

La directiva Location de Apache asocia el bloque que contiene a una URL determinada. Aqui por ejemplo, la configuración del módulo dav_svn queda asociado a la dirección http://localhost/repos. Perfectamente podríamos haber usado Location /cualquier/otra/ruta, y dejar el repositorio accesible en http://localhost/cualquier/otra/ruta.

Si acabas de instalar Apache, probablemente ya este en ejecución (prueba ps -A | grep apache2). Reinícialo para que lea los cambios:

debian:/# /etc/init.d/apache2 restart
Restarting web server: Apache2.

Vamos a http://127.0.0.1/repos, y vemos el repositorio:

Revision 0: /

Powered by Subversion version 1.0.5 (r9954).

Windows

Primero copiamos el fichero mod_dav_svn.so de la instalación de Subversion (C:\Program Files\Subversion\httpd\mod_dav_svn.so) al directorio modules de la instalación de apache (C:\Program Files\Apache2\modules\).

En el fichero httpd.conf de la instalación de Apache busca la siguiente línea:

#LoadModule dav_module modules/mod_dav.so
y cambiala por esto:
LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so

Suponiendo que nuestro repositorio este en d:\repositorio ponemos esto al final de httpd.conf:

<Location /repos>
  DAV svn
  SVNPath d:/repositorio
</Location>
# observa que hemos usado d:/ y no d:\

La directiva Location de Apache asocia el bloque que contiene a una URL determinada. Aqui por ejemplo, la configuración del módulo dav_svn queda asociado a la dirección http://localhost/repos. Perfectamente podríamos haber usado Location /cualquier/otra/ruta, y dejar el repositorio accesible en http://localhost/cualquier/otra/ruta.

Reiniciamos apache usando el monitor. Si el monitor indica que la operación ha fallado, conviene abrir una consola en el directorio bin de la instalación de Apache (en mi ordenador es C:\Program Files\Apache\bin) y ejecutar lo siguiente:

D:\programas\Apache2\bin>apache -e debug
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module access_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module actions_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module alias_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module asis_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module auth_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module autoindex_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module cgi_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module dav_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module dav_svn_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module dir_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module env_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module imap_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module include_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module isapi_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module log_config_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module mime_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module negotiation_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module setenvif_module
[Wed Mar 03 22:22:54 2004] [debug] mod_so.c(290): loaded module userdir_module
Vemos que entre otros ha cargado el módulo dav_svn_module. En este punto la consola se queda bloqueada, Apache espera peticiones. Ya deberías poder acceder por red, comprueba la dirección http://127.0.0.1/repos/. Deberías ver algo como

Figura 1. Repositorio vacío

Repositorio vacío

Pulsamos Ctrl+C para cerrar la consola, y arrancamos Apache desde el monitor, o desde la consola de servicios de Microsoft. Desgraciadamente, a mí me falló en ambos casos el servicio, y cuando consulte el visor de eventos del sistema encontré este mensaje:

The Apache service named  reported the following error:
>>> Cannot load C:/Program Files/Apache/modules/mod_dav_svn.so into server: 
The specified module could not be found.  
Gracias a mis dotes adivinatorias y a que examiné mod_dav_svn.so con DependencyWalker, descubrí que el módulo DAV_SVN no encontraba los ficheros libapr.dll, libaprutil.dll, y libhttpd.dll, que son las bibliotecas de la APR (Apache Portable Runtime Library). Para arreglarlo las copié de C:\Program Files\Apache\bin al directorio modules.

Por desgracia seguía sin funcionar, y DependencyWalker no daba más pistas. En la lista de correo leí que debía copiar los ficheros libdb42.dll, libeay32.dll, ssleay32.dll, del bin/ de la instalación de Subversion al directorio modules de Apache.

Como aun así seguía sin funcionar copie todas las .dll de subversion/bin al modules/ de Apache, en algún caso, sobreescribiendo la versión de Apache que había copiado antes. No es un método muy científico pero funcionó. Supongo que el módulo de Subversion prefería las librerías de Apache contra las que había sido compilado.

Por cierto, no encontré referencias a este problema en el manual de Subversion.

Restringir el acceso

Aquí se explica como configurar Apache para restringir el acceso usando autentificación básica (basic authentication) o SSL.

La autentificación básica no es segura porque envía los passwords a través de la red codificados en base64 (un algoritmo que proporciona muy poca protección). Estos passwords pueden capturarse con un sniffer y desencriptarse con paciencia. Por tanto:

  • Si el servidor esta expuesto a Internet, convendrá usar SSL para operaciones de escritura y asegurar Apache contra ataques.

  • Si lo vamos a usar en un entorno seguro (una intranet) y solo nos interesa identificar a los usuarios que realizan cada cambio en el repositorio, basta la autentificación básica.

Debian

Volvemos a editar la configuración del módulo (/etc/apache2/mods-available/dav_svn.conf):

<Location /repos>
    DAV svn
    SVNPath /var/local/repos
    AuthType Basic
    AuthName "Subversion repository"
    # fichero de passwords
    AuthUserFile /etc/subversion/passwd
    # permito las opciones GET PROPFIND OPTIONS REPORT a usuarios anonimos
    <LimitExcept GET PROPFIND OPTIONS REPORT>
        # pero requiero autentificación para el resto de operaciones (las de escritura)
        Require valid-user
    </LimitExcept>
</Location>

Luego crea un usuario, por ejemplo 'jano':

debian:/# htpasswd2 -c /etc/subversion/passwd jano
New password:
Re-type new password:
Adding password for user jano

Y reinicia:

debian:/# /etc/init.d/apache2 restart
Restarting web server: Apache2.

Windows con Autentificación básica

El procedimiento es casi el mismo que veíamos con Debian. Creamos el fichero de passwords:

D:\programas\Apache2\bin>htpasswd.exe -nb jano secreto > usuarios.txt
Automatically using MD5 format.

Añadimos la configuración necesaria a httpd.conf:

<Location /repos>
  DAV svn
  SVNPath d:/repositorio
  
  # Autentificación básica.
  AuthType Basic
  AuthName "Repositorio Subversion"
  AuthUserFile D:/programas/Apache2/bin/usuarios.txt  

  # Solo permitimos usuarios identificados en el fichero de passwords.
  #require valid-user
  
  # Solo permitimos usuarios identificados en el fichero de passwords 
  # con nombre 'jano' o 'alicia'.
  #require user jano alicia

  # La lectura es libre pero solo permitimos usuarios identificados 
  # en el fichero de passwords para otras operaciones.
  <LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
  </LimitExcept>

</Location>

Y reiniciamos:

net restart apache

Acceso remoto con svnserve

svnserve es un servidor incluido en Subversion cuya función es acceder al repositorio usando un protocolo TCP/IP propio. Las URLs son similares a las que usamos en Apache, pero comienzan por svn:// o svn+ssh://. svnserve consume menos recursos que Apache, pero es menos potente.

Instalar svnserve

Si ya has instalado Subversion, ya tienes el programa svnserve. El propio comando nos muestra las opciones de arranque:

$ svnserve --help
Usage: svnserve [options]

Valid options:
  -d [--daemon]            : daemon mode
  --listen-port arg        : listen port (for daemon mode)
  --listen-host arg        : listen hostname or IP address (for daemon mode)
  --foreground             : run in foreground (useful for debugging)
  -h [--help]              : display this help
  -i [--inetd]             : inetd mode
  -r [--root] arg          : root of directory to serve
  -R [--read-only]         : deprecated; use repository config file
  -t [--tunnel]            : tunnel mode
  -X [--listen-once]       : listen once (useful for debugging)

Windows

No es aconsejable usar svnserve en Windows porque necesita fork para gestionar el acceso concurrente, pero Windows no lo implementa. Desconozco que problemas pueden darse. En Windows podemos usar este wrapper para instalarlo como servicio.

Si tenemos CygWin instalado, instalamos xinetd en la sección Net y hacemos

/usr/sbin/inetd --install-as-service
net start inetd
También podemos arrancar inetd desde consola manualmente en depuración con
/usr/sbin/inetd -d

Para SSH también necesitaremos OpenSSH y OpenSSL. Instalalos y comprueba que que estan ahi:

$ ssh -version
OpenSSH_3.8p1, SSH protocols 1.5/2.0, OpenSSL 0.9.7d 17 Mar 2004
Bad escape character 'rsion'.

Consulta tus dudas en la lista de correo de Subversion. Por ejemplo en http://www.contactor.se/~dast/svnusers/.

Linux

Por defecto, el servidor escucha en el puerto 3690 reservado por la IANA para el protocolo svn.

En modo independiente la consola queda bloqueada:

$ svnservce -d

Para lanzarlo con inetd:

$ svnserve -i
( success ( 1 2 ( ANONYMOUS ) ( edit-pipeline ) ) )
y añadimos esto a /etc/inetd.conf:
svn stream tcp nowait svnowner /path/to/subversion/bin/svnserve -i

Importar un proyecto

Ya tenemos el repositorio funcionando en red. Para iniciar un proyecto simplemente creamos un subdirectorio donde iremos añadiendo ficheros. Durante el resto del documento usare un miniproyecto casero llamado "awpool".

# Creo un proyecto llamado "awpool" en el repositorio
svn mkdir http://127.0.0.1:80/repos/awpool -m "Creo el proyecto"

Si ya tienes un proyecto y quieres importarlo necesitareis una copia libre de directorios CVS/ (si es que usábamos CVS). Lo más sencillo es eliminar los directorios e importar en el CVS.

Si vais a conservar el repositorio CVS convendrá etiquetar la versión a partir de la cual has migrado a Subversion. Por ejemplo, vamos a etiquetarlo como "release1":

# Suponiendo que aun no tengo en mi disco el CVS, lo hago ahora
mkdir /home/jano/tmp
cd /home/jano/tmp
cvs co awpool

# y lo etiqueto como 'release1'
cvs tag release1
En mi caso no quería perder mi copia local del CVS, así que me baje esa release exacta exportando. En CVS exportar significa bajarte el código sin control de versiones, o sea, sin los directorios CVS/:
mkdir /home/jano/release1
cvs export -r release1 awpool

De un modo u otro, deberíamos acabar con el código listo para ser importado.

# Creo un directorio para la versión principal del proyecto.
# A veces se hacen versiones (branches) de un proyecto, y lo principal se pone 
# en un directorio que por convención se llama trunk.
svn mkdir http://127.0.0.1:80/repos/awpool/trunk -m "version principal"

# importo el código que copie (o exporte) antes en /home/jano/release1, 
# o sea, el directorio con el código a importar, y lo meto en trunk 
cd /home/jano/release1
svn import . http://127.0.0.1:80/repos/awpool/trunk -m "importacion inicial"

# en Windows me coloque dentro del directorio con el proyecto a importar y teclee
# svn import . http://127.0.0.1:80/repos/awpool/trunk -m "importacion inicial"

La operación anterior tarda un rato, veremos desfilar todos los ficheros que están importándose. Si olvidaste eliminar la versión compilada de tú programa (ooops!!) también se añadirá y tendrás que borrarla luego. Cuando termina, puedes conectarte por web para ver el resultado, o hacer checkout (descargarlo) desde otro directorio:

mkdir /home/jano/awpool
cd  /home/jano/awpool
svn checkout http://127.0.0.1:80/repos/awpool/trunk .

La copia local generada tiene un subdirectorio .svn junto a cada directorio. Es el equivalente a los antiguos CVS/, pero su contenido tiene un formato distinto.

Guardar la versión principal en un subdirectorio trunk no es obligatorio, pero ese y otros, son los elementos acostumbrados en un repositorio:

  • trunk/ Por convención suele usarse para el código principal del proyecto. Cuando la gente dice "get the head of the trunk", se refieren a que te bajes la última versión de este directorio.

  • branches/ Ramas del desarrollo. Copias del código principal con cambios experimentales.

  • tags/ Versiones del código listas para empaquetar como entregables.