Software Freedom Law Center

root/trunk/trac/contrib/trac-post-commit-hook

Revision 57, 7.8 kB (checked in by bkuhn, 10 months ago)

r60@hughes: bkuhn | 2008-03-19 17:59:34 -0400

  • Brought in sync with r6719 of Trac upstream, which was accomplished via:

svk smerge /loblaw/local/branches/trac.upstream-r6719 .

  • Property svn:executable set to *
Line 
1 #!/usr/bin/env python
2
3 # trac-post-commit-hook
4 # ----------------------------------------------------------------------------
5 # Copyright (c) 2004 Stephen Hansen
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to
9 # deal in the Software without restriction, including without limitation the
10 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11 # sell copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 #   The above copyright notice and this permission notice shall be included in
15 #   all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 # IN THE SOFTWARE.
24 # ----------------------------------------------------------------------------
25
26 # This Subversion post-commit hook script is meant to interface to the
27 # Trac (http://www.edgewall.com/products/trac/) issue tracking/wiki/etc
28 # system.
29 #
30 # It should be called from the 'post-commit' script in Subversion, such as
31 # via:
32 #
33 # REPOS="$1"
34 # REV="$2"
35 #
36 # /usr/bin/python /usr/local/src/trac/contrib/trac-post-commit-hook \
37 #  -p "$TRAC_ENV" -r "$REV"
38 #
39 # (all the other arguments are now deprecated and not needed anymore)
40 #
41 # It searches commit messages for text in the form of:
42 #   command #1
43 #   command #1, #2
44 #   command #1 & #2
45 #   command #1 and #2
46 #
47 # Instead of the short-hand syntax "#1", "ticket:1" can be used as well, e.g.:
48 #   command ticket:1
49 #   command ticket:1, ticket:2
50 #   command ticket:1 & ticket:2
51 #   command ticket:1 and ticket:2
52 #
53 # In addition, the ':' character can be omitted and issue or bug can be used
54 # instead of ticket.
55 #
56 # You can have more then one command in a message. The following commands
57 # are supported. There is more then one spelling for each command, to make
58 # this as user-friendly as possible.
59 #
60 #   close, closed, closes, fix, fixed, fixes
61 #     The specified issue numbers are closed with the contents of this
62 #     commit message being added to it.
63 #   references, refs, addresses, re, see
64 #     The specified issue numbers are left in their current status, but
65 #     the contents of this commit message are added to their notes.
66 #
67 # A fairly complicated example of what you can do is with a commit message
68 # of:
69 #
70 #    Changed blah and foo to do this or that. Fixes #10 and #12, and refs #12.
71 #
72 # This will close #10 and #12, and add a note to #12.
73
74 import re
75 import os
76 import sys
77 from datetime import datetime
78
79 from trac.env import open_environment
80 from trac.ticket.notification import TicketNotifyEmail
81 from trac.ticket import Ticket
82 from trac.ticket.web_ui import TicketModule
83 # TODO: move grouped_changelog_entries to model.py
84 from trac.util.text import to_unicode
85 from trac.util.datefmt import utc
86 from trac.versioncontrol.api import NoSuchChangeset
87
88 from optparse import OptionParser
89
90 parser = OptionParser()
91 depr = '(not used anymore)'
92 parser.add_option('-e', '--require-envelope', dest='envelope', default='',
93                   help="""
94 Require commands to be enclosed in an envelope.
95 If -e[], then commands must be in the form of [closes #4].
96 Must be two characters.""")
97 parser.add_option('-p', '--project', dest='project',
98                   help='Path to the Trac project.')
99 parser.add_option('-r', '--revision', dest='rev',
100                   help='Repository revision number.')
101 parser.add_option('-u', '--user', dest='user',
102                   help='The user who is responsible for this action '+depr)
103 parser.add_option('-m', '--msg', dest='msg',
104                   help='The log message to search '+depr)
105 parser.add_option('-c', '--encoding', dest='encoding',
106                   help='The encoding used by the log message '+depr)
107 parser.add_option('-s', '--siteurl', dest='url',
108                   help=depr+' the base_url from trac.ini will always be used.')
109
110 (options, args) = parser.parse_args(sys.argv[1:])
111
112
113 ticket_prefix = '(?:#|(?:ticket|issue|bug)[: ]?)'
114 ticket_reference = ticket_prefix + '[0-9]+'
115 ticket_command =  (r'(?P<action>[A-Za-z]*).?'
116                    '(?P<ticket>%s(?:(?:[, &]*|[ ]?and[ ]?)%s)*)' %
117                    (ticket_reference, ticket_reference))
118
119 if options.envelope:
120     ticket_command = r'\%s%s\%s' % (options.envelope[0], ticket_command,
121                                     options.envelope[1])
122    
123 command_re = re.compile(ticket_command)
124 ticket_re = re.compile(ticket_prefix + '([0-9]+)')
125
126 class CommitHook:
127     _supported_cmds = {'close':      '_cmdClose',
128                        'closed':     '_cmdClose',
129                        'closes':     '_cmdClose',
130                        'fix':        '_cmdClose',
131                        'fixed':      '_cmdClose',
132                        'fixes':      '_cmdClose',
133                        'addresses':  '_cmdRefs',
134                        're':         '_cmdRefs',
135                        'references': '_cmdRefs',
136                        'refs':       '_cmdRefs',
137                        'see':        '_cmdRefs'}
138
139     def __init__(self, project=options.project, author=options.user,
140                  rev=options.rev, url=options.url):
141         self.env = open_environment(project)
142         repos = self.env.get_repository()
143         repos.sync()
144        
145         # Instead of bothering with the encoding, we'll use unicode data
146         # as provided by the Trac versioncontrol API (#1310).
147         try:
148             chgset = repos.get_changeset(rev)
149         except NoSuchChangeset:
150             return # out of scope changesets are not cached
151         self.author = chgset.author
152         self.rev = rev
153         self.msg = "(In [%s]) %s" % (rev, chgset.message)
154         self.now = datetime.now(utc)
155
156         cmd_groups = command_re.findall(self.msg)
157
158         tickets = {}
159         for cmd, tkts in cmd_groups:
160             funcname = CommitHook._supported_cmds.get(cmd.lower(), '')
161             if funcname:
162                 for tkt_id in ticket_re.findall(tkts):
163                     func = getattr(self, funcname)
164                     tickets.setdefault(tkt_id, []).append(func)
165
166         for tkt_id, cmds in tickets.iteritems():
167             try:
168                 db = self.env.get_db_cnx()
169                
170                 ticket = Ticket(self.env, int(tkt_id), db)
171                 for cmd in cmds:
172                     cmd(ticket)
173
174                 # determine sequence number...
175                 cnum = 0
176                 tm = TicketModule(self.env)
177                 for change in tm.grouped_changelog_entries(ticket, db):
178                     if change['permanent']:
179                         cnum += 1
180                
181                 ticket.save_changes(self.author, self.msg, self.now, db, cnum+1)
182                 db.commit()
183                
184                 tn = TicketNotifyEmail(self.env)
185                 tn.notify(ticket, newticket=0, modtime=self.now)
186             except Exception, e:
187                 # import traceback
188                 # traceback.print_exc(file=sys.stderr)
189                 print>>sys.stderr, 'Unexpected error while processing ticket ' \
190                                    'ID %s: %s' % (tkt_id, e)
191            
192
193     def _cmdClose(self, ticket):
194         ticket['status'] = 'closed'
195         ticket['resolution'] = 'fixed'
196
197     def _cmdRefs(self, ticket):
198         pass
199
200
201 if __name__ == "__main__":
202     if len(sys.argv) < 5:
203         print "For usage: %s --help" % (sys.argv[0])
204         print
205         print "Note that the deprecated options will be removed in Trac 0.12."
206     else:
207         CommitHook()
Note: See TracBrowser for help on using the browser.

SFLC Main Page

[frdm] Support SFLC