Pergunta

Há alguém que tem instruções claras sobre como adicionar um gancho pre-commit que evita mudanças nas Marcações subdiretórios?

Eu já procurei na internet um pouco. Eu encontrei este link: SVN :: Ganchos :: DenyChanges , mas eu posso' t parecem compilar as coisas.

Foi útil?

Solução

Eu não tenho reputação suficiente para "comentário" na resposta de Raim acima, mas seu grande trabalhado, com uma exceção, o seu padrão grep é errado.

Eu simplesmente usado a seguir como meu pre-commit gancho (eu não tenho um já existente, você precisa mesclar nesse caso):

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

O único problema com padrão grep do Raim é que ele só combinado "tags" se fosse na "raiz" do seu repo. Desde que eu tenho vários projetos em meu repo, o script como escreveu permitiu commits em ramos de tag.

Além disso, certifique-se de chmod + x como indicado, caso contrário você vai acho que funcionou b / c do commit falhou, mas falhou b / c não poderia exec o gancho pre-commit, não por causa do gancho trabalhou .

Este foi realmente grande, graças Raim. Muito melhor e mais leve do que todas as outras sugestões, uma vez que não tem dependências!

Outras dicas

Aqui está um script shell curto para evitar comprometer com as tags depois de terem sido criados:

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

Save isso em hooks/pre-commit para o seu Subversion repositório e torná-lo executável com chmod +x.

Aqui está o meu arquivo janelas lote pre-commit gancho. Se o usuário é um administrador as outras verificações será ignorado. Ele verifica se a mensagem de commit estiver vazia, e se a cometer é uma tag. Nota:. Findstr é uma alternativa nerfed de grep em outras plataformas

A forma como ele verifica se a cometer é uma tag, ele primeiro verifica se svnlook mudou contém "tags /". Em seguida, ele verifica se svnlook mudou partidas "^ A. tags / [^ /] / $", o que significa que ele irá verificar se você está adicionando uma nova pasta em etiquetas /.

Os usuários têm permissão para criar novos projetos. O gancho pre-commit permite que um usuário para criar as pastas trunk / tags / e ramos /. Os usuários não têm permissão para excluir as pastas trunk / tags / e ramos /. Isto irá funcionar para um único ou multi-projeto de repositório.

 @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%$" >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/$" >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/[^/]*/$" >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/$" >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 anwser é muito após a data, mas eu descobri o parâmetro --copy-info para o comando svnlook alterado.

A saída deste comando adiciona um '+' na terceira coluna, então você sabe que é uma cópia. Você pode verificar se há commit no diretório tags, e só permitir commits com um presente de '+'.

Eu adicionei alguma saída em meu blog .

Pretty atrasado para a festa, no entanto eu escrevi um python pré-commit gancho para o trabalho que é baseado fora o script log-police.py em http://subversion.tigris.org/ .

Este script deve fazer o que quiser, no entanto, também verifica que uma mensagem de log existe, no entanto, que deve ser fácil de remover do script.

Algumas advertências:

  • Eu sou novo para Python, por isso provavelmente poderia ser escrito melhor
  • É só foi testado no Windows 2003 com Python 2.5 e Subversion 1.4.

Requisitos:

  • Subversion
  • Python
  • ligações Subversion para Python

Finalmente, o 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))

A maioria dos scripts escritos anteriormente são incompletos porque vários casos não são cobertos. Este é o meu script:

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

Pode parecer complicado, mas você tem que ter certeza que você está em /tags e você é permitido criar /tags se ele não existe e todas as pastas subseqüentes. Qualquer outra alteração é bloqueado. Quase nenhum dos scripts anteriores cobrir todos os casos descritos no livro do Subversion para svnlook changed ....

Os previne resposta aceita atualizando arquivos em uma tag, mas não impede a adição de arquivos para um tag. Os seguintes alças versão 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

A minha versão só permite criar e apagar tags. Isso deve lidar com todos os casos especiais (como a adição de arquivos, alterar as propriedades, 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/[^/]+/$" && output_error_and_exit "Modification of tags is not allowed."
fi 

exit 0

Se você estiver usando JIRA, você pode usar o add-on chamado Commit política para proteger os caminhos em seu repositório sem escrever ganchos feitos sob encomenda .

Como? Use a condição chamada Changed arquivos devem corresponder a um padrão .

Ele tem um argumento de tipo de expressão regular que deve corresponder para cada arquivo em um commit, caso contrário, a submissão é rejeitada. Assim, no seu caso, você deve usar um regex que significa "não começar com o prefixo / etiquetas /".

(Você pode implementar muitas outras verificações inteligentes com o mesmo plugin.)

Disclaimer:. Eu sou um desenvolvedor trabalhando neste add-on pago

Desde o 1º resposta não impediu add / arquivos SUPPR, e impediu nova criação etiquetas, e muitos outros onde incompleta ou de buggy, eu reescrevi-lo

Aqui está a minha pré-commit gancho: Os objetivos são:

  • Não permitir compromete em tags (adição de arquivo / supressão / atualizações)
  • não impedem a criação de marcas

--------- arquivo "pré-compromisso" (put em repositórios ganchos pasta) ---------

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

--------- fim de arquivo "pré-compromisso" ---------

Além disso, eu fiz 2 shell scripts para copiar o meu anzol em cada projeto do meu svn: Um para definir um repositório apenas para leitura:

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

--------- fim de arquivo "setOneRepoTagsReadOnly.sh" ---------

E um chamando-o para cada repo, fazer todos os meus repos somente leitura:

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

--------- fim de arquivo "makeTagsReadOnly.sh" ---------

eu executar thoses de scripts diretamente do "root" svn (/ var / svn / repos / SVN, no meu caso). Btw, uma tarefa cron poderia ser ajustado para automaticamente modificar novas repos executando thoses roteiros diária

Hope isso ajuda.

As respostas listadas são grandes, mas nenhum fez exatamente o que eu preciso. Eu quero permitir a criação de etiquetas com facilidade, mas uma vez que são criados, eles devem ser totalmente só de leitura.

Eu também quero evitar que a situação estúpida em que se você fizer isso:

svn copy myrepo/trunk myrepo/tags/newrelease

Tudo está bem pela primeira vez. Mas o segundo tempo, se a tag já existe, você vai acabar com myrepo/tags/newrelease/trunk.

O meu pré-commit hook vai olhar para qualquer pré-existente SVN (repo)/tags/(tag)/ diretório correspondente e falhar se ele é encontrado:

$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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top