Edgewall Software

Ticket #1602: trac-pre-commit-hook_4bat.2

File trac-pre-commit-hook_4bat.2, 3.0 KB (added by Denney <denney@…>, 6 years ago)

Updated to work with Trac 0.9-stable

Line 
1#!/usr/bin/env python
2# -*- coding: iso8859-1 -*-
3#
4# Author: Jonas Borgström <jonas@edgewall.com>
5#
6# This script will enforce the following policy:
7#
8#  "A checkin must reference an open ticket."
9#
10# This script should be invoked from the subversion pre-commit hook like this:
11#
12#  REPOS="$1"
13#  TXN="$2"
14#  TRAC_ENV="/somewhere/trac/project/"
15#  LOG=`/usr/bin/svnlook log -t "$TXN" "$REPOS"`
16#  /usr/bin/python /some/path/trac-pre-commit-hook "$TRAC_ENV" "$LOG" || exit 1
17#
18# WINDOWS: sample of pre-commit.bat (must use temporary files for the log message)
19#
20##SET REPOS=%1
21##SET TXN=%2
22##
23##::-----------------------------
24##::Call the TRAC pre-commit hook
25##::
26##SET TRAC_ENV=C:\somewhere\trac\project
27##SET LOG_FILE=%TEMP%.\svnfileT-%TXN%
28##
29##svnlook log -t %TXN% %REPOS%>%LOG_FILE%
30##
31##python [trac-path]\contrib\trac-pre-commit-hook "%TRAC_ENV%" "file:%LOG_FILE%"
32##IF ERRORLEVEL 1 SET TRAC_CANCEL=YES
33##DEL %LOG_FILE%
34##IF DEFINED TRAC_CANCEL GOTO :ERROR
35##::
36##::-----------------------------
37##
38##:SUCCESS
39##EXIT 0
40##
41##:ERROR
42##EXIT 1
43##
44
45import os
46import re
47import sys
48
49from trac.env import open_environment
50
51def main():
52    if len(sys.argv) != 3:
53        print >> sys.stderr, 'Usage: %s <trac_project> <log_message>' % sys.argv[0]
54        sys.exit(1)
55
56    env_path = sys.argv[1]
57    log = sys.argv[2]
58    log = _readFromFile( log )
59
60    tickets = []
61    for tmp in re.findall('(?:closes|fixes|addresses|references|refs|re)'
62                          '.?(#[0-9]+(?:(?:[, &]+| *and *)#[0-9]+)*)', log):
63        tickets += re.findall('#([0-9]+)', tmp)
64   
65    # At least one ticket has to be mentioned in the log message
66    if tickets == []:
67        print >> sys.stderr, 'At least one open ticket must be mentioned ' \
68              'in the log message.'
69        sys.exit(1)
70
71    env = open_environment(env_path)
72    db = env.get_db_cnx()
73
74    cursor = db.cursor()
75    cursor.execute("SELECT COUNT(id) FROM ticket WHERE "
76                   "status <> 'closed' AND id IN (%s)" % ','.join(tickets))
77    row = cursor.fetchone()
78    # At least one of the tickets mentioned in the log messages has to
79    # be open
80    if not row or row[0] < 1:
81        print >> sys.stderr, 'At least one open ticket must be mentioned ' \
82              'in the log message.'
83        sys.exit(1)
84    else:
85        sys.exit(0)
86
87def _readFromFile(message):
88    """ Ivan Melnychuk: SOLUTION FOR WINDOWS SYSTEMS:
89    Windows does not support returning values from script.
90    Therefore temporary files may be used to keep some information like commit message
91    If the 'message' starts with 'file:', and the file with indicated name exists, then read the text message from the file rather then using the text directly
92    Even though actual message also may start with such prefix, it is very unlikely that the file exists with such a name by accident
93    """
94    if message[:5] == 'file:' and os.path.exists( message[5:] ):
95        f = open( message[5:], 'r' )
96        message = f.read()
97        f.close()
98        return message
99    return message;
100
101if __name__ == '__main__':
102    main()
103
104
105