Hace ya un par de años que me convertí en el administrador del repositorio de subversion de nuestro departamento. Incluso prestamos servicio de subversion a otros departamentos para sus proyectos.
Uno de los problemas que me he encontrado es que la gente por despiste, por "pasotismo" o por no saber dónde guardar las cosas, mete en subversion ficheros binarios (.exe, .dll, etc) documentos (.doc, .docx, .pdf), etc, etc que no es el sitio adecuado para guardarlos, además que abusar de ello puede llenar el disco en un pis-pas. Y no es un problema específico de un administrador de subversion, pero tampoco me gusta que la gente suba a subversion sin poner el correspondiente comentario en el commit.
Así que me puse a investigar cómo evitarlo y descubrí los "hooks" de subversion. Son scripts que se guardan en el servidor y que se ejecutan cuando ocurren ciertas acciones en subversion, como un commit, un bloqueo, etc.
En el directorio /path/REPOSITORIO_SVN/hooks de un proyecto basta con poner un script de nombre pre-commit.bat (en windows también vale un pre-commit.exe o pre-commit.com, para unix bastaría un fichero de nombre pre-commit, sin extensión, con permisos de ejecución) que se ejecutará siempre que se intente hacer un commit y se ejecutará antes del commit, pudiendo rechazarlo en un momento dado. Ese directorio ya está lleno de scripts con extensión .tmpl, no ejecutables por tanto. Cada uno corresponde a uno de los posibles "hooks" y nos bastaría con copiarlo poniendo extensión .bat (o dándole permisos de ejecución en linux) y modificarlo por dentro para que haga lo que queramos.
Este script debe salir de forma normal (exit 0) si el commit se acepta, y salir con error (exit 1) si no se acepta el commit. En este último caso, lo que el script saque por la salida de error estándar, será lo que subversion le muestre al usuario como mensaje de error.
El que yo he puesto, pre-commit.bat, verifica las extensiones de los ficheros que se quieren subir y verifica que hay un comentario. El script es el siguiente y me disculpareis si hay forma mejor de hacerlo (seguro que la hay), pero se más bien nada de "scripts" en windows.
set REPOS=%1set TXN=%2svnlook changed %REPOS% -t %TXN% | findstr ".\exe \.dll \.o \.lib \.a \.so \.jar \.class \.doc \.docx \.pdf \.zip" >&2if %errorlevel% equ 0 (goto err)svnlook log %REPOS% -t %TXN% | findstr . > nulif %errorlevel% gtr 0 (goto err2)exit 0:errecho No se admiten ficheros binarios >&2exit 1:err2echo Como no metas un comentario …. >&2exit 1
Como parámetros del script, subversion nos pasará el repositorio y una "cosa extraña" que contiene la información de lo que se está pretendiendo meter. Nos guardamos esos dos parámetros %1 y %2 en las variables REPOS y TXN.
El comando de subversion svnlook, pasándole estas dos cosas, es capaz de darnos información sobre el commit. Así, svnlook changed nos da un listado de los ficheros que se pretenden modificar/añadir/borrar. svnlook log nos da el comentario del commit.
El comando findstr de windows nos permite buscar una cadena. En el primer uso buscamos extensiones de ficheros no permitidos. En el segundo caso, buscamos cualquier caracter (el punto de findstr equivale a cualquier caracter). Este comando findstr da un error si no encuentra la cadena, por lo que inmediatamente detrás pongo un if de %errorlevel% (que es donde se guarda si ha habido error) para decidir si se acepta el commit (exit 0) o saco algún error.
En fin, las posibilidades serían muchas, como verificar si el comentario lleva un número de incidencia para admitirlo, analizar el contenido del fichero que se va a meter buscando cosas no permitidas (código sin comentar, que no cumpla métricas, paths absolutos dentro, etc) o incluso ¿por qué no? si compila o no compila y pasa los test.