Edgewall Software

Ticket #1602: trac-pre-commit-hook_4bat

File trac-pre-commit-hook_4bat, 3.0 KB (added by coreywangler@…, 3 years ago)

renamed python script given in #897

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