Pregunta

¿Hay alguien que tenga instrucciones claras sobre cómo agregar un enlace previo al compromiso que evite cambios en los subdirectorios de etiquetas?

Ya busqué bastante en Internet. Encontré este enlace: SVN :: Hooks :: DenyChanges , pero puedo ' Parece que compila cosas.

¿Fue útil?

Solución

No tengo suficiente reputación para " comentar " en la respuesta de Raim anterior, pero funcionó muy bien, con una excepción, su patrón grep está mal.

Simplemente utilicé el siguiente como mi gancho previo a la confirmación (no tenía uno existente, en ese caso necesitaría fusionarlo):

#!/bin/sh

REPOS="$1"
TXN="$2"

SVNLOOK=/opt/local/bin/svnlook

# Committing to tags is not allowed
$SVNLOOK changed -t "$TXN" "$REPOS" | grep "^U\W.*\/tags\/" && /bin/echo "Cannot commit to tags!" 1>&2 && exit 1

# All checks passed, so allow the commit.
exit 0

El único problema con el patrón grep de Raim es que solo coincidía con " tags " si estaba en la raíz "" de tu repositorio. Como tengo varios proyectos en mi repositorio, el script tal como lo escribió permitió confirmaciones en las ramas de etiquetas.

Además, asegúrese de hacer chmod + x como se indica, de lo contrario pensará que funcionó porque el compromiso falló, pero falló b / c no pudo ejecutar el enlace previo al compromiso, no porque el enlace funcionó .

Esto fue realmente genial, gracias Raim. ¡Mucho mejor y más liviano que todas las demás sugerencias ya que no tiene dependencias!

Otros consejos

Aquí hay un breve script de shell para evitar comprometerse con las etiquetas después de que se hayan creado:

#!/bin/sh

REPOS="$1"
TXN="$2"

SVNLOOK=/usr/bin/svnlook

# Committing to tags is not allowed
$SVNLOOK changed -t "$TXN" "$REPOS" | grep "^U\W*tags" && /bin/echo "Cannot commit to tags!" 1>&2 && exit 1

# All checks passed, so allow the commit.
exit 0

Guarde esto en hooks / pre-commit para su repositorio de Subversion y hágalo ejecutable con chmod + x .

Aquí está mi gancho de confirmación previa de archivo por lotes de Windows. Si el usuario es administrador, se omitirán las otras verificaciones. Comprueba si el mensaje de confirmación está vacío y si la confirmación es para una etiqueta. Nota: FindStr es una alternativa nerfed a grep en otras plataformas.

La forma en que comprueba si la confirmación es a una etiqueta, primero comprueba si svnlook cambiado contiene " etiquetas / " ;. Luego comprueba si svnlook cambió coincide '' ^ A. tags / [^ /] / $ " ;, lo que significa que verificará si está agregando una nueva carpeta en las etiquetas /.

Los usuarios pueden crear nuevos proyectos. El enlace previo a la confirmación permite al usuario crear las carpetas troncal / etiquetas / y ramas /. Los usuarios no pueden eliminar las carpetas troncal / etiquetas / y ramas /. Esto funcionará para un repositorio único o multiproyecto.

 @echo off
 rem This pre-commit hook will block commits with no log messages and blocks commits on tags.
 rem Users may create tags, but not modify them.
 rem If the user is an Administrator the commit will succeed.

 rem Specify the username of the repository administrator
 rem commits by this user are not checked for comments or tags
 rem Recommended to change the Administrator only when an admin commit is neccessary
 rem then reset the Administrator after the admin commit is complete
 rem this way the admin user is only an administrator when neccessary
 set Administrator=Administrator

 setlocal

 rem Subversion sends through the path to the repository and transaction id.
 set REPOS=%1%
 set TXN=%2%

 :Main
 rem check if the user is an Administrator
 svnlook author %REPOS% -t %TXN% | findstr /r "^%Administrator%<*>quot; >nul
 if %errorlevel%==0 (exit 0)

 rem Check if the commit has an empty log message
 svnlook log %REPOS% -t %TXN% | findstr . > nul
 if %errorlevel% gtr 0 (goto CommentError)

 rem Block deletion of branches and trunk
 svnlook changed %REPOS% -t %TXN% | findstr /r "^D.*trunk/$ ^D.*branches/<*>quot; >nul
 if %errorlevel%==0 (goto DeleteBranchTrunkError)

 rem Check if the commit is to a tag
 svnlook changed %REPOS% -t %TXN% | findstr /r "^.*tags/" >nul
 if %errorlevel%==0 (goto TagCommit)
 exit 0

 :DeleteBranchTrunkError
 echo. 1>&2
 echo Trunk/Branch Delete Error: 1>&2
 echo     Only an Administrator may delete the branches or the trunk. 1>&2
 echo Commit details: 1>&2
 svnlook changed %REPOS% -t %TXN% 1>&2
 exit 1

 :TagCommit
 rem Check if the commit is creating a subdirectory under tags/ (tags/v1.0.0.1)
 svnlook changed %REPOS% -t %TXN% | findstr /r "^A.*tags/[^/]*/<*>quot; >nul
 if %errorlevel% gtr 0 (goto CheckCreatingTags)
 exit 0

 :CheckCreatingTags
 rem Check if the commit is creating a tags/ directory
 svnlook changed %REPOS% -t %TXN% | findstr /r "^A.*tags/<*>quot; >nul
 if %errorlevel% == 0 (exit 0)
 goto TagsCommitError

 :CommentError
 echo. 1>&2
 echo Comment Error: 1>&2
 echo     Your commit has been blocked because you didn't enter a comment. 1>&2
 echo     Write a log message describing your changes and try again. 1>&2
 exit 1

 :TagsCommitError
 echo. 1>&2
 echo %cd% 1>&2
 echo Tags Commit Error: 1>&2
 echo     Your commit to a tag has been blocked. 1>&2
 echo     You are only allowed to create tags. 1>&2
 echo     Tags may only be modified by an Administrator. 1>&2
 echo Commit details: 1>&2
 svnlook changed %REPOS% -t %TXN% 1>&2
 exit 1

Esta respuesta es mucho después de la fecha, pero descubrí el parámetro --copy-info para el comando cambiado svnlook.

El resultado de este comando agrega un '+' en la tercera columna, para que sepa que es una copia. Puede verificar las confirmaciones en el directorio de etiquetas y solo permitir confirmaciones con un '+' presente.

He agregado algunos resultados en mi publicación de blog .

Bastante tarde para la fiesta, sin embargo, escribí un enlace de precompromiso de Python para el trabajo que se basa en el script log-police.py en http://subversion.tigris.org/ .

Este script debe hacer lo que desee, sin embargo, también verifica que exista un mensaje de registro, aunque debería ser fácil de eliminar del script.

Algunas advertencias:

  • Soy nuevo en Python, por lo que probablemente podría escribirse mejor
  • Solo se ha probado en Windows 2003 con Python 2.5 y Subversion 1.4.

Requisitos:

  • Subversion
  • Python
  • Enlaces de Subversion para Python

Finalmente, el código:

#!/usr/bin/env python

#
# pre-commit.py:
#
# Performs the following:
#  - Makes sure the author has entered in a log message.
#  - Make sure author is only creating a tag, or if deleting a tag, author is a specific user
#
# Script based on http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/log-police.py
#
# usage: pre-commit.py -t TXN_NAME REPOS
# E.g. in pre-commit.bat (under Windows)
#   python.exe {common_hooks_dir}\pre_commit.py -t %2 %1
#


import os
import sys
import getopt
try:
  my_getopt = getopt.gnu_getopt
except AttributeError:
  my_getopt = getopt.getopt

import re

import svn
import svn.fs
import svn.repos
import svn.core

#
# Check Tags functionality
#
def check_for_tags(txn):
  txn_root = svn.fs.svn_fs_txn_root(txn)
  changed_paths = svn.fs.paths_changed(txn_root)
  for path, change in changed_paths.iteritems():
    if is_path_within_a_tag(path): # else go to next path
      if is_path_a_tag(path):
        if (change.change_kind == svn.fs.path_change_delete):
          if not is_txn_author_allowed_to_delete(txn):
            sys.stderr.write("\nOnly an administrator can delete a tag.\n\nContact your Subversion Administrator for details.")
            return False
        elif (change.change_kind != svn.fs.path_change_add):
          sys.stderr.write("\nUnable to modify " + path + ".\n\nIt is within a tag and tags are read-only.\n\nContact your Subversion Administrator for details.")
          return False
        # else user is adding a tag, so accept this change
      else:
        sys.stderr.write("\nUnable to modify " + path + ".\n\nIt is within a tag and tags are read-only.\n\nContact your Subversion Administrator for details.")
        return False
  return True

def is_path_within_a_tag(path):
  return re.search('(?i)\/tags\/', path)

def is_path_a_tag(path):
  return re.search('(?i)\/tags\/[^\/]+\/?, path)

def is_txn_author_allowed_to_delete(txn):
  author = get_txn_property(txn, 'svn:author')
  return (author == 'bob.smith')

#
# Check log message functionality
#
def check_log_message(txn):
  log_message = get_txn_property(txn, "svn:log")
  if log_message is None or log_message.strip() == "":
    sys.stderr.write("\nCannot enter in empty commit message.\n")
    return False
  else:
    return True

def get_txn_property(txn, prop_name):
  return svn.fs.svn_fs_txn_prop(txn, prop_name)

def usage_and_exit(error_msg=None):
  import os.path
  stream = error_msg and sys.stderr or sys.stdout
  if error_msg:
    stream.write("ERROR: %s\n\n" % error_msg)
  stream.write("USAGE: %s -t TXN_NAME REPOS\n"
               % (os.path.basename(sys.argv[0])))
  sys.exit(error_msg and 1 or 0)

def main(ignored_pool, argv):
  repos_path = None
  txn_name = None

  try:
    opts, args = my_getopt(argv[1:], 't:h?', ["help"])
  except:
    usage_and_exit("problem processing arguments / options.")
  for opt, value in opts:
    if opt == '--help' or opt == '-h' or opt == '-?':
      usage_and_exit()
    elif opt == '-t':
      txn_name = value
    else:
      usage_and_exit("unknown option '%s'." % opt)

  if txn_name is None:
    usage_and_exit("must provide -t argument")
  if len(args) != 1:
    usage_and_exit("only one argument allowed (the repository).")

  repos_path = svn.core.svn_path_canonicalize(args[0])

  fs = svn.repos.svn_repos_fs(svn.repos.svn_repos_open(repos_path))
  txn = svn.fs.svn_fs_open_txn(fs, txn_name)

  if check_log_message(txn) and check_for_tags(txn):
    sys.exit(0)
  else:
    sys.exit(1)

if __name__ == '__main__':
  sys.exit(svn.core.run_app(main, sys.argv))

La mayoría de los scripts escritos anteriormente están incompletos porque varios casos no están cubiertos. Este es mi script:

contains_tags_dir=`$SVNLOOK changed --copy-info -t "$TXN" "$REPOS" | head -1 | egrep "+\/tags\/.*<*>quot; | wc -l | sed "s/ //g"`

if [ $contains_tags_dir -gt 0 ]
then
  tags_dir_creation=`$SVNLOOK changed --copy-info -t "$TXN" "$REPOS" | head -1 | egrep "^A       .+\/tags\/<*>quot; | wc -l | sed "s/ //g"`
  if [ $tags_dir_creation -ne 1 ]
  then
    initial_add=`$SVNLOOK changed --copy-info -t "$TXN" "$REPOS" | head -1 | egrep "^A \+ .+\/tags\/.+\/<*>quot; | wc -l | sed "s/ //g"`
    if [ $initial_add -ne 1 ]
    then
      echo "Tags cannot be changed!" 1>&2
      exit 1
    fi
  fi
fi

Puede parecer complicado, pero debe asegurarse de estar en / tags y se le permite crear / tags si no existe y todas las carpetas posteriores. Cualquier otro cambio está bloqueado. Casi ninguno de los scripts anteriores cubre todos los casos descritos en el libro de Subversion para svnlook cambiado ... .

La respuesta aceptada evita la actualización de archivos en una etiqueta pero no impide agregar archivos a una etiqueta. La siguiente versión maneja ambos:

#!/bin/sh

REPOS="$1"
TXN="$2"
SVNLOOK="/home/staging/thirdparty/subversion-1.6.17/bin/svnlook"

# Committing to tags is not allowed
$SVNLOOK changed -t "$TXN" "$REPOS" --copy-info| grep -v "^ " | grep -P '^[AU]   \w+/tags/' && /bin/echo "Cannot update tags!" 1>&2 && exit 1

# All checks passed, so allow the commit.
exit 0

Mi versión solo permite crear y eliminar etiquetas. Esto debería manejar todos los casos especiales (como agregar archivos, cambiar propiedades, etc.).

#!/bin/sh

REPOS="$1"
TXN="$2"
SVNLOOK=/usr/local/bin/svnlook

output_error_and_exit() {
    echo "$1" >&2
    exit 1
}

changed_tags=$( $SVNLOOK changed -t "$TXN" "$REPOS" | grep "[ /]tags/." )

if [ "$changed_tags" ]
then 
    echo "$changed_tags" | egrep -v "^[AD] +(.*/)?tags/[^/]+/<*>quot; && output_error_and_exit "Modification of tags is not allowed."
fi 

exit 0

Si está utilizando JIRA, puede usar el complemento llamado Política de compromiso para proteger las rutas en su repositorio sin escribir enlaces personalizados .

¿Cómo? Use la condición llamada Modificado los archivos deben coincidir con un patrón .

Tiene un argumento de tipo de expresión regular que debe coincidir para cada archivo en una confirmación; de lo contrario, la confirmación se rechaza. Entonces, en su caso, debe usar una expresión regular que significa que "no comienza con el prefijo / etiquetas /".

(Puede implementar muchas otras comprobaciones inteligentes con el mismo complemento).

Descargo de responsabilidad: soy un desarrollador que trabaja en este complemento pago.

Dado que la primera respuesta no impidió agregar / suprimir archivos, e impidió la creación de nuevas etiquetas, y muchos otros donde estaban incompletos o con errores, lo reelaboré

Aquí está mi gancho previo a la confirmación: Los objetivos son:

  • No permitir confirmaciones en etiquetas (adición / supresión / actualizaciones de archivos)
  • No impida la creación de etiquetas

--------- archivo " pre-commit " (poner en la carpeta ganchos de repositorios) ---------

#!/bin/sh

REPOS="$1"
TXN="$2"

SVNLOOK=/usr/bin/svnlook

#Logs
#$SVNLOOK changed -t "$TXN" "$REPOS" > /tmp/changes
#echo "$TXN" > /tmp/txn
#echo "$REPOS" > /tmp/repos

# Committing to tags is not allowed
# Forbidden changes are Update/Add/Delete.  /W = non alphanum char  Redirect is necessary to get the error message, since regular output is lost.
# BUT, we must allow tag creation / suppression

$SVNLOOK changed -t "$TXN" "$REPOS" | /bin/grep "^A\W.*tags\/[0-9._-]*\/." && /bin/echo "Commit to tags are NOT allowed ! (Admin custom rule)" 1>&2 && exit 101
$SVNLOOK changed -t "$TXN" "$REPOS" | /bin/grep "^U\W.*tags\/[0-9._-]*\/." && /bin/echo "Commit to tags are NOT allowed ! (Admin custom rule)" 1>&2 && exit 102
$SVNLOOK changed -t "$TXN" "$REPOS" | /bin/grep "^D\W.*tags\/[0-9._-]*\/." && /bin/echo "Commit to tags are NOT allowed ! (Admin custom rule)" 1>&2 && exit 104

# All checks passed, so allow the commit.
exit 0;

--------- fin del archivo " pre-commit " ---------

Además, hice 2 scripts de shell para copiar mi gancho en cada proyecto de mi svn: Uno para establecer un repositorio de solo lectura:

--------- script " setOneRepoTagsReadOnly.sh " ---------

#!/bin/sh

cd /var/svn/repos/svn
zeFileName=$1/hooks/pre-commit
/bin/cp ./CUSTOM_HOOKS/pre-commit $zeFileName
chown www-data:www-data $zeFileName
chmod +x $zeFileName

--------- fin del archivo '' setOneRepoTagsReadOnly.sh '' ---------

Y uno lo llama para cada repositorio, para que todos mis repositorios sean de solo lectura:

--------- archivo " makeTagsReadOnly.sh " ---------

#!/bin/shs/svn                                                                                                                                                                         
#Lists all repos, and adds the pre-commit hook to protect tags on each of them
find /var/svn/repos/svn/ -maxdepth 1 -mindepth 1 -type d -execdir '/var/svn/repos/svn/setOneRepoTagsReadOnly.sh' \{\} \;

--------- fin del archivo " makeTagsReadOnly.sh " ---------

Ejecuto estos scripts directamente desde el svn " root " (/ var / svn / repos / svn, en mi caso). Por cierto, una tarea cron podría configurarse para modificar automáticamente nuevos repositorios ejecutando estos scripts diariamente

Espero que ayude.

Las respuestas enumeradas son geniales, pero ninguna hizo exactamente lo que necesito. Quiero permitir la creación de etiquetas fácilmente, pero una vez que se creen, deberían ser de solo lectura.

También quiero evitar la estúpida situación en la que si haces esto:

svn copy myrepo/trunk myrepo/tags/newrelease

Todo está bien la primera vez. Pero la segunda vez, si la etiqueta ya existe, terminará con myrepo / tags / newrelease / trunk .

Mi enlace de confirmación previa buscará cualquier directorio SVN preexistente que coincida con (repo) / tags / (tag) / y fallará si se encuentra:

$SVNLOOK tree -N --full-paths "$REPOS" "`$SVNLOOK changed -t "$TXN" "$REPOS" \
  | sed 's/[A-Z][[:space:]]*\([^/]*\)\/tags\/\([^/]*\)\/.*/\1\/tags\/\2\//' \
  | head -n 1`" \
  && echo "Tag already exists, commit rejected." >&2 \
  && exit 1
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top