有没有人对如何添加避免更改标签子目录的预提交挂钩有明确的说明?

我已经在互联网上搜索了很多。我找到了这个链接: SVN::Hooks::拒绝更改 ,但我似乎无法编译东西。

有帮助吗?

解决方案

我没有对RAIM的回答足够的声誉“评论”上,但他的伟大的工作,但有一个例外,他的grep的模式是错误的。

我只是用下面是我pre-commit钩子(我没有一个现有的,你需要在这种情况下,合并):

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

施用rAIM的grep的格局,唯一的问题是,如果它是在你的回购的“根”,它仅匹配的“标签”。因为我有几个项目在我的回购,剧本,他写了它允许在标签分支机构提交。

此外,请务必于chmod + x作为指示,否则你会觉得它的工作二/三提交失败,但是失败了B / C它不能执行的是pre-commit钩子,而不是因为工作挂钩

这真是棒极了,感谢RAIM。更好,重量更轻比所有其他的建议,因为它没有依赖性!

其他提示

下面是一个简短的shell脚本,以防止承诺的标签,他们已经被创建之后:

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

hooks/pre-commit保存此为您的Subversion版本库,并使其与chmod +x可执行文件。

下面是预先承诺我的窗户批处理文件钩。如果用户是管理员的其他检查将被跳过。它检查是否提交消息是空的,并且如果所述提交是标签。注意:FINDSTR是削弱替代到grep在其他平台上

如果提交它检查的方法是一个标记时,它首先检查是否svnlook的改变包含“标签/”。然后,它检查是否svnlook的改变比赛的“^ 标签/ [^ /] 的/ $”,这意味着它会检查您是否在标签中添加一个新的文件夹/.

用户被允许创建新项目。在pre-commit钩子允许用户创建的文件夹主干/标签/枝/。不允许用户删除的文件夹主干/标签/枝/。这将用于单个或多项目存储库工作。

 @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

这anwser是很多日期之后,但是,我发现了svnlook的所述--copy-info参数改变命令。

此命令的输出在第三列中增加了一个“+”,所以你知道它是一个副本。您可以检查提交到标签目录,并只允许提交一个“+”存在。

我已在我的博客文章

很晚的派对,不过我写了一python预先承诺挂钩的工作,这是基于关闭log-police.py 脚本 http://subversion.tigris.org/.

这个脚本应该做你想做的,但是它还检查,记录信息存在,虽然这应该很容易从中删除脚本。

一些注意事项:

  • 我是新来的蟒蛇,所以它最有可能可以写得更好
  • 它只有经过测试的Windows2003Python2.5和颠复1.4.

要求:

  • 颠复
  • 蟒蛇
  • 颠复绑定的蟒蛇

最后,代码:

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

大多数以前写的脚本是不完整的,因为不包括几种情况。这是我的脚本:

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

这可能看起来很复杂,但你必须确保你是在/tags和你被允许,如果不存在,所有后续文件夹,它创建/tags。任何其他变化被阻断。几乎没有任何以前的脚本覆盖在Subversion书svnlook changed ...描述的所有情况。

接受的答案防止更新文件在一个标记,但并不妨碍将文件添加到标记。下面的版本同时处理:

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

我的版本只允许创建和删除标签。这应处理所有的特殊情况下(如添加文件,更改属性等)。

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

如果您使用 JIRA,则可以使用名为的附加组件 承诺政策 保护存储库中的路径 无需编写自定义钩子.

如何?使用名为的条件 更改的文件必须匹配模式.

它有一个正则表达式类型参数,该参数必须与提交中的每个文件匹配,否则提交将被拒绝。因此,在您的情况下,您应该使用一个正则表达式,这意味着“不以前缀 /tags/ 开头”。

(您可以使用同一插件实现许多其他智能检查。)

免责声明:我是一名开发人员,致力于此付费附加组件。

由于第1答案没有防止添加/suppr文件和防止新标签的设立,以及许多其他哪里不完整或越野车,我重新设计它

这是我预先承诺挂钩:目标是:

  • 禁止提交上标签(文件除/制止/更新)
  • 不会阻止创建的标签

---------文件"pre-commit"(放在仓库 钩子 文件夹) ---------

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

------结束的文件"预先提交" ---------

此外,我做了2个脚本来复制我的钩,在每一个项目,我svn:一个设置一个仓库的只读:

---------脚本"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

------结束的文件"setOneRepoTagsReadOnly.sh" ---------

和一个叫它的每一个仓库,让我所有的仓库只读:

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

------结束的文件"makeTagsReadOnly.sh" ---------

我放入系统执行的脚本直接从svn"根源"(/var/svn/repos/svn,在我的情况)。顺便说一句,一个cron任务可能设置自动修改新的仓库,通过执行放入系统脚本的日常

希望这有所帮助。

以上答案都是伟大的,但没有做正是我需要的。我想允许轻松创建标签,但一旦创建就应该完全为只读。

我也想避免愚蠢的情况下,如果你这样做:

svn copy myrepo/trunk myrepo/tags/newrelease

全部是很好的第一次。但第二次,如果标签已经存在,你将最终myrepo/tags/newrelease/trunk

我的pre-commit钩子将寻找任何预先存在的SVN目录匹配(repo)/tags/(tag)/和失败,如果它的发现:

$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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top