Introducción a Subversion

Gestión de proyectos con Subversion

Introducción

Subversion es un sistema de control de versiones, es decir, sirve para
tener un control sobre nuestro proyecto y permitirnos realizar cambios a
los distintos componentes del mismo manteniendo un histórico de estos
cambios y permitiéndonos en cualquier momento deshacer los cambios
hechos en un momento dado, actualizar el proyecto a la última versión de
los programadores, ver históricos de cambios y comentarios, y unir
nuestros cambios con los que otros hayan podido hacer sobre los mismos
ficheros.

De hecho uno de los motivos por los que estos sistemas se
utilicen tanto en el mundo del software libre se debe a que permite, de
forma cómoda, coordinar el trabajo de varios profesionales a través©s de
Internet cómodamente.

Sin duda el sistema de control de versiones (SCV de aquí en adelante)
más utilizado actualmente por los programadores de software libre es el
viejo y probado CVS. Este sistema tiene ya bastantes años detrás y
aunque sirve bastante bien para sus propósitos tiene una serie de
limitaciones que han hecho que poco a poco otros SCV están ocupando su
(todavía predominante) cuota de mercado.

Entre estos nuevos sistemas podemos destacar tres: Arch, BitKeeper y
Subversion. De los tres, en mi opinión, uno de los más interesantes
para los que conozcan y hayan utilizado CVS con anterioridad es
Subversion porque es el que más se le parece dado que sus programadores
lo que han intentado es hacer una evolución natural de CVS superando sus
limitaciones y mejorándolo allá­ donde estaba claro que se podía mejorar.
Arch sigue una filosofía bastante distinta de CVS y BitKeeper, aún
siendo probablemente el más avanzado de los tres, no es libre (sí de
uso gratuito si se va a utilizar en proyectos libres).

Así­ que en este artículo vamos a explicar como trabajar con Subversion,
aunque dada la similitud con CVS lo aprendido aquí­ es fácilmente
aplicable a ese otro SCV.

Ciclo de uso de Subversion

La mayorí­a de los programadores utilizan CVS y Subversion de una forma
más bien cíclica. En este apartado vamos a ver en que consiste ese ciclo
y que comandos vamos a utilizar para cada paso.

1. Obteniendo una copia de trabajo

Antes de empezar a explicar comandos y operaciones conviene entender un
poco como se va a trabajar normalmente con un SCV como Subversion.
Supongamos que decidimos colaborar a un proyecto de software libre que
utiliza Subversion como SCV y dispone de un repositorio publico del que
podemos bajarnos las fuentes listas para trabajar, y que disponemos de
permiso de escritura para ese repositorio. Si tenemos ya instalado
Subversion, el comando habitual para descargar esas fuentes serí­a algo
parecido a esto (supongamos que el proyecto se llama SuperMail):

svn co http://www.supermail.org/repositorio/svn/tronco supermail

Esto nos copiaráa desde la red a un directorio 'supermail' en nuestro
sistema de archivos todo el código fuente del proyecto hospedado en el
repositorio Subversion del proyecto. 'svn' es el comando que vamos a
utilizar casi siempre mientras trabajamos con Subversion, indicándolo
subcomandos que especifican la operación a realizar; 'co' es la
abreviatura de 'checkout' que es la operación que creará una copia del
repositorio en nuestro sistema de archivos local sobre la que podamos
trabajar y a continuación vemos una URL que indica la dirección de donde
obtener las fuentes (Podemos observar que la es una dirección HTTP:
Subversion utiliza Apache+WebDav para los repositorios de acceso por
Internet; si nuestro repositorio va a ser privado no necesitaremos
Apache). Por último, la palabra 'supermail' indica el nombre del
directorio local donde se copiará el contenido del anterior repositorio
(de no existir se crearía) y es necesario porque en este caso (como
sucede con bastantes repositorios de Subversion) el repositorio del
proyecto no se ha denominado 'supermail' sino 'tronco' (o más
habitualmente su equivalente en inglés 'trunk'). Esto suele hacerse así
porque en ocasiones puede convenir que en un mismo repositorio coexista
más de un proyecto.

Una vez hemos ejecutado el comando vemos que empieza a aparecer una
salida en la que se va enumerando cada fichero y directorio contenido en
el proyecto con una letra 'A' antepuesta. Esta letra indica que el
fichero se ha añadido nuevo, más adelante veremos que existen otras
letras que indican otras operaciones sobre nuestra copia del
repositorio.

2. Trabajando

Cuando los ficheros se han terminado de descargar ya podemos meternos en
el directorio supermail/ y empezar a hacer los cambios que queramos
(programación, documentación, etc), teniendo solamente en cuenta que
cuando creemos un fichero nuevo tenemos que utilizar el comando 'svn add
fichero' (si el fichero no existe en el directorio especificado lo
creará vacío) para informar a Subversion de los ficheros nuevos que
añadamos, 'svn rm fichero' para informarle de los ficheros que
eliminemos, y 'svn mv fichero' y 'svn cp fichero' para mover y copiar,
respectivamente, los ficheros. Es decir, si dividiéramos los tipos de
cambios en 'cambios a ficheros' y 'cambios al árbol de directorios' los
primeros no necesitarían de ningún comando especial (tan sólo
necesitamos hacer los cambios como los haríamos si no estuviera
Subversion, es decir, con nuestro editor favorito en el caso de ficheros
de texto) mientras que los cambios al árbol de directorios del proyecto
si necesitan utilizar los comandos que hemos visto para indicarle a
Subversion estos cambios (svn [add|rm|cp|mv], normalmente).

3. Comprobando los cambios

Una vez hemos quedado satisfechos con los cambios realizados, es hora de
comprobar el conjunto de cambios que hemos realizado sobre la copia
original que descargamos al principio.

Esto se realiza mediante el comando 'svn status' que producirá una
salida con un lista de los ficheros que han cambiado con respecto al
original y una letra indicando el tipo de cambio. el significado para
algunas de estas letras es:

  • A El fichero ha sido añadido.
  • D El fichero ha sido eliminado.
  • M El fichero contiene modificaciones con respecto al original
  • _M El fichero contiene modificaciones de propiedades respecto al
    original (veremos más tarde que son las propiedades)
  • ? El fichero existe en la copia local, pero no en el repositorio
    (quizás sea un fichero temporal creado por compilaciones, o es un
    fichero que hemos creado nosotros pero se nos ha olvidado hacer 'svn
    add').
  • ! El fichero existe en el repositorio pero no es nuestra copia local
    (quizás se nos ha olvidado hacer 'svn remove').
  • ~ Algo que está marcado como fichero es un directorio o viceversa.

Como podemos ver por el significado de cada carácter, este comando es
muy útil para asegurarnos de que no nos ha olvidado añadir o eliminar
ficheros o de que no hemos realizado modificaciones inesperadas a
ficheros que no pretendíamos modificar (en este caso podríamos deshacer
las modificaciones inesperadas haciendo 'svn revert FICHERO').

Por defecto svn status ignora los ficheros que concuerdan terminan con
.o, .lo, .la, y algunos más, pues casi siempre estos ficheros son
ficheros temporales creados por la compilación de archivos. La expresión
regular que contiene los ficheros a ignorar es la propiedad svn:ignore
del directorio padre (veremos más sobre propiedades un poco más
adelante).

También, como con casi todos los comandos de Subversion, podemos obtener
información de estado sobre un sólo fichero o directorio indicando su
ruta:

svn status supermail/README

Además, si ejecutamos svn status con el parámetro -v aparecerán dos
nuevas columnas indicando cual fue la última revisión en la que se
cambió el fichero y quien lo hizo.

4. Actualizando la copia de trabajo

El último paso antes de hacer efectivos nuestros cambios con el
repositorio global es actualizar nuestra copia local para que se
reflejen esos cambios, y poder resolver los conflictos que hayan podido
surgir.

Para ello utilizamos 'svn up' (de update) que nos irá mostrando una
lista de los ficheros que han cambiado con, de nuevo, una letra
indicando el tipo de cambio. El significado de esta letra es el mismo
que hemos explicado con 'svn status' pero además pueden darse:

  • U El fichero, que no habíamos cambiado, se ha actualizado
  • G Un fichero que habíamos cambiado se ha actualizado, y Subversion ha
    unido ambos cambios sin ningún problema.
  • C Un fichero que habíamos cambiado se ha actualizado, y el cambio ha
    provocado un conflicto.

Si se produce un conflicto en algún fichero debemos resolverlo
manualmente (Subversion aún no sabe programar) para lo cual abrimos el
fichero, observamos las partes que Subversion nos ha marcado indicando
los cambios locales y los del repositorio global y resolvemos el
conflicto. Una vez lo hemos hecho ejecutamos tenemos que ejecutar 'svn
resolve FICHERO' para indicar a Subversion que el conflicto está
resuelto.

5. Enví­ando nuestros cambios

Una vez hemos comprobado (mediante svn status y svn update) que nuestros
cambios son correctos y que no son conflictivos con lo que actualmente
existe en el repositorio global (y si no lo fueran, lo resolvemos y
ejecutamos de nuevo svn status y svn update para asegurarnos) llega el
momento de enviar nuestros cambios a dicho repositorio.

Para ello se utiliza el commando 'svn commit' al que normalmente le
vamos a pasar el parámetro -m con un mensaje de texto indicando los
cambios que hemos realizado (luego la gente podrá ver ese mensaje cuando
consulte los históricos). Si no le pasamos el parámetro -m utilizará la
variable de entorno $EDITOR para abrir un editor de texto en el que
introduzcamos un mensaje.

Por ejemplo, el comando podría quedar de la siguiente forma:

svn commit -m "He mejorado mucho la ritratransfusión de los megabixeloides"

svn commit fallará si se han realizado nuevos cambios en el repositorio
global; en este caso tendremos que actualizar (svn update) y volver al
punto 4.

En el caso de que no tuviéramos permiso de escritura, Subversion nos
permite crear un parche, que podamos enviar por email a los autores, de
forma muy sencilla; Sólo tenemos que ejecutar desde el directorio
superior del proyecto:

cvs diff > parche.diff

Y ya tendríamos nuestro parche en el archivo parche.diff, que podríamos
mandar al autor o autores para que lo añadieran utilizando el comando
patch < parche.diff desde el mismo directorio.

Y ya está, en realidad, salvo casos muy concretos, no vamos a salirnos
casi nunca de los comandos especificados en este apartado. Una vez hemos
terminado de trabajar, y nos hemos asegurado de que nuestros cambios se
han enviado correctamente al repositorio global podemos o bien borrar
nuestro directorio de trabajo y volver a hacer el checkout la próxima
vez que queramos trabajar en el, o no borrarlo y hacer el update en su
lugar.

Otras operaciones con Subversion

Una vez que hemos visto el manejo fundamental de Subversion, vamos a recorrer
otras operaciones habituales que podemos realizar con el mismo, y algunas 'bases
teóricas' fundamentales.

El sistema de versiones

El sistema de versiones de Subversion es distinto al de CVS. En el segundo,
cada fichero tiene su propia versión, y los directorios no tienen versiones
pues CVS los considera simplemente como 'contenedores de ficheros', lo que
causa muchos dolores de cabeza a sus usuarios a la hora de reorganizar el árbol
de un proyecto. En Subversion las versiones se aplican a todo el árbol
de nuestro proyecto (incrementándose en uno en cada commit), y por lo tanto
todos los ficheros tendrán la misma versión en una misma 'captura' del árbol,
incluyendo los directorios.

Por ejemplo, si tuviéramos un sencillo proyecto que contuviera los siguientes ficheros:

hola/README
hola/INSTALL
hola/holamundo.c

En la primera versión todos los ficheros tendrían la versión '1'. Si después hiciéramos un cambio al fichero
INSTALL y ejecutáramos el commit, las versión del árbol, y por lo tanto la de todos sus
archivos, cambiaría a '2'.

Creando nuestro repositorio

Crear un repositorio es tan sencillo como utilizar los comando:


mkdir /home/usuario/svn
svnadmin create /home/usuario/svn

Con esto se nos crearía un repositorio básico (vacío) en el cual podríamos empezar a crear
ficheros y directorios. Pero normalmente nos interesará importar algún arbol de código existente,
para lo cual tendríamos que hacer a continuación:


svn import file:///home/usuario/svn /home/usuario/HolaMundo holamundo

Analicemos. El comando para importar un código existente es 'svn import'. A
continuación le hemos pasado la URL a nuestro repositorio (que como resulta que
está en nuestro sistema de archivos tiene la forma file://[ruta_completa], hay
que recordar que svn siempre trabaja con URLs cuando se refiere a repositorios
globales, no así svnadmin), después le indicamos donde está el árbol existente
que queremos importar (en este caso /home/usuario/HolaMundo) y por último el
subdirectorio dentro del repositorio en el que queremos que se importe, de modo
que si quisiéramos hacer un checkout para crear una copia local y comprobar que
se ha importado correctamente tendríamos que hacer:

svn co file:///home/usuario/svn/holamundo copia_local

Lo que nos crearía en el directorio actual un subdirectorio 'copia_local' conteniendo
el árbol (Subversionizado) de nuestro proyecto 'HolaMundo'.

Sin embargo normalmente nos va a interesar crear más de un subdirectorio dentro de nuestro
repositorio de 'HolaMundo' de forma que en uno de ellos contengamos el árbol de la versión
en desarrollo o inestable, en otro las distintas ramas (veremos algo sobre ramas más
adelante) y en otro las distintas versiones estables. Por ello nos conviene utilizar
el subcomando mkdir para crear los distintos subdirectorios dentro del repositorio de nuestro
proyecto 'holamundo':


mkdir /home/usuario/svn
svnadmin create /home/usuario/svn
svn mkdir file:///home/usuario/svn/holamundo -m "Directorio base para HolaMundo"
svn import file:///home/usuario/svn/holamundo /home/usuario/HolaMundo head -m "Rama en desarrollo"
svn mkdir file:///home/usuario/svn/holamundo/ramas -m "Directorio de ramas"
svn mkdir file:///home/usuario/svn/holamundo/finales -m "Directorio de versiones finales"

Tras esto nos quedaría un repositorio conteniendo a su vez tres directorios (que podríamos
considerar 'subrepositorios') que serían 'head', con código ya añadido, y que contendrá
las versiones en continuo desarrollo, "ramas" que podría contener en el futuro distintas ramas
del desarrollo y "finales" que contendría imágenes de las versiones finales estables de nuestro
programa.

Deshaciendo un cambio

Existen dos formas de deshacer un cambio, dependiendo de en que fase del desarrollo
lo hayamos hecho. Si el cambio se ha producido sólo localmente, y queremos volver en
determinado archivo a la versión del repositorio global, tan sólo tenemos que hacer
svn revert fichero
o svn revert a secas desde el directorio raíz si quisiéramos
deshacer todos los cambios.

El segundo caso es que queramos deshacer uno o más cambios ya enviados al repositorio
global en un commit anterior. En este caso tendremos que utilizar el subcomando 'merge'
indicando en primer lugar la revisión desde la que queremos volver atrás y en segundo lugar
la revisión a la que queremos volver. Por ejemplo, si en nuestro proyecto (revisión 5) un día que estábamos
borrachos hicimos dos horrendos commits (revisión 6 y revisión 7) y al día siguiente
comprobáramos con resacoso horror el estropicio realizado, podríamos volver tranquilamente
a nuestra revisión pre-pedal con:

svn merge -r 7:5

Aquí podemos ver que hemos utilizado el subcomando merge con un parámetro '-r' que nos permite indicar
dos revisiones sobre las que efectuar el cambio, y hemos indicado en primer lugar la última revisión
que hicimos tolingas seguido de dos puntos y la última revisión que hicimos sobrios. Como con
casi todos los comandos, además, podemos especificar como parámetro uno o varios archivos o directorios
para que los cambios se realicen sólamente sobre ellos.

'merge' tiene otros usos que veremos más adelante.

Históricos y registros

En muchas ocasiones nos resultará tremendamente útil comprobar que mensajes se adjuntaron a cada revisión,
los cambios producidos en ellas, los cambios entre dos revisiones especificadas, etc.
Todas estas operaciones se realizan mediante los comandos 'svn log' y 'svn diff'.

'svn log' permite obtener los mensajes que el autor de cada revisión escribió. Si lo ejecutamos en el
directorio raíz y sin parámetros nos mostrará todos los mensajes de todas las revisiones, pero
también podemos ejecutarlo sobre un archivo o directorio en cuyo caso sólo nos mostrará los mensajes
de las revisiones que modificaran ese archivo. También puede especificarse un conjunto de revisiones
con el parámetro -r (como vimos anteriormente con svn merge) si sólo queremos ver las revisiones
comprendidas en ese rango.

'svn diff' ejecutado sin parámetros nos permite, como vimos anteriormente, ver las diferencias
entre nuestra copia de trabajo y el fichero original en el repositorio global, pero, como era de esperar,
también admite el parámetro -r para especificar un rango de revisiones entre las que queremos que se nos
muestren los cambios a los ficheros, por ejemplo svn diff -r 2:4 ejecutado desde el
directorio raíz de la copia de trabajo mostraría todos los cambios realizados a los ficheros
que fueran modificados entre la segunda y la cuarta revisión. 'svn diff' también admite ficheros o
conjuntos de ficheros como parámetro para mostrar sólo los cambios producidos en ellos.

Ramas

El concepto de rama es uno de los más útiles a la hora de trabajar con sistemas
de control de versiones. Se explica mejor con un ejemplo; imaginamos que
nuestro afamado programa 'HolaMundo' ha llegado a un punto en el que tiene la
estabilidad y características necesarias para poder considerarlo una versión
'Beta', pero tenemos otras características en mente que quisiéramos añadir
(como colorear el HolaMundo, efectos de fuegos artificiales que forman las
palabras, etc) pero a una versión posterior a esta beta. Una solución sería
hacer un paquete con el código fuente de la versión actual, publicarlo como
'HolaMundo 1.0-Beta' y seguir trabajando en las nuevas características en nuestro
repositorio Subversion. El problema obvio es que si, como es natural, a nuestra
versión beta le salen fallos, ya no podemos incorporarlos al repositorio sin incorporar
al mismo tiempo a esa versión las nuevas (e inestables) características que hemos
desarrollado, con lo cual podríamos introducir nuevos fallos. Tendríamos que, o bien
seguir desarrollando el código de esa beta por separado sin ningún repositorio, o bien
crear un nuevo repositorio sólo para ella hasta que se convierta en 'versión estable'.
En cualquier caso si arregláramos un fallo en la versión beta, y quisiéramos incorporar
ese arreglo también a la versión en desarrollo, tendríamos que hacerlo 'a mano'.

Las ramas nos proporcionan una solución elegante a todo este embrollo. Las ramas ('branches')
nos permiten seguir desarrollando una versión paralela del proyecto, surgida a partir de una
determinada última revisión común, y nos permitirán seguir intercambiando cambios entre ambas
cuando queramos.

Para crear una rama a partir de una revisión existente se utiliza el subcomando 'cp'. En este
caso vamos a suponer que la revisión 173 de nuestro proyecto 'HolaMundo' es lo bastante estable
como para poder considerarla una beta, por lo que decidimos crear una rama del proyecto llamada
'holamundo-beta'. Suponiendo que hubiéramos utilizado la estructura explicada en el apartado de
creación de un repositorio haríamos:


svn cp file:///home/usuario/svn/holamundo/head file:///home/usuario/svn/holamundo/ramas/holamundo-beta

Ya tenemos nuestra rama lista para ser modificada independientemente de la
principal. Es importante destacar que la nueva rama no ocupará nada de espacio
en disco mientras no modifiquemos nada, pues sus ficheros en realidad serán
punteros a los mismos ficheros de la revisión en la que salga en la rama
inestable pero según vayamos modificando ficheros se irán creando copias con
las modificaciones en esta rama. Como vemos, ya podemos arreglar fallos
tranquilamente en la rama holamundo-beta mientras seguimos añadiendo felizmente
características inútiles y llenas de bugs a la rama head.

Aún nos queda el segundo problema que teníamos ¿cómo hacemos que las soluciones a los bugs
de la versión beta se apliquen también a la versión inestable? Para ello se utiliza el comando
svn merge, que ya conocíamos anteriormente aplicado a deshacer una revisión o parte de ella. En
este caso, suponiendo que la solución al fallo se haya hecho en la revisión 177 de la rama
holamundo-beta, el comando a utilizar sería (suponiendo que estuviéramos en el directorio
raíz de la versión inestable):

svn merge -r 176:177 file:///home/usuario/svn/holamundo/ramas/holamundo-beta .

Con esto (si no hay conflictos) ya deberíamos tener también la solución al
fallo incorporada en la versión inestable. Por supuesto para que este comando
sólo incorpore la solución, esta debe de haber el único cambio incorporado
entre la revisión 176 y la 177, es decir, no se deben de haber realizado otros
cambios en ese mismo commit pues sino esos otros cambios también se aplicarán
en nuestra versión inestable (salvo que especifiquemos ficheros pero, de nuevo,
sólo suponiendo que la solución al fallo sea la única fuente de modificación de
esos ficheros). Por ello (entre otros muchos motivos como por ejemplo la
conveniencia de poder deshacer un cambio)es más que conveniente intentar que
los commits sean pequeños y que nunca incorporen cambios que no estén relacionados.

¿Y qué son los tags? Los tags en terminología CVS no son más que etiquetas
que le dan un nombre a una determinada revisión del árbol, por ejemplo llamar
'1.0Final' a la revisión 345. Subversion no tiene tags pero es fácil conseguir
el mismo resultado simplemente copiando la revisión que interese con 'svn cp'
al directorio 'finales' con el nombre de la versión real (que podríamos haber
llamado igualmente 'tags') y ajustando la propiedad del directorio a
sólo-lectura (veremos más adelante como ajustar las propiedades de un fichero o
directorio):

svn cp -r 345 file:///home/usuario/svn/holamundo/ramas/holamundo-beta \
file:///home/usuario/svn/holamundo/finales/1_0
svn propset svn:read-only 1 file:///home/usuario/svn/holamundo/finales/1_0

Una vez que hemos terminado de trabajar con una rama, y creado una nueva versión (como
hemos visto antes, con svn cp al directorio de tags) o incorporado sus cambios experimentales
en nuestra rama principal, podemos eliminarla con 'svm rm'.

Propiedades

Las propiedades son valores textuales que podemos asociar con cada fichero o directorio de
un repositorio. Por ejemplo en el apartado anterior hemos puesto la
propiedad 'svn:read-only'
de un directorio del repositorio a uno. svn:read-only en realidad es una propiedad especial con
un significado concreto, pero nosotros podemos poner propiedades con los
nombre y los valores que queramos simplemente teniendo cuidado de que
sus nombres no empiecen por 'svn:' pues este prefijo se ha reservado
para las propiedades con un significado especial para Subversion.

Entre estas 'propiedades especiales', destacaremos:

  • svn;read-only Como hemos visto, mientras exista esta propiedad no se
    nos permitirá modificar el fichero o directorio sobra el que la
    propiedad esté asignada.
  • svn:executable Esta propiedad (que sólo es aplicable a ficheros)
    especifica que el fichero es ejecutable.
  • svn:mime-type Esta propiedad se utiliza para intentar determinar el
    tipo mime del fichero. Si Subversion está intentando determinar el tipo
    de un fichero y no tiene esta propiedad puesta, intentará adivinar el
    tipo de forma 'inteligente' por lo que normalmente no vamos a tener que
    especificarle que ficheros son binarios y cuales no (como sucede con
    CVS).
  • svn:ignore Hace que Subversion ignore todos los ficheros cuyos
    nombres coincidan con los patrones especificados por esta propiedad. Por
    defecto ignora automáticamente los ficheros con extensión .o, .lo, .la y
    alguno más, resultado de la compilación de programas C/C++. Los patrones
    deben ir uno en cada línea, más adelante veremos como poner propiedades
    con valores multilínea.
  • svn:keywords Subversion, como CVS, tiene la habilidad para sustituir
    determinadas palabras clave dentro del texto de un archivo por valores,
    por ejemplo, puede sustituir $LastChangedDate$ automáticamente por
    $LastChangedDate: 2002-10-22 18:58:35 +100 (Thu 22 Oct 2002)$, pero para
    que se activen esas substituciones debe de existir el valor adecuado
    dentro de la propiedad keywords del archivo, por ejemplo en este caso
    debería contener (posiblemente entre otros) la cadena "Date".
  • svn:eol-style Esta propiedad especifica la forma en la que se hacen
    los saltos de línea en los archivos de texto; esto es útil porque
    distintos sistemas operativos tienen distintas formas de hacer los
    saltos de línea. Lo más aconsejable en un proyecto en el que los
    ficheros fuente vayan a ser utilizados desde distintos sistemas
    operativos es poner esta propiedad a "native" que especificará que en
    cada sistema operativo se utilicen los saltos de línea del mismo. Sin
    embargo, en otros casos puede interesar que determinado fichero tenga
    los saltos de línea de un determinado tipo, por lo que esta propiedad
    también puede tomar los valores "LF", "CR", o "CRLF".

Pero ¿cómo cambiar y obtener las propiedades de un fichero o directorio?
Muy sencillo, simplemente utilizamos 'svn propget propiedad fichero' para obtener las
propiedades y 'svn propset propiedad valor fichero' para ponerlas. En el caso de
que queramos editar una propiedad con nuestro editor de texto (algo
interesante para propiedades que puedan tener valores de varias líneas
como svn:ignore) utilizaremos 'svn propedit propiedad fichero'.

Administración general de un repositorio

svnlook

Esta utilidad sirve para analizar los cambios que se han ido
produciendo a un repositorio a lo largo del tiempo, sin cambiarlo.
La forma más obvia de utilizarlo es con svnlook
/home/usuario/svn
(siendo por supuesto la ruta dependiente de
donde esté nuestro repositorio). Esto nos mostrará por pantalla el árbol
de directorios y ficheros correspondiente a ese repositorio en la
revisión actual. Además podemos especificar una revisión concreta con
svnlook /home/usuario/svn rev número lo que nos dará el
árbol del repositorio para la revisión 'número'. svnlook [ruta] rev
[numero] puede tener además subcomandos adicionales que especifican el
tipo de información que queremos obtener para esa revisión determinada,
que irán al final del comando:

  • log Mostrará el mensaje que el autor de la revisión escribió.
  • author Mostrará el autor de la revisión.
  • date Mostrará la fecha de la revisión
  • dirs-changed Mostrará los directorios que cambiaron en la revisión
  • changed Mostrará todos los ficheros y directorios que cambiaron en
    la revisión.
  • diff Mostrará diferencias en el formato utilizado por diff -u de los
    cambios realizados en la revisión.
svnadmin

Ya hemos visto anteriormente que podemos utilizar svnadmin para crear
nuevo repositorios mediante su subcomando 'create'. Pero svnadmin tiene
otros subcomandos bastante interesantes, entre los que están:

  • lsrevs ruta_al_repositorio [revisión_menor] [revisión_mayor]:
    Muestra todo el árbol de todas las revisiones, incluyendo números de
    versión, mensajes de log y otros datos. Si se especifican revision_menor
    y revisión_mayor sólo listará las revisiones comprendidas entre esos dos
    parámetros.
  • lscr ruta_al_repositorio ruta: Mostrará todas las revisiones
    en las que se ha cambiado el fichero o directorio 'ruta' dentro del
    repositorio.
  • setlog ruta_al_repositorio revisión fichero_con_mensaje:
    Cambiará el mensaje de log de la revisión especificada por el contenido
    del fichero 'fichero con mensaje'. Hay que tener cuidado al hacer esto
    pues este cambio no se puede deshacer automáticamente.
  • shell ruta_al_repositorio: Este es uno de los (sub)comandos
    más útiles de svnadmin. Nos proporcionará una sencilla shell desde la
    que podemos navegar el repositorio especificado como si de un directorio
    local del sistema de archivos se tratase de forma que podamos cambiar
    entre los distintos directorios y listar sus contenidos. Esta simplísima
    shell sólo cuente (de momento) con los comandos 'help' (muestra la
    ayuda), 'cd' (cambia de directorio), 'ls' (lista un directorio), 'cr'
    (cambia la revisión sobre la que estamos navegando) y 'exit' (sale de la
    shell).
  • youngest ruta_al_repositorio:Muestra el número de la revisión
    más reciente del repositorio.
  • dump ruta_al_repositorio [revisión_menor] [revisión_mayor]:
    Otro comando extremádamente útil. Nos permite volcar el contenido de un
    repositorio, bien todas las revisiones, bien sólo una de ellas (si sólo
    se ha especificado revisión_menor) o bien un rango de ellas (si se han
    especificado tanto revisión_menor como revisión_mayor) a la salida
    estándar (aunque normalmente la vamos a redirigir a un fichero) en un
    formato de fichero portable. Este fichero normalmente lo vamos a
    utilizar como copia de seguridad del repositorio, o para trasladar el
    repositorio a otro sistema. También es necesario hacerlo cuando
    actualicemos Subversion y la nueva versión tenga un formato interno
    incompatible con la que veníamos utilizando.
  • load ruta_al_repositorio: Lee de la entrada estándar (a la
    que normalmente vamos a volcarle un fichero) un fichero como el creado
    mediante el comando dump, y recrea el repositorio en la ruta
    especificada. Esto es útil para restaurar copias de seguridad o crear
    una réplica de un repositorio que existía anteriormente en otro sistema.

Haciendo que un repositorio sea accesible a través de Internet

En algunos ejemplos anteriores hemos visto que cuando accedemos a un
repositorio en Internet con Subversion especificamos una URL de
protocolo HTTP (http://www.midominio,org/mirepositorio, por ejemplo).
Esto es así porque para publicar repositorios por Internet Subversion
utiliza Apache con el módulo WebDav, que es un protocolo que permite
acceder y modificar ficheros de el servidor Apache. No nos vamos a
extender en como instalar Apache (por cierto, necesita la versión 2.0) y
el módulo WebDav, pero indicaré los pasos a seguir:

  1. Instalar Apache 2.0, procurar que funcione ;)
  2. Instalar el módulo mod_dav.
  3. Instalar el plugin mod_dav_svn para el módulo mod_dav.
  4. Configurar correctamente el fichero http.conf.

Los pasos uno a tres suelen poderse conseguir fácilmente si utilizamos
una distribución moderna de Linux, pues casi todas incluyen ya entre sus
paquetes Apache 2.0, el módulo WebDav para el mismo, y en algunas
ocasiones hasta el plugin para el módulo webDav.

El último paso (configurar el fichero http.conf) consiste en añadir al
final del fichero http.conf lo siguiente:

<Location /repos/mirepo>
   DAV svn
   SVNPath /home/usuario/svn
</Location>

Cambiando '/home/usuario/svn' por la ruta real de nuestro repositorio
y 'repos/mirepo' por la parte final de la URL que queramos que
represente nuestro repositorio a través de Internet, por ejemplo, si
nuestro dominio es http://www.midominio.com y queremos que nuestro
repositorio, situado en /home/usuario/repositorio se vea a través de
internet como http://www.midominio.com/repositorio/HolaMundo tendríamos
que añadir al http.conf:

<Location /repositorio/HolaMundo>
   DAV svn
   SVNPath /home/usuario/repositorio
</Location>

Ya sólo nos queda restringir los permisos de acceso para que
sólo puedan leer y hacer commits a nuestro repositorio las personas que
nosotros consideremos oportuno. Para el caso más habitual de un acceso
de lectura público y un acceso de escritura por usuario creamos un
fichero que contenga nombres de usuarios y claves cifradas con el
comando crypt con el siguiente formato:

usuario1:clave_cifrada1
usuario2:clave_cifrada2
...

Después dentro del grupo 'Location' que acabamos de definir en el
archivo http.conf añadimos las siguientes opciones:

AuthType Basic
AuthName "Repositorio Subversion"
AuthUserFile /ruta/al/fichero/de/usuarios

<LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
</LimitExcept>

Sustituyendo "Repositorio Subversion" por el texto que queramos que
aparezca en la cadena de autenticación y
"/ruta/al/fichero/de/usuarios" por la ruta real del fichero que hemos
creado anteriormente con el listado de usuarios.

Responder

Please solve the math problem above and type in the result. e.g. for 1+1, type 2.
The content of this field is kept private and will not be shown publicly.
  • Lines and paragraphs break automatically.

More information about formatting options