ربط SVN المسبق لتجنب التغييرات في الدلائل الفرعية للعلامات

StackOverflow https://stackoverflow.com/questions/464384

سؤال

هل هناك أي شخص لديه تعليمات واضحة حول كيفية إضافة رابط الالتزام المسبق الذي يتجنب التغييرات في الدلائل الفرعية للعلامات؟

لقد بحثت بالفعل في الإنترنت قليلاً.لقد وجدت هذا الرابط: SVN::خطافات::رفض التغييرات ، لكن يبدو أنني لا أستطيع تجميع الأشياء.

هل كانت مفيدة؟

المحلول

وأنا لم يكن لديك ما يكفي لسمعة "التعليق" على الجواب RAIM في أعلاه، إلا أن عملت كبيرة، مع استثناء واحد، له نمط البقرى خاطئ.

وأنا ببساطة استخدام أدناه كما بلدي قبل ارتكاب هوك (لم يكن لديك واحدة موجودة، وكنت بحاجة إلى دمج في هذه الحالة):

#!/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 هو أنه يضاهيه سوى "العلامات" إذا كان في "جذور" من الريبو الخاصة بك. لأن لدي العديد من المشاريع في بلدي الريبو، والسيناريو لأنه كتب أنه سمح يرتكب على فروع العلامة.

وبالإضافة إلى ذلك، يجب التأكد من شمود + س على النحو المشار إليه، وإلا عليك التفكير عملت ب / ج فشلت ارتكابها، لكنها فشلت ب / ج أنه لا يمكن أن إكسيك ما قبل ارتكاب هوك، وليس لأن ربط عمل .

وهذا كان عظيما حقا، وذلك بفضل RAIM. الوزن أفضل بكثير وأخف وزنا من كل الاقتراحات الأخرى لأنه لا يوجد لديه تبعيات!

نصائح أخرى

وهنا هو قذيفة قصيرة النصي لمنع ارتكاب إلى علامات بعد أن تم إنشاؤها:

#!/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 لمستودع التخريب وجعله قابل للتنفيذ مع chmod +x.

وهنا هو بلدي ملف النوافذ دفعة قبل ارتكاب هوك. إذا كان المستخدم مسؤول سيتم تخطي الاختبارات الأخرى. فإنه يتحقق إذا كان ارتكاب رسالة فارغة، وإذا كان ارتكاب هو علامة. ملاحظة: FINDSTR هو بديل nerfed على البقرى على منصات أخرى

والطريقة التي يتحقق إذا كان الالتزام هو علامة، فإنه أولا بفحص إذا تغيرت svnlook يحتوي على "العلامات /". ومن ثم يتحقق اذا غيرت svnlook مباريات "^ A. <م> علامات / [^ /] / $"، مما يعني أنه سوف تحقق إذا كنت تقوم بإضافة مجلد جديد تحت علامات /.

يسمح

والمستخدمين لإنشاء مشاريع جديدة. وقبل ارتكاب هوك يسمح للمستخدم لإنشاء المجلدات جذع / علامات / والفروع /. لا يسمح للمستخدمين حذف المجلدات جذع / علامات / والفروع /. وهذا العمل للمستودع واحد أو مشاريع متعددة.

 @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

لقد تأخرت هذه الإجابة كثيرًا، لكنني اكتشفت المعلمة --copy-info لأمر svnlook الذي تم تغييره.

يضيف ناتج هذا الأمر علامة "+" في العمود الثالث، حتى تعرف أنها نسخة.يمكنك التحقق من الالتزامات في دليل العلامات، والسماح فقط بالالتزامات التي تحتوي على علامة "+".

لقد أضفت بعض الإخراج في مشاركة مدونتي.

لقد تأخرت كثيرًا عن الحفلة، ومع ذلك فقد كتبت رابطًا للالتزام المسبق ببايثون للعمل والذي يستند إلى البرنامج النصي log-police.py الموجود على http://subversion.tigris.org/.

يجب أن يفعل هذا البرنامج النصي ما تريد، ولكنه يتحقق أيضًا من وجود رسالة سجل، على الرغم من أنه من السهل إزالتها من البرنامج النصي.

بعض التحذيرات:

  • أنا جديد على لغة بايثون، لذلك على الأرجح يمكن كتابتها بشكل أفضل
  • تم اختباره فقط على نظام التشغيل Windows 2003 مع Python 2.5 وSubversion 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 إذا لم يكن موجودا، وجميع المجلدات اللاحقة. يتم حظر أي تغيير آخر. تقريبا لا شيء من النصوص السابقة تغطي جميع الحالات الموصوفة في الكتاب التخريب ل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، فيمكنك استخدام الوظيفة الإضافية المسماة سياسة الالتزام لحماية المسارات في المستودع الخاص بك دون كتابة السنانير المخصصة.

كيف؟استخدم الشرط المسمى يجب أن تتطابق الملفات التي تم تغييرها مع النمط.

يحتوي على وسيطة نوع التعبير العادي التي يجب أن تتطابق مع كل ملف في الالتزام، وإلا فسيتم رفض الالتزام.لذلك، في حالتك يجب عليك استخدام regex الذي يعني "لا يبدأ بالبادئة /tags/".

(يمكنك تنفيذ العديد من عمليات الفحص الذكية الأخرى باستخدام نفس المكون الإضافي.)

تنصل:أنا مطور أعمل على هذه الوظيفة الإضافية المدفوعة.

نظرًا لأن الإجابة الأولى لم تمنع إضافة/دعم الملفات، ومنعت إنشاء علامات جديدة، والعديد من الأشياء الأخرى التي تكون غير مكتملة أو بها أخطاء، فقد قمت بإعادة صياغتها

إليكم خطاف الالتزام المسبق الخاص بي:الأهداف هي :

  • عدم السماح بالالتزامات على العلامات (إضافة ملف/قمع/تحديثات)
  • لا تمنع إنشاء العلامات

--------- ملف "الالتزام المسبق" (وضع في المستودعات خطافات مجلد) ---------

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

--------- نهاية الملف "الالتزام المسبق" ---------

قمت أيضًا بإنشاء نصين برمجيين لنسخ الخطاف الخاص بي في كل مشروع على 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.

وبلدي قبل ارتكاب هوك سوف تبحث عن أي (repo)/tags/(tag)/ SVN دليل مطابقة موجودة من قبل وتفشل إذا وجدت ما يلي:

$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