Domanda

C'è qualcuno che ha chiare istruzioni su come aggiungere un hook pre-commit che evita le modifiche alle sottodirectory dei tag?

Ho già cercato un po 'su Internet. Ho trovato questo link: SVN :: Hooks :: DenyChanges , ma posso ' sembra compilare le cose.

È stato utile?

Soluzione

Non ho abbastanza reputazione per " commentare " sulla risposta di Raim sopra, ma ha funzionato alla grande, con una sola eccezione, il suo modello grep è sbagliato.

Ho semplicemente usato il seguito come hook pre-commit (non ne avevo uno esistente, in quel caso avresti dovuto unirlo):

#!/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

L'unico problema con il modello grep di Raim è che corrispondeva solo a " tag " se fosse nella "radice" del tuo repository. Dal momento che ho diversi progetti nel mio repository, la sceneggiatura mentre scriveva mi ha permesso di eseguire il commit su tag branch.

Inoltre, assicurati di chmod + x come indicato, altrimenti penserai che abbia funzionato b / c il commit non è riuscito, ma ha fallito b / c non potrebbe eseguire l'hook pre-commit, non perché l'hook ha funzionato .

È stato davvero fantastico, grazie Raim. Peso molto migliore e più leggero di tutti gli altri suggerimenti in quanto non ha dipendenze!

Altri suggerimenti

Ecco uno script di shell corta per impedire il commit dei tag dopo che sono stati creati:

#!/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

Salva questo in hook / pre-commit per il tuo repository Subversion e rendilo eseguibile con chmod + x .

Ecco l'hook pre-commit del mio file batch di Windows. Se l'utente è un amministratore, gli altri controlli verranno ignorati. Verifica se il messaggio di commit è vuoto e se il commit è su un tag. Nota: findstr è un'alternativa nerfed a grep su altre piattaforme.

Il modo in cui controlla se il commit è su un tag, controlla innanzitutto se svnlook è cambiato contiene " tags / " ;. Quindi controlla se svnlook ha cambiato le corrispondenze " ^ A. tags / [^ /] / $ " ;, il che significa che controllerà se stai aggiungendo una nuova cartella sotto i tag /.

Gli utenti sono autorizzati a creare nuovi progetti. L'hook pre-commit consente all'utente di creare le cartelle trunk / tag / e rami /. Agli utenti non è consentito eliminare le cartelle trunk / tags / e rami /. Funzionerà con un repository singolo o multiprogetto.

 @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

Questa risposta è molto successiva, ma ho scoperto il parametro --copy-info per il comando svnlook changed.

L'output di questo comando aggiunge un '+' nella terza colonna, quindi sai che è una copia. Puoi verificare la presenza di commit nella directory dei tag e consentire solo i commit con un '+' presente.

Ho aggiunto qualche output in il mio post sul blog .

Abbastanza tardi per la festa, tuttavia ho scritto un hook pre-commit in pitone per lavoro che si basa sullo script log-police.py su http://subversion.tigris.org/ .

Questo script dovrebbe fare quello che vuoi, tuttavia controlla anche che esista un messaggio di registro, anche se dovrebbe essere facile da rimuovere dallo script.

Alcuni avvertimenti:

  • Sono nuovo di Python, quindi molto probabilmente potrebbe essere scritto meglio
  • È stato testato solo su Windows 2003 con Python 2.5 e Subversion 1.4.

Requisiti:

  • Subversion
  • Python
  • Binding Subversion per Python

Infine, il codice:

#!/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 maggior parte degli script precedentemente scritti sono incompleti perché diversi casi non sono coperti. Questa è la mia sceneggiatura:

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

Potrebbe sembrare complicato ma devi assicurarti di essere in / tags e di poter creare / tags se non esiste e tutte le cartelle successive. Qualsiasi altra modifica è bloccata. Quasi nessuno degli script precedenti copre tutti i casi descritti nel libro Subversion per svnlook modificato ... .

La risposta accettata impedisce l'aggiornamento dei file in un tag ma non impedisce l'aggiunta di file a un tag. La seguente versione gestisce entrambi:

#!/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

La mia versione consente solo di creare ed eliminare tag. Questo dovrebbe gestire tutti i casi speciali (come l'aggiunta di file, la modifica delle proprietà, ecc.).

#!/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

Se si utilizza JIRA, è possibile utilizzare il componente aggiuntivo denominato Commit Policy per proteggere i percorsi nel tuo repository senza scrivere hook personalizzati .

Come? Utilizza la condizione denominata Modificato i file devono corrispondere a un modello .

Ha un argomento del tipo di espressione regolare che deve corrispondere per ogni file in un commit, altrimenti il ??commit viene rifiutato. Quindi, nel tuo caso dovresti usare una regex che significa che "non inizia con il prefisso / tag / " ;.

(Puoi implementare molti altri controlli intelligenti con lo stesso plugin.)

Disclaimer: sono uno sviluppatore che lavora su questo componente aggiuntivo a pagamento.

Poiché la prima risposta non ha impedito l'aggiunta di file / suppr e ha impedito la creazione di nuovi tag e molti altri in cui erano incompleti o difettosi, l'ho rielaborato

Ecco il mio hook pre-commit: Gli obiettivi sono:

  • Non consentire commit su tag (aggiunta file / soppressione / aggiornamenti)
  • Non impedire la creazione di tag

--------- file " pre-commit " (metti nei repository hook cartella) ---------

#!/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;

--------- fine del file " pre-commit " ---------

Inoltre, ho creato 2 script di shell per copiare il mio hook in ogni progetto del mio svn: Uno per impostare un repository di sola lettura:

--------- 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

--------- fine del file " setOneRepoTagsReadOnly.sh " ---------

E uno lo chiama per ogni repository, per rendere tutti i miei repository di sola lettura:

--------- file " 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' \{\} \;

--------- fine del file " makeTagsReadOnly.sh " ---------

Eseguo questi script direttamente dalla svn " root " (/ var / svn / repos / svn, nel mio caso). A proposito, è possibile impostare un'attività cron per modificare automaticamente i nuovi repository eseguendo questi script ogni giorno

Spero che sia d'aiuto.

Le risposte elencate sono ottime, ma nessuna ha fatto esattamente quello di cui avevo bisogno. Voglio consentire la creazione di tag facilmente, ma una volta creati dovrebbero essere completamente di sola lettura.

Voglio anche prevenire la stupida situazione in cui se lo fai:

svn copy myrepo/trunk myrepo/tags/newrelease

Tutto va bene la prima volta. Ma la seconda volta, se il tag esiste già, finirai con myrepo / tags / newrelease / trunk .

Il mio hook pre-commit cercherà qualsiasi directory SVN preesistente corrispondente a (repo) / tags / (tag) / e fallirà se viene trovato:

$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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top