Sistema de manejo y seguimiento de proyectos: Trac

Trac es un sistema multiplataforma desarrollado y mantenido por Edgewall Software, el cual está orientado al seguimiento y manejo de proyectos de desarrollo de software haciendo uso de un enfoque minimalista basado en la Web, su misión es ayudar a los desarrolladores a escribir software de excelente calidad mientras busca no interferir con el proceso y políticas de desarrollo. Incluye un sistema wiki que es adecuado para el manejo de la base de conocimiento del proyecto, fácil integración con sistemas de control de versiones ((Por defecto Trac se integra con subversion)). Además incluye una interfaz para el seguimiento de tareas, mejoras y reporte de errores por medio de un completo y totalmente personalizable sistema de tickets, todo esto con el fin de ofrecer una interfaz integrada y consistente para acceder a toda información referente al proyecto de desarrollo de software. Además, todas estas capacidades son extensibles por medio de plugins o complementos desarrollados específicamente para Trac.

Breve historia de Trac

El origen de Trac no es una idea original, algunos de sus objetivos se basan en los diversos sistemas de manejo y seguimiento de errores que existen en la actualidad, particularmente del sistema CVSTrac y sus autores.

Trac comenzó como la reimplementación del sistema CVSTrac en el lenguaje de programación Python y como ejercicio de entretenimiento, además de utilizar la base de datos embebida SQLite ((Hoy día también se le da soporte a PostgreSQL, mayor detalle en Database Backend)). En un corto lapso de tiempo, el alcance de estos esfuerzos iniciales crecieron en gran medida, se establecieron metas y en el presente Trac presenta un curso de desarrollo propio.

Los desarrolladores de Edgewall Software esperan que Trac sea una plataforma viable para explorar y expandir el cómo y qué puede hacerse con sistemas de manejo de proyectos de desarrollo de software basados en sistemas wiki.

Características de Trac

A continuación se presenta una descripción breve de las distintas características de Trac.

Herramienta de código abierto para el manejo de proyectos

Trac es una herramienta ligera para el manejo de proyectos basada en la Web, desarrollada en el lenguaje de programación Python. Está enfocada en el manejo de proyectos de desarrollo de software, aunque es lo suficientemente flexible para usarla en muchos tipos de proyectos. Al ser una herramienta de código abierto, si Trac no llena completamente sus necesidades, puede aplicar los cambios necesarios usted mismo, escribir complementos o plugins, o contratar a alguien calificado que lo haga por usted.

Sistema de tickets

Tickets activos para el hito 0.12 de Trac, ordenados por última fecha de modificación

El sistema de tickets le permite hacer seguimiento del progreso en la resolución de problemas de programación particulares, requerimientos de nuevas características, problemas e ideas, cada una de ellas en su propio ticket, los cuales son enumerados de manera ascendente. Puede resolver o reconciliar aquellos tickets que buscan un mismo objetivo o donde más de una persona reporta el mismo requerimiento. Permite hacer búsquedas o filtrar tickets por severidad, componente del proyecto, versión, responsable de atender el ticket, entre otros.

Para mejorar el seguimiento de los tickets Trac ofrece la posibilidad de activar notificaciones vía correo electrónico, de este modo se mantiene informado a los desarrolladores de los avances en la resolución de las actividades planificadas.

Vista de progreso

Existen varias maneras convenientes de estar al día con los acontecimientos y cambios que ocurren dentro de un proyecto. Puede establecer hitos y ver un mapa del progreso (así como los logros históricos) de manera resumida. Además, puede visualizar desde una interfaz centralizada los cambios ocurridos cronológicamente en el wiki, hitos, tickets y repositorios de código fuente, comenzando con los eventos más recientes, toda esta información es accesible vía Web o de manera alternativa Trac le ofrece la posibilidad de exportar esta información a otros formatos como el RSS, permitiendo que los usuarios puedan observar esos cambios fuera de la interfaz centralizada de Trac, así como la notificación por correo electrónico.

vista de progreso del proyecto

Vista del repositorio en línea

Una de las características de mayor uso en Trac es el navegador o visor del repositorio en línea, se le ofrece una interfaz bastante amigable para el sistema de control de versiones que esté usando ((Por defecto Trac se integra con subversion, la integración con otros sistemas es posible gracias a plugins o complementos.)). Este visualizador en línea le ofrece una manera clara y elegante de observar el código fuente resaltado, así como también la comparación de ficheros, apreciando fácilmente las diferencias entre ellos.

Visor de código fuente en Trac

Manejo de usuarios

Trac ofrece un sistema de permisología para controlar cuales usuarios pueden acceder o no a determinadas secciones del sistema de manejo y seguimiento del proyecto, esto se logra a través de la interfaz administrativa. Además, esta interfaz es posible integrarla con la definición de permisos de lectura y escritura de los usuarios en el sistema de control de versiones, de ese modo se logra una administración centralizada de usuarios.

Wiki

El sistema wiki es ideal para mantener la base de conocimientos del proyecto, la cual puede ser usada por los desarrolladores o como medio para ofrecerles recursos a los usuarios. Tal como funcionan otros sistemas wiki, puede permitirse la edición compartida. La sintaxis del sistema wiki es bastante sencilla, si esto no es suficiente, es posible integrar en Trac un editor WYSIWYG (lo que se ve es lo que se obtiene, por sus siglas en inglés) que facilita la edición de los documentos.

Características adicionales

Al ser Trac un sistema modular puede ampliarse su funcionalidad por medio de complementos o plugins, desde sistemas anti-spam hasta diagramas de Gantt o sistemas de seguimiento de tiempo.

4 min read

Pylint: Análisis estático del código en Python

Básicamente el análisis estático del código se refiere al proceso de evaluación del código fuente sin ejecutarlo, es en base a este análisis que se obtendrá información que nos permita mejorar la línea base de nuestro proyecto, sin alterar la semántica original de la aplicación.

Pylint es una herramienta que todo programador en Python debe considerar en su proceso de integración continua (Ej. Bitten), básicamente su misión es analizar código en Python en busca de errores o síntomas de mala calidad en el código fuente. Cabe destacar que por omisión, la guía de estilo a la que se trata de apegar Pylint es la descrita en el PEP-8.

Es importante resaltar que Pylint no sustituye las labores de revisión continua de alto nivel en el Proyecto, con esto quiero decir, su estructura, arquitectura, comunicación con elementos externos como bibliotecas, diseño, entre otros.

Tome en cuenta que Pylint puede arrojar falsos positivos, esto puede entenderse al recibir una alerta por parte de Pylint de alguna cuestión que usted realizó conscientemente. Ciertamente algunas de las advertencias encontradas por Pylint pueden ser peligrosas en algunos contextos, pero puede que en otros no lo sea, o simplemente Pylint haga revisiones de cosas que a usted realmente no le importan. Puede ajustar la configuración de Pylint para no ser informado acerca de ciertos tipos de advertencias o errores.

Entre la serie de revisiones que hace Pylint al código fuente se encuentran las siguientes:

  • Revisiones básicas:
    • Presencia de cadenas de documentación (docstring).
    • Nombres de módulos, clases, funciones, métodos, argumentos, variables.
    • Número de argumentos, variables locales, retornos y sentencias en funciones y métodos.
    • Atributos requeridos para módulos.
    • Valores por omisión no recomendados como argumentos.
    • Redefinición de funciones, métodos, clases.
    • Uso de declaraciones globales.
  • Revisión de variables:
    • Determina si una variable o import no está siendo usado.
    • Variables indefinidas.
    • Redefinición de variables proveniente de módulos builtins o de ámbito externo.
    • Uso de una variable antes de asignación de valor.
  • Revisión de clases:
    • Métodos sin self como primer argumento.
    • Acceso único a miembros existentes vía self
    • Atributos no definidos en el método __init__
    • Código inalcanzable.
  • Revisión de diseño:
    • Número de métodos, atributos, variables locales, entre otros.
    • Tamaño, complejidad de funciones, métodos, entre otros.
  • Revisión de imports:
    • Dependencias externas.
    • imports relativos o importe de todos los métodos, variables vía * (wildcard).
    • Uso de imports cíclicos.
    • Uso de módulos obsoletos.
  • Conflictos entre viejo/nuevo estilo:
    • Uso de property, __slots__, super.
    • Uso de super.
  • Revisiones de formato:
    • Construcciones no autorizadas.
    • Sangrado estricto del código.
    • Longitud de la línea.
    • Uso de <> en vez de !=.
  • Otras revisiones:
    • Notas de alerta en el código como FIXME, XXX.
    • Código fuente con caracteres non-ASCII sin tener una declaración de encoding. PEP-263
    • Búsqueda por similitudes o duplicación en el código fuente.
    • Revisión de excepciones.
    • Revisiones de tipo haciendo uso de inferencia de tipos.

Mientras Pylint hace el análisis estático del código muestra una serie de mensajes así como también algunas estadísticas acerca del número de advertencias y errores encontrados en los diferentes ficheros. Estos mensajes son clasificados bajo ciertas categorías, entre las cuales se encuentran:

  • Refactorización: Asociado a una violación en alguna buena práctica.
  • Convención: Asociada a una violación al estándar de codificación.
  • Advertencia: Asociadas a problemas de estilo o errores de programación menores.
  • Error: Asociados a errores de programación importantes, es probable que se trate de un bug.
  • Fatal: Asociados a errores que no permiten a Pylint avanzar en su análisis.

Un ejemplo de este reporte lo puede ver a continuación:

Messages by category
--------------------

+-----------+-------+---------+-----------+
|type       |number |previous |difference |
+===========+=======+=========+===========+
|convention |969    |1721     |-752.00    |
+-----------+-------+---------+-----------+
|refactor   |267    |182      |+85.00     |
+-----------+-------+---------+-----------+
|warning    |763    |826      |-63.00     |
+-----------+-------+---------+-----------+
|error      |78     |291      |-213.00    |
+-----------+-------+---------+-----------+

Cabe resaltar que el formato de salida del ejemplo utilizado está en modo texto, usted puede elegir entre: coloreado, texto, msvs (Visual Estudio) y HTML.

Pylint le ofrece una sección dedicada a los reportes, esta se encuentra inmediatamente después de la sección de mensajes de análisis, cada uno de estos reportes se enfocan en un aspecto particular del proyecto, como el número de mensajes por categorías (mostrado arriba), dependencias internas y externas de los módulos, número de módulos procesados, el porcentaje de errores y advertencias encontradas por módulo, el total de errores y advertencias encontradas, el porcentaje de clases, funciones y módulos con docstrings y su respectiva comparación con un análisis previo (si existe). El porcentaje de clases, funciones y módulos con nombres correctos (de acuerdo al estándar de codificación), entre otros.

Al final del reporte arrojado por Pylint podrá observar una puntuación general por su código, basado en el número y la severidad de los errores y advertencias encontradas a lo largo del código fuente. Estos resultados suelen motivar a los desarrolladores a mejorar cada día más la calidad de su código fuente.

Si usted ejecuta Pylint varias veces sobre el mismo código, podrá ver el puntaje de la corrida previa junto al resultado de la corrida actual, de esta manera puede saber si ha mejorado la calidad de su código o no.

Global evaluation
-----------------
Your code has been rated at 7.74/10 (previous run: 4.64/10)
If you commit now, people should not be making nasty comments about you on c.l.py

Una de las grandes ventajas de Pylint es que es totalmente configurable, además, se pueden escribir complementos o plugins para agregar una funcionalidad que nos pueda ser útil.

Si usted quiere probar desde ya Pylint le recomiendo seguir la guía introductoria descrita en Pylint tutorial. Si desea una mayor ayuda respecto a los códigos indicados por Pylint, puede intentar el comando pylint --help-msg=CODIGO, si eso no es suficiente, le recomiendo visitar el wiki PyLint Messages para obtener una rápida referencia de los mensajes arrojados por Pylint, organizados de varias maneras para hacer más fácil y agradable la búsqueda. Además de encontrar explicaciones de cada mensaje, especialmente útiles para aquellos programadores que recién comienzan en Python.

Referencias

4 min read

Consideraciones para el envío de cambios en Subversion

Hoy día pareciese que los sistemas de control de versiones centralizados están pasando de moda ante la aparición de sistemas de control de versiones descentralizados poderosos como Git, del cual espero poder escribir en próximos artículos. Sin embargo, puede que la adopción de estos sistemas descentralizados tarden en controlar el mundo de los SCM, al menos por ahora las métricas de ohloh.net indican que Subversion sigue siendo bastante empleado, mayor detalle en el artículo Subversion - As Strong As Ever.

En este artículo se expondrán algunas políticas que suelen definirse para la sana convivencia entre colaboradores de un proyecto de desarrollo de software, estas reglas no solo aplican a Subversion en particular, son de uso común en otros sistemas de control de versiones centralizados.

Analice bien los cambios hechos antes de enviarlos

Cualquier cambio en la línea base de su proyecto puede traer consecuencias, tome en cuenta que los demás desarrolladores obtendrán sus cambios una vez que estén en el repositorio centralizado. Si usted no se preocupó por validar que todo funcionara correctamente antes de enviar sus cambios, es probable que algún compañero le recrimine por su irresponsabilidad, esto afecta de cierta forma el anillo de confianza entre los colaboradores del proyecto.

Nunca envíe cambios que hagan fallar la construcción del proyecto

Siempre verifique que su proyecto compile, si el proyecto presenta errores debido a los cambios hechos por usted atiendalos inmediatamente, evite los errores de sintaxis, tenga siempre presente respetar las políticas de estilo de código definidas para su proyecto.

Si ha ingresado nuevos ficheros o directorios al proyecto recuerde ejecutar el comando svn add para programar la adición en Subversion, si omite este paso es posible que su copia de trabajo funcione o compile, pero la del resto de sus compañeros no, evite de nuevo ser recriminado por los demás colaboradores del proyecto.

Si su proyecto pretende ser multiplataforma, trate de imaginar las consecuencias de sus cambios bajo otro sistema operativo o arquitectura. Por ejemplo, he visto más de una vez este tipo de error:

path = "dir/subdir/fichero.txt" # Malo
path = os.path.join(os.path.dirname(__file__), 'dir', 'subdir', 'fichero.txt') # Correcto

Pruebe los cambios antes de hacer el envío

Antes de realizar un envío al repositorio centralizado actualice su copia de trabajo (svn up), verifique que las pruebas unitarias, regresión de su proyecto arrojan resultados positivos, de igual manera haga pruebas funcionales del sistema.

Al momento de hacer la actualización de su copia de trabajo tome nota de los ficheros editados por los demás colaboradores del proyecto, verifique que no existan conflictos, nuevos ficheros que no haya considerado, entre otros. Una vez que haya solventado la actualización de su copia de trabajo, construya (su proyecto tiene un sistema de autoconstrucción, ¿verdad?) el paquete, inicie su aplicación que contiene los cambios locales y asegúrese que el comportamiento obtenido sea igual al esperado.

Promueva un histórico de cambios descriptivo

El histórico de cambios debe ser comprensible por cualquier colaborador del proyecto solamente con la información suministrada en dicho registro, evite depender de información fuera del contexto del envío de cambios. Se le recomienda colocar toda la información importante que no pueda obtenerse a partir de un svn diff del código fuente.

¿Está corrigiendo un error?

Si usted está reparando un error en la aplicación que se encuentra presente en la rama principal de desarrollo (trunk), considere seriamente portar esa reparación a otras ramas de desarrollo (branches) en el caso que su proyecto posea una versión estable que requiere actualmente de mantenimiento. Trate en lo posible de aprovechar el mismo commit para enviar la corrección de la rama principal de desarrollo (trunk) y las ramas de mantenimiento.

Si el error fue reportado a través del sistema de seguimiento de errores (usted mantiene un sistema de seguimiento de errores, ¿verdad?), agregue en el registro del mensaje de envío el número del ticket, boleto o reporte que usted está atendiendo. Seguidamente proceda a cerrar el ticket o boleto en el sistema de seguimiento de errores.

No agregue ficheros generados por otras herramientas al repositorio

No agregue ficheros innecesarios al repositorio, el origen de estos ficheros suele ser:

  • Proceso de autoconstrucción (Ej. distutils, autotools, scons, entre otros).
  • Herramientas de verificación de calidad del código (Ej. PyLint, CppLint, entre otros).
  • Herramientas para generar documentación (Ej. Doxygen, Sphinx, entre otros).

Estos ficheros generados por otras herramientas no es necesario versionarlos, puede considerarlos cache, este tipo de datos son localmente generados como resultado de operaciones I/O o cálculos, las herramientas deben ser capaces de regenerar o restaurar estos datos a partir del código presente en el repositorio central.

Realice envíos atómicos

Recuerde que SVN le brinda la posibilidad de enviar más de un fichero en un solo commit. Por lo tanto, envíe todos los cambios relacionados en múltiples ficheros, incluso si los cambios se extienden a lo largo de varios directorios en un mismo commit. De esta manera, se logra que SVN se mantenga en un estado compatible antes y después del commit.

Recuerde asegurarse al enviar un cambio al repositorio central reflejar un solo propósito, el cual puede ser la corrección de un error de programación o bug, agregar una nueva funcionalidad al sistema, ajustes de estilo del código o alguna tarea adicional.

Separe los ajustes de formato de código de otros envíos

Ajustar el formato del código, como la sangría, los espacios en blanco, el largo de la línea incrementa considerablemente los resultados del diff, si usted mezcla los cambios asociados al ajuste de formato de código con otros estará dificultando un posterior análisis al realizar un svn diff.

Haga uso intensivo de la herramienta de seguimiento de errores

Trate en lo posible de crear enlaces bidireccionales entre el conjunto de cambios hechos en el repositorio de subversion y la herramienta de seguimientos de errores tanto como sea posible.

  • Trate de hacer una referencia al id o número del ticket al cual está dando solución desde su mensaje de registro o log previo a realizar el commit.
  • Cuando agregue información o responda a un ticket, ya sea para describir su avance o simplemente para cerrar el ticket, indique el número o números de revisión que atienden o responden a dichos cambios.

Indique en el registro de envío el resultado del merge

Cuando usted está enviando el resultado de un merge, asegúrese de indicar sus acciones en el registro de envío, tanto aquello que fue fusionado como los números de revisiones que fueron tomadas en cuenta. Ejemplo:

Fusión de las revisiones 10:40 de /branches/foo a /trunk.

Tenga claro cuando es oportuno crear una rama

Esto es un tema polémico. Sin embargo, dependiendo del proyecto en el que esté involucrado usted puede definir una estrategia o mezcla de ellas para manejar el desarrollo del proyecto. Generalmente puede encontrar lo siguiente:

Los proyectos que requieren un alto manejo y supervisión recurren a estrategias de siempre crear ramas, acá puede encontrarse que cada colaborador crea o trabaja en una rama privada para cada tarea de codificación. Cuando el trabajo individual ha finalizado, algún responsable, ya sea el fundador del proyecto, un revisor técnico, analiza los cambios hechos por el colaborador y hace la fusión con la línea principal de desarrollo. En estos casos la rama principal de desarrollo suele ser bastante estable. Sin embargo, este modo de trabajo conlleva normalmente a crear mayores conflictos en la etapa de fusión o merge, además, las labores de fusión bajo este esquema son constantemente requeridas.

Existe otro enfoque que permite mantener una línea base de desarrollo estable, el cual consiste en crear ramas de desarrollo solo cuando se ameritan. Sin embargo, esto requiere que los colaboradores tengan mayor dominio del uso de Subversion y una constante comunicación entre ellos. Además de aumentar el número de pruebas antes de cada envío al repositorio centralizado.

Estudie, analice las distintas opciones y defina un método para la creación de ramas en su proyecto. Una vez definido, es sumamente importante que cada colaborador tenga clara esta estrategia de trabajo.

Las estrategias antes mencionadas y otras más pueden verse en detalle en:

Los sistemas de control de versiones no substituyen la comunicación entre los colaboradores

Por último pero no menos importante, los sistemas de control de versiones no substituyen la comunicación entre los desarrolladores o colaboradores del proyecto de software. Cuando usted tenga planes de hacer un cambio que pueda afectar una cantidad de código considerable en su proyecto, establezca un control de cambios, haga un análisis de las posibles consecuencias o impacto de los mismos, difunda esta información a través de una lista de discusión (usted mantiene una lista de discusión para desarrolladores, ¿verdad?) y espere la respuesta, preocupaciones, sugerencias de los demás colaboradores, quizá juntos se encuentre un modo más eficaz de aplicar los cambios.

Referencias:

7 min read

Configurando nuestras interfaces de red con ifupdown

Si usted es de esas personas que suele mover su máquina portátil entre varias redes que no necesariamente proveen DHCP y usualmente vuelve a configurar sus preferencias de conexión, seguramente este artículo llame su atención puesto que se explicará acerca de la configuración de diversos perfiles de conexión vía línea de comandos.

En los sistemas Debian y los basados en él, Ubuntu por ejemplo, para lograr la configuración de las redes existe una herramienta de alto nivel que consiste en los comandos ifup e ifdown, adicionalmente se cuenta con el fichero de configuración /etc/network/interfaces. También el paquete wireless-tools incluye un script en /etc/network/if-pre-up.d/wireless-tools que hace posible preparar el hardware de la interfaz inalámbrica antes de darla de alta, dicha configuración se hace a través del comando iwconfig.

Para hacer uso de las ventajas que nos ofrece la herramienta de alto nivel ifupdown, en primer lugar debemos editar el fichero /etc/network/interfaces y establecer nuestros perfiles de la siguiente manera:

auto lo
iface lo inet loopback

# Conexión en casa usando WPA
iface home inet dhcp
    wpa-driver wext
    wpa-ssid foo
    wpa-psk baz
    wpa-keymgmt WPA-PSK
    wpa-pairwise TKIP CCMP
    wpa-group TKIP CCMP
    wpa-proto WPA RSN

# Conexión en la oficina
# sin DHCP
iface office inet static
    wireless-essid bar
    wireless-key s:egg
    address 192.168.1.97
    netmask 255.255.255.0
    broadcast 192.168.1.255
    gateway 192.168.1.1
    dns-search company.com #[email protected]
    dns-nameservers 192.168.1.2 192.168.1.3 #[email protected]

# Conexión en reuniones
iface meeting inet dhcp
	wireless-essid ham
	wireless-key s:jam

En este ejemplo se encuentran 3 configuraciones particulares (home, work y meeting), la primera de ellas define que nos vamos a conectar con un Access Point cuyo ssid es foo con un tipo de cifrado WPA-PSK/WPA2-PSK, esto fue explicado en detalle en el artículo Haciendo el cambio de ipw3945 a iwl3945. La segunda configuración indica que nos vamos a conectar a un Access Point con una IP estática y configuramos los parámetros search y nameserver del fichero /etc/resolv.conf (para más detalle lea la documentación del paquete resolvconf). Finalmente se define una configuración similar a la anterior, pero en este caso haciendo uso de DHCP.

Llegados a este punto es importante aclarar lo que ifupdown considera una interfaz lógica y una interfaz física. La interfaz lógica es un valor que puede ser asignado a los parámetros de una interfaz física, en nuestro caso home, office, meeting. Mientras que la interfaz física es lo que propiamente conocemos como la interfaz, en otras palabras, lo que regularmente el kernel reconoce como eth0, wlan0, ath0, ppp0, entre otros.

Como puede verse en el ejemplo previo las definiciones adyacentes a iface hacen referencia a interfaces lógicas, no a interfaces físicas.

Ahora bien, para dar de alta la interfaz física wlan0 haciendo uso de la interfaz lógica home, como superusuario puede hacer lo siguiente:

# ifup wlan0=home

Si usted ahora necesita reconfigurar la interfaz física wlan0, pero en este caso particular haciendo uso de la interfaz lógica work, primero debe dar de baja la interfaz física wlan0 de la siguiente manera:

# ifdown wlan0

Seguidamente deberá ejecutar el siguiente comando:

# ifup wlan0=work

Es importante hacer notar que tal como está definido ahora el fichero /etc/network/interfaces ya no es posible dar de alta la interfaz física wlan0 ejecutando solamente lo siguiente:

ifup wlan0

La razón de este comportamiento es que el comando ifup utiliza el nombre de la interfaz física como el nombre de la interfaz lógica por omisión y evidentemente ahora no está definido en el ejemplo un nombre de interfaz lógica igual a wlan0.

En un próximo artículo se harán mejoras en la definición del fichero /etc/network/interfaces y su respectiva integración con una herramienta para la detección de redes que tome como entrada una lista de perfiles de redes candidatas, cada una de ellas incluyendo casos de pruebas. Teniendo esto como entrada ya no será necesario indicar la interfaz lógica a la que se hace referencia ya que la herramienta se encargará de probar todos los perfiles en paralelo y elegirá aquella que cumpla en primera instancia con los casos de prueba. De modo tal que ya podremos dar de alta nuestra interfaz física con solo hacer ifup wlan0.

3 min read

subversion: Recuperar cambios y eliminaciones hechas

Muchos compañeros de trabajo y amigos en general que recién comienzan con el manejo de sistemas de control de versiones centralizados, en particular subversion, regularmente tienen inquietudes en cuanto al proceso de recuperación de cambios una vez que han sido enviados al repositorio, así como también la recuperación de ficheros y directorios que fueron eliminados en el pasado. Trataré de explicar algunos casos en base a ejemplos para que se tenga una idea más clara del problema y su respectiva solución.

En el primero de los casos se tiene recuperar la revisión previa a la actual, suponga que usted mantiene un repositorio de recetas, una de ellas en particular es la ensalada caprese, por error o descuido añadió el ingrediente Mostaza tipo Dijón a la lista, si usted posee siquiera un lazo con italinos sabe que está cometiendo un error que puede devenir en escarnio público, desprecio e insultos.

~/svn/wc/trunk$ svn diff -r 2:3 ${URL}/trunk/caprese
Index: caprese
===================================================================
--- caprese	(revision 2)
+++ caprese	(revision 3)
@@ -7,3 +7,4 @@
  - Albahaca fresca
  - Aceite de oliva
  - Pimienta
+ - Mostaza tipo Dijon

Note que el comando anterior muestra las diferencias entre las revisiones 2 y 3 del repositorio, en el resumen se puede apreciar que en la revisión 3 ocurrió el error. Un modo rápido de recuperarlo es como sigue.

~/svn/wc/trunk$ svn merge -c -3 ${URL}/trunk/caprese
--- Reverse-merging r3 into 'caprese':
U    caprese

En este caso particular se están aplicando las diferencias entre las revisiones consecutivas a la copia de trabajo. Es hora de verificar que los cambios hechos sean los deseados:

~/svn/wc/trunk$ svn status
M      caprese
~/svn/wc/trunk$ svn diff
Index: caprese
===================================================================
--- caprese	(revision 3)
+++ caprese	(working copy)
@@ -7,4 +7,3 @@
  - Albahaca fresca
  - Aceite de oliva
  - Pimienta
- - Mostaza tipo Dijon

Una vez verificado enviamos los cambios hechos al repositorio a través de comando svn commit.

Seguramente usted se estará preguntando ahora que sucede si las revisiones del ficheros no son consecutivas como en el caso mostrado previamente. En este caso es importante hacer notar que la opción -c 3 es equivalente a -r 2:3 al usar el comando svn merge, en nuestro caso particular -c -3 es equivalente a -r 3:2 (a esto se conoce como una fusión reversa), substituyendo la opción -c (o --changes) en el caso previo obtenemos lo siguiente:

~/svn-tests/wc/trunk$ svn merge -r 3:2 ${URL}/trunk/caprese
--- Reverse-merging r3 into 'caprese':
U    caprese

Referencias: svn help merge, svn help diff, svn help status.

Recuperando ficheros o directorios eliminados

Una manera bastante sencilla de recuperar ficheros o directorios eliminados es haciendo uso de comando svn cp o svn copy, una vez determinada la revisión del fichero o directorio que desea recuperar la tarea es realmente sencilla:

~/svn-tests/wc/trunk$ svn cp ${URL}/trunk/panzanella@6 panzanella
A         panzanella

En este caso se ha duplicado la revisión 6 del fichero panzanella en la copia de trabajo local, se ha programado para su adición incluyendo su historial, esto último puede verificarse en detalle al observar el signo ’+’ en la cuarta columna del comando svn status.

~/svn-tests/wc/trunk$ svn status
A  +   panzanella

Referencias: svn help copy, svn help status.

2 min read