Хук предварительной фиксации SVN для предотвращения изменений в подкаталогах тегов

Есть ли у кого-нибудь четкие инструкции о том, как добавить ловушку перед фиксацией, которая позволяет избежать изменений в подкаталогах тегов?

Я уже довольно много поискал в Интернете. Я нашел эту ссылку: SVN :: Hooks :: DenyChanges, но я могу ' Кажется, я компилирую вещи.


person Wim Deblauwe    schedule 21.01.2009    source источник


Ответы (11)


У меня недостаточно репутации, чтобы «комментировать» ответ Раима выше, но он отлично работал, за одним исключением, его шаблон grep неверен.

Я просто использовал нижеприведенный хук перед фиксацией (у меня не было существующего, в этом случае вам нужно было бы выполнить слияние):

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

Единственная проблема с шаблоном grep Раима заключается в том, что он сопоставляет «теги» только в том случае, если он находится в «корне» вашего репо. Поскольку в моем репо есть несколько проектов, сценарий, который он написал, разрешал коммиты в ветвях тегов.

Кроме того, убедитесь, что chmod + x, как указано, иначе вы подумаете, что это сработало, потому что фиксация не удалась, но она не удалась, потому что не удалось выполнить ловушку перед фиксацией, а не потому, что ловушка сработала.

Это было действительно здорово, спасибо, Раим. Намного лучше и легче, чем все другие предложения, поскольку он не имеет зависимостей!

person apinstein    schedule 15.03.2009
comment
Ты прав. Я не думал о нескольких проектах в одном репозитории, так как это установка, которую я сам не использую. - person raimue; 08.04.2009
comment
Круто спасибо и за проверку, и за скрипт! Это, безусловно, самое элегантное решение проблемы. - person apinstein; 09.04.2009
comment
Этот скрипт неполный, он не обрабатывает ни удаления, ни добавления, ни изменения свойств. - person Michael-O; 17.11.2011
comment
Мне пришлось изменить соответствие grep на grep "^U\W.*tags\/", потому что в моем выводе svnlook не было ведущей косой черты в пути к репозиторию. - person Marcus; 20.10.2012
comment
Это не совсем правильно. Вы также должны запретить пользователям добавлять и удалять файлы в теге, а не только изменять их. - person mvd; 19.03.2014

Вот короткий сценарий оболочки для предотвращения фиксации тегов после их создания:

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

person raimue    schedule 23.02.2009

Вот мой хук предварительной фиксации командного файла Windows. Если пользователь является администратором, другие проверки будут пропущены. Он проверяет, является ли сообщение фиксации пустым, а фиксация - тегом. Примечание: findstr - это уменьшенная альтернатива grep на других платформах.

Как он проверяет, относится ли фиксация к тегу, он сначала проверяет, содержит ли svnlook changed "теги /". Затем он проверяет, соответствует ли svnlook changed "^ A. tags / [^ /] / $", что означает, что он проверит, добавляете ли вы новую папку в тегах /.

Пользователи могут создавать новые проекты. Ловушка предварительной фиксации позволяет пользователю создавать папки trunk / tags / и branch /. Пользователям не разрешается удалять папки trunk / tags / и branch /. Это будет работать для репозитория с одним или несколькими проектами.

 @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
person mcdon    schedule 23.08.2010
comment
Хорошо отшлифованный, готовый к запуску сценарий, который охватывает заданный вопрос и многое другое - молодец! - person Michael Sorens; 30.05.2013

Этот ответ очень устарел, но я обнаружил параметр --copy-info для команды svnlook changed.

В выводе этой команды в третьем столбце добавляется знак «+», так что вы знаете, что это копия. Вы можете проверить наличие коммитов в каталоге тегов и разрешить коммиты только со знаком «+».

Я добавил некоторые результаты в мою запись в блоге .

person coudenysj    schedule 20.08.2010

Довольно поздно для вечеринки, однако я написал хук предварительной фиксации python для работы, который основан на сценарии log-police.py на http://subversion.tigris.org/.

Этот сценарий должен делать то, что вы хотите, однако он также проверяет наличие сообщения журнала, хотя его должно быть легко удалить из сценария.

Некоторые предостережения:

  • Я новичок в Python, поэтому его, скорее всего, можно было бы написать лучше
  • Он был протестирован только в Windows 2003 с Python 2.5 и Subversion 1.4.

Требования:

  • Subversion
  • Python
  • Привязки Subversion для Python

Наконец, код:

#!/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))
person Nick Brooks    schedule 30.01.2009

Большинство ранее написанных сценариев неполны, потому что некоторые случаи не рассмотрены. Это мой сценарий:

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

person Michael-O    schedule 17.11.2011
comment
Что требуется для использования этого крючка? Я готов реализовать его для блокировки comit в указанный каталог ... но я не понимаю, где мне нужно его отредактировать, чтобы изменить отмеченный каталог ... может быть, есть какое-то приложение, которое может сгенерировать такой скрипт, взяв каталог репо в качестве параметра .. .? - person HX_unbanned; 27.01.2012
comment
Нет, вы должны поместить ловушку в hooks каталог сервера, на котором размещено репо. Прочтите об этом книгу о подрывной деятельности. - person Michael-O; 28.01.2012
comment
Да, я понимаю это; Извините за плохо сформулированный вопрос: / My Eng не так хорош для специфики программирования :( Идея вопроса: как указать другой каталог репо, кроме тегов? Например, ветвь или вперед или что-то еще ... но вместо жесткого -кодировать каталог в скрипте - передать его как параметр? - person HX_unbanned; 30.01.2012
comment
Фактически вы не можете этого сделать, если не определите массив блокируемых каталогов и не выполните итерацию в приведенном выше скрипте. В вашем скрипте переданы только два параметра. Ни больше ни меньше. - person Michael-O; 30.01.2012

Принятый ответ предотвращает обновление файлов в теге, но не предотвращает добавление файлов в тег. Следующая версия обрабатывает оба:

#!/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
person Vinay Sahni    schedule 19.07.2011
comment
Могу ли я изменить теги на ветки или другие подкаталоги svn: // ‹root› / tags? Например, ‹root› / ‹some_direcotry› / ‹some_other_dir›? - person HX_unbanned; 27.01.2012
comment
По какой-то причине у меня это не сработало. Я пробовал это, и он хорошо работает. $ SVNLOOK изменился на $ TXN $ REPOS | grep ^ [AUD_]. . * / теги /.*/. && / bin / echo 'Невозможно обновить теги!' 1 ›& 2 && exit 2 - person VRK; 06.10.2015

Моя версия позволяет только создавать и удалять теги. Это должно обрабатывать все особые случаи (например, добавление файлов, изменение свойств и т. Д.).

#!/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
person Marián Černý    schedule 11.11.2013

Если вы используете JIRA, вы можете использовать надстройку с именем Политика фиксации для защиты путей в вашем репозитории без написания пользовательских хуков.

Как? Используйте условие с именем Changed файлы должны соответствовать шаблону.

У него есть аргумент типа регулярного выражения, который должен соответствовать для каждого файла в фиксации, в противном случае фиксация будет отклонена. Итак, в вашем случае вы должны использовать регулярное выражение, которое означает «не начинается с префикса / tags /».

(Вы можете реализовать множество других интеллектуальных проверок с помощью того же плагина.)

Заявление об ограничении ответственности: я разработчик и работаю над этим платным дополнением.

person Ferenc Kiss    schedule 29.09.2015

Поскольку 1-й ответ не препятствовал добавлению / поддержке файлов и предотвращал создание новых тегов, а также многих других, неполных или ошибочных, я переработал его.

Вот мой прием перед фиксацией: Цели:

  • Запретить коммиты по тегам (добавление / подавление / обновление файлов)
  • Не препятствовать созданию тегов

--------- файл "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 может быть настроена для автоматического изменения новых репозиториев, ежедневно выполняя сценарии thoses.

Надеюсь, поможет.

person Balmipour    schedule 11.07.2014

Перечисленные ответы великолепны, но ни один из них не сделал именно то, что мне нужно. Я хочу упростить создание тегов, но после их создания они должны быть полностью доступны только для чтения.

Я также хочу предотвратить глупую ситуацию, когда, если вы сделаете это:

svn copy myrepo/trunk myrepo/tags/newrelease

С первого раза все хорошо. Но во второй раз, если тег уже существует, вы получите myrepo/tags/newrelease/trunk.

Моя ловушка перед фиксацией будет искать любой ранее существовавший каталог 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
person grue    schedule 18.12.2015