Как реализовать перехватчик Post Commit с помощью Trac и SVN в среде Windows?

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

  •  01-07-2019
  •  | 
  •  

Вопрос

Я работаю в среде Windows с Trac/SVN и хочу внести изменения в репозиторий для интеграции с Trac и закрытия ошибок, отмеченных в комментарии SVN.

Я знаю, что для этого есть несколько перехватчиков после фиксации, но информации о том, как это сделать в Windows, не так много.

Кто-нибудь сделал это успешно?И какие шаги вы предприняли для достижения этой цели?

Вот крючок, который мне нужно добавить в SVN, но я не совсем уверен, как это сделать в среде Windows.

Крючок фиксации сообщения Trac

Это было полезно?

Решение 2

Хорошо, теперь у меня есть время опубликовать свой опыт после того, как я во всем этом разобрался, и спасибо Крейгу за то, что он направил меня на правильный путь.Вот что вам нужно сделать (по крайней мере, с SVN v1.4 и Trac v0.10.3):

  1. Найдите свой репозиторий SVN, для которого вы хотите включить перехватчик Post Commit.
  2. внутри репозитория SVN есть каталог под названием «hooks», именно здесь вы разместите хук после фиксации.
  3. создайте файл post-commit.bat (это пакетный файл, который автоматически вызывается после фиксации SVN).
  4. Поместите следующий код в файл post-commit.bat (это вызовет ваш cmd-файл после фиксации, передав параметры, которые SVN автоматически передает: %1 — это репозиторий, %2 — это зафиксированная ревизия.

%~dp0 rac-post-commit-hook.cmd %1 %2

  1. Теперь создайте файл trac-post-commit-hook.cmd следующим образом:

@ЭХО ВЫКЛ.
::
::Trac Post-Commit-Hook Script для Windows
::
::Внесен Маркус, модифицированный CBOOS.

::Использование:
::
::1) Вставьте следующую строку в свой сценарий Post-commit.bat
::
::звонок %~ dp0 trac-post-commit-hook.cmd %1 %2
::
::2) Проверьте раздел «Изменить пути» ниже, обязательно установите хотя бы trac_env


:: ----------------------------------------------------------
::Измените пути здесь:

::-- Вот этот должен быть установлен
Установить trac_env = c: trac myspecialproject

::- Установите, если Python нет в системном пути
::Установить python_path =

::-Установите в папку, содержащую TRAC/ если установлена ​​в нестандартном месте
::Установить trac_path =
:: ----------------------------------------------------------

::Не выполняйте крючок, если среда TRAC не существует
Если нет, % trac_env % goto: eof

установить PATH=%PYTHON_PATH%;%PATH%
Установить PythonPath =%trac_path%;%pythonpath%

УСТАНОВИТЬ ОБРАТ=%2

::Получить автора и сообщение журнала
для /f %% A in ('svnlook Автор -r%rev%1') do установить автор = %% a
for /f "delims ==" %% b in ('svnlook log -r%rev%1') do set log = %% b

::ВЫЗОВ СКРИПТА PYTHON
Python "%~ dp0 trac -post -commit -hook" -p "%trac_env%" -r "%rev%" -u "%автора%" -m "%log%"

Наиболее важным моментом здесь является установка TRAC_ENV, который является путем к корню репозитория (SET TRAC_ENV=C: rac\MySpecialProject).

Следующая ОЧЕНЬ ВАЖНАЯ ВЕЩЬ в этом скрипте — сделать следующее:

::Получить автора и сообщение журнала
для /f %% A in ('svnlook Автор -r%rev%1') do установить автор = %% a
for /f "delims ==" %% b in ('svnlook log -r%rev%1') do set log = %% b

Если вы видите в файле сценария выше, я использую svnlook (утилиту командной строки с SVN), чтобы получить сообщение LOG и автора, который сделал фиксацию в репозитории.

Затем следующая строка сценария фактически вызывает код Python для закрытия заявок и анализа сообщения журнала.Мне пришлось изменить это, чтобы передать сообщение журнала и автора (имена пользователей, которые я использую в Trac, соответствуют именам пользователей в SVN, так что это было легко).

ВЫЗОВ СКРИПТА PYTHON
Python "%~ dp0 trac -post -commit -hook" -p "%trac_env%" -r "%rev%" -u "%автора%" -m "%log%"

Приведенная выше строка сценария передаст в сценарий Python среду Trac, версию, человека, сделавшего фиксацию, и его комментарий.

Вот скрипт Python, который я использовал.Еще одна вещь, которую я сделал в дополнение к обычному сценарию, — это использование настраиваемого поля (fixed_in_ver), которое используется нашей командой контроля качества, чтобы определить, находится ли проверяемое исправление в той версии кода, которую они тестируют в QA.Итак, я изменил код в скрипте Python, чтобы обновить это поле в билете.Вы можете удалить этот код, поскольку он вам не понадобится, но это хороший пример того, что вы можете сделать для обновления настраиваемых полей в Trac, если вы тоже хотите это сделать.

Я сделал это, предложив пользователям по желанию включить в свои комментарии что-то вроде:

(версия 2.1.2223.0)

Затем я использую ту же технику, которую использует скрипт Python с регулярными выражениями, чтобы получить информацию.Это было не так уж плохо.

В любом случае, вот скрипт Python, который я использовал. Надеюсь, это хороший учебник о том, что именно я сделал, чтобы заставить его работать в мире Windows, чтобы вы все могли использовать его в своем собственном магазине...

Если вы не хотите иметь дело с моим дополнительным кодом для обновления настраиваемого поля, получите базовый скрипт из этого места, как упоминалось Крейгом выше (Скрипт из Edgewall)

#!/usr/bin/env python

# trac-post-commit-hook
# ----------------------------------------------------------------------------
# Copyright (c) 2004 Stephen Hansen 
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included in
#   all copies or substantial portions of the Software. 
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# ----------------------------------------------------------------------------

# This Subversion post-commit hook script is meant to interface to the
# Trac (http://www.edgewall.com/products/trac/) issue tracking/wiki/etc 
# system.
# 
# It should be called from the 'post-commit' script in Subversion, such as
# via:
#
# REPOS="$1"
# REV="$2"
# LOG=`/usr/bin/svnlook log -r $REV $REPOS`
# AUTHOR=`/usr/bin/svnlook author -r $REV $REPOS`
# TRAC_ENV='/somewhere/trac/project/'
# TRAC_URL='http://trac.mysite.com/project/'
#
# /usr/bin/python /usr/local/src/trac/contrib/trac-post-commit-hook \
#  -p "$TRAC_ENV"  \
#  -r "$REV"       \
#  -u "$AUTHOR"    \
#  -m "$LOG"       \
#  -s "$TRAC_URL"
#
# It searches commit messages for text in the form of:
#   command #1
#   command #1, #2
#   command #1 & #2 
#   command #1 and #2
#
# You can have more then one command in a message. The following commands
# are supported. There is more then one spelling for each command, to make
# this as user-friendly as possible.
#
#   closes, fixes
#     The specified issue numbers are closed with the contents of this
#     commit message being added to it. 
#   references, refs, addresses, re 
#     The specified issue numbers are left in their current status, but 
#     the contents of this commit message are added to their notes. 
#
# A fairly complicated example of what you can do is with a commit message
# of:
#
#    Changed blah and foo to do this or that. Fixes #10 and #12, and refs #12.
#
# This will close #10 and #12, and add a note to #12.

import re
import os
import sys
import time 

from trac.env import open_environment
from trac.ticket.notification import TicketNotifyEmail
from trac.ticket import Ticket
from trac.ticket.web_ui import TicketModule
# TODO: move grouped_changelog_entries to model.py
from trac.util.text import to_unicode
from trac.web.href import Href

try:
    from optparse import OptionParser
except ImportError:
    try:
        from optik import OptionParser
    except ImportError:
        raise ImportError, 'Requires Python 2.3 or the Optik option parsing library.'

parser = OptionParser()
parser.add_option('-e', '--require-envelope', dest='env', default='',
                  help='Require commands to be enclosed in an envelope. If -e[], '
                       'then commands must be in the form of [closes #4]. Must '
                       'be two characters.')
parser.add_option('-p', '--project', dest='project',
                  help='Path to the Trac project.')
parser.add_option('-r', '--revision', dest='rev',
                  help='Repository revision number.')
parser.add_option('-u', '--user', dest='user',
                  help='The user who is responsible for this action')
parser.add_option('-m', '--msg', dest='msg',
                  help='The log message to search.')
parser.add_option('-c', '--encoding', dest='encoding',
                  help='The encoding used by the log message.')
parser.add_option('-s', '--siteurl', dest='url',
                  help='The base URL to the project\'s trac website (to which '
                       '/ticket/## is appended).  If this is not specified, '
                       'the project URL from trac.ini will be used.')

(options, args) = parser.parse_args(sys.argv[1:])

if options.env:
    leftEnv = '\\' + options.env[0]
    rghtEnv = '\\' + options.env[1]
else:
    leftEnv = ''
    rghtEnv = ''

commandPattern = re.compile(leftEnv + r'(?P<action>[A-Za-z]*).?(?P<ticket>#[0-9]+(?:(?:[, &]*|[ ]?and[ ]?)#[0-9]+)*)' + rghtEnv)
ticketPattern = re.compile(r'#([0-9]*)')
versionPattern = re.compile(r"\(version[ ]+(?P<version>([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+))\)")

class CommitHook:
    _supported_cmds = {'close':      '_cmdClose',
                       'closed':     '_cmdClose',
                       'closes':     '_cmdClose',
                       'fix':        '_cmdClose',
                       'fixed':      '_cmdClose',
                       'fixes':      '_cmdClose',
                       'addresses':  '_cmdRefs',
                       're':         '_cmdRefs',
                       'references': '_cmdRefs',
                       'refs':       '_cmdRefs',
                       'see':        '_cmdRefs'}

    def __init__(self, project=options.project, author=options.user,
                 rev=options.rev, msg=options.msg, url=options.url,
                 encoding=options.encoding):
        msg = to_unicode(msg, encoding)
        self.author = author
        self.rev = rev
        self.msg = "(In [%s]) %s" % (rev, msg)
        self.now = int(time.time()) 
        self.env = open_environment(project)
        if url is None:
            url = self.env.config.get('project', 'url')
        self.env.href = Href(url)
        self.env.abs_href = Href(url)

        cmdGroups = commandPattern.findall(msg)


        tickets = {}

        for cmd, tkts in cmdGroups:
            funcname = CommitHook._supported_cmds.get(cmd.lower(), '')

            if funcname:

                for tkt_id in ticketPattern.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number... 
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1

                # get the version number from the checkin... and update the ticket with it.
                version = versionPattern.search(msg)
                if version != None and version.group("version") != None:
                    ticket['fixed_in_ver'] = version.group("version")

                ticket.save_changes(self.author, self.msg, self.now, db, cnum+1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=self.now)
            except Exception, e:
                # import traceback
                # traceback.print_exc(file=sys.stderr)
                print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (tkt_id, e)


    def _cmdClose(self, ticket):
        ticket['status'] = 'closed'
        ticket['resolution'] = 'fixed'

    def _cmdRefs(self, ticket):
        pass


if __name__ == "__main__":
    if len(sys.argv) < 5:
        print "For usage: %s --help" % (sys.argv[0])
    else:
        CommitHook()

Другие советы

Ответ Бенджамина близок, но в Windows вам необходимо присвоить файлам сценариев ловушек исполняемое расширение, например .bat или .cmd.Я использую .cmd.Вы можете взять шаблонные сценарии, которые представляют собой сценарии оболочки unix, сценарии оболочки, и преобразовать их в синтаксис .bat/.cmd.

Но чтобы ответить на вопрос об интеграции с Trac, выполните следующие действия.

  1. Убедитесь, что Python.exe находится в системном пути.Это облегчит вашу жизнь.

  2. Создайте post-commit.cmd в папке \hooks.Это фактический скрипт-перехватчик, который Subversion выполнит в событии после фиксации.

    @ECHO OFF
    
    :: POST-COMMIT HOOK
    ::
    :: The post-commit hook is invoked after a commit.  Subversion runs
    :: this hook by invoking a program (script, executable, binary, etc.)
    :: named 'post-commit' (for which this file is a template) with the 
    :: following ordered arguments:
    ::
    ::   [1] REPOS-PATH   (the path to this repository)
    ::   [2] REV          (the number of the revision just committed)
    ::
    :: The default working directory for the invocation is undefined, so
    :: the program should set one explicitly if it cares.
    ::
    :: Because the commit has already completed and cannot be undone,
    :: the exit code of the hook program is ignored.  The hook program
    :: can use the 'svnlook' utility to help it examine the
    :: newly-committed tree.
    ::
    :: On a Unix system, the normal procedure is to have 'post-commit'
    :: invoke other programs to do the real work, though it may do the
    :: work itself too.
    ::
    :: Note that 'post-commit' must be executable by the user(s) who will
    :: invoke it (typically the user httpd runs as), and that user must
    :: have filesystem-level permission to access the repository.
    ::
    :: On a Windows system, you should name the hook program
    :: 'post-commit.bat' or 'post-commit.exe',
    :: but the basic idea is the same.
    :: 
    :: The hook program typically does not inherit the environment of
    :: its parent process.  For example, a common problem is for the
    :: PATH environment variable to not be set to its usual value, so
    :: that subprograms fail to launch unless invoked via absolute path.
    :: If you're having unexpected problems with a hook program, the
    :: culprit may be unusual (or missing) environment variables.
    :: 
    :: Here is an example hook script, for a Unix /bin/sh interpreter.
    :: For more examples and pre-written hooks, see those in
    :: the Subversion repository at
    :: http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
    :: http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
    
    setlocal
    
    :: Debugging setup
    :: 1. Make a copy of this file.
    :: 2. Enable the command below to call the copied file.
    :: 3. Remove all other commands
    ::call %~dp0post-commit-run.cmd %* > %1/hooks/post-commit.log 2>&1
    
    :: Call Trac post-commit hook
    call %~dp0trac-post-commit.cmd %* || exit 1
    
    endlocal
    
  3. Создайте trac-post-commit.cmd в папке \hooks:

    @ECHO OFF
    ::
    :: Trac post-commit-hook script for Windows
    ::
    :: Contributed by markus, modified by cboos.
    
    :: Usage:
    ::
    :: 1) Insert the following line in your post-commit.bat script
    ::
    :: call %~dp0\trac-post-commit-hook.cmd %1 %2
    ::
    :: 2) Check the 'Modify paths' section below, be sure to set at least TRAC_ENV
    
    setlocal
    
    :: ----------------------------------------------------------
    :: Modify paths here:
    
    :: -- this one *must* be set
    SET TRAC_ENV=D:\projects\trac\membershipdnn
    
    :: -- set if Python is not in the system path
    SET PYTHON_PATH=
    
    :: -- set to the folder containing trac/ if installed in a non-standard location
    SET TRAC_PATH=
    :: ----------------------------------------------------------
    
    :: Do not execute hook if trac environment does not exist
    IF NOT EXIST %TRAC_ENV% GOTO :EOF
    
    set PATH=%PYTHON_PATH%;%PATH%
    set PYTHONPATH=%TRAC_PATH%;%PYTHONPATH%
    
    SET REV=%2
    
    :: Resolve ticket references (fixes, closes, refs, etc.)
    Python "%~dp0trac-post-commit-resolve-ticket-ref.py" -p "%TRAC_ENV%" -r "%REV%"
    
    endlocal
    
  4. Создайте trac-post-commit-resolve-ticket-ref.py в папке \hooks.я использовал тот же скрипт от EdgeWall, только я его переименовал, чтобы лучше прояснить его назначение.

Хуки после фиксации находятся в каталоге «hooks», где бы у вас ни находился репозиторий на стороне сервера.Я не знаю, где они находятся в вашей среде, поэтому это всего лишь пример.

например(окна):

C:\Subversion\repositories\repo1\hooks\post-commit

например(Линукс/Юникс):

/usr/local/subversion/repositories/repo1/hooks/post-commit

Единственное, что я добавлю: «Ответ Code Monkey ИДЕАЛЬНЫЙ» - это опасаться этого (моя ошибка)

:: Modify paths here:

:: -- this one must be set
SET TRAC_ENV=d:\trac\MySpecialProject

:: -- set if Python is not in the system path
:: SET PYTHON_PATH=**d:\python**

:: -- set to the folder containing trac/ if installed in a non-standard location 
:: SET TRAC_PATH=**d:\python\Lib\site-packages\trac**

Я не устанавливал несистемные пути, и мне потребовалось некоторое время, чтобы увидеть очевидное: D

Просто убедитесь, что никто другой не повторит ту же ошибку!Спасибо Code Monkey!1000000000 баллов :D

Во-первых, большое спасибо Code Monkey!

Однако важно получить правильный скрипт Python в зависимости от версии вашего трека.Чтобы получить соответствующую версию, SVN проверьте папку:

http://svn.edgewall.com/repos/trac/branches/ххх-стабильный/вклад

где ххх соответствует используемой вами версии trac, например:0,11

В противном случае вы получите сообщение об ошибке после фиксации, которое выглядит следующим образом:

фиксация не удалась (подробности приведены ниже):ОБЪЕДИНЕНИЕ '/svn/project/trunk/web/directory/':200 ОК

Для всех пользователей Windows, желающих установить новейшую версию trac (0.11.5):Следуйте инструкциям на сайте Trac под названием TracOnWindows.

Загрузите 32-битную версию Python 1.5, даже если у вас 64-битная Windows.примечание:Я где-то видел инструкции, как скомпилировать trac для работы в 64-битной системе.

После установки всего необходимого зайдите в папку репозитория.Есть папки с крючками.Внутри него поместите файлы, упомянутые Code Monkey, но не создавайте «trac-post-commit-resolve-ticket-ref.py», как он это сделал.Прислушайтесь к совету Quant Analyst и поступайте так, как он сказал:

«Однако важно получить правильный скрипт Python в зависимости от вашей версии trac.Чтобы получить соответствующую версию, SVN проверьте папку:http://svn.edgewall.com/repos/trac/branches/xxx-stable/contrib, где xxx соответствует используемой вами версии TRAC, например:0,11 дюйма

Оттуда скачайте файл «trac-post-commit-hook» и поместите его в папку «hooks».

Отредактируйте эти строки в trac-post-commit.cmd.

SET PYTHON_PATH="Путь к папке установки Python"

Установите trac_env = "Путь к папке, где вы сделали Tracd in in intenv"

Помните, не последний\!!!

Я удалил кавычки из последней строки -r "%REV%", чтобы она была -r %REV%, но я не знаю, нужно ли это.Сейчас это не будет работать (по крайней мере, на моем сервере с Win 2008), потому что перехват не удастся (фиксация пройдет нормально).Это связано с разрешениями.По умолчанию разрешения ограничены, и нам нужно разрешить python, svn или trac (что я не знаю) изменять информацию отслеживания.Итак, перейдите в папку trac, папку проекта, папку db, щелкните правой кнопкой мыши trac.db и выберите свойства.Перейдите на вкладку «Безопасность» и измените разрешения, чтобы предоставить всем полный доступ.Это не так безопасно, но я потратил весь день на этот вопрос безопасности, и я не хочу тратить еще один только на то, чтобы найти, для какого пользователя вам следует включить разрешения.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top