8a9e92fe51
X-SVN-Rev: 29371
171 lines
6.7 KiB
Python
Executable File
171 lines
6.7 KiB
Python
Executable File
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
|
|
# Author: <srl@icu-project.org>
|
|
#
|
|
|
|
#
|
|
# Ticket management.
|
|
# This component manages the revision to ticket map.
|
|
|
|
|
|
|
|
from trac.core import Component, implements, TracError
|
|
from trac.env import IEnvironmentSetupParticipant
|
|
from trac.db import Table, Column, Index, DatabaseManager
|
|
from trac.config import Option
|
|
from trac.util.text import exception_to_unicode
|
|
|
|
import re
|
|
|
|
tktmgr_schema = [
|
|
Table('rev2ticket', key='rev')[ # map rev->ticket
|
|
Column('rev', type='int'), # changeset id
|
|
Column('ticket', type='int'), # ticket #
|
|
Index(['ticket'])], # index by ticket
|
|
]
|
|
|
|
class TicketManager(Component):
|
|
implements(IEnvironmentSetupParticipant)
|
|
# implements(IEnvironmentSetupParticipant, IRepositoryObserver)
|
|
|
|
ticket_pattern = Option('icucodetools', 'ticket_pattern', '^ticket:(\d+)',
|
|
"""A regex matching the commit messages. Group 1 must return a number.""")
|
|
|
|
def icu_tktmgr(self):
|
|
return 1;
|
|
|
|
known_youngest = -1
|
|
|
|
def environment_created(self):
|
|
db = self.env.get_db_cnx()
|
|
connector, _ = DatabaseManager(self.env)._get_connector()
|
|
cursor = db.cursor()
|
|
for table in tktmgr_schema:
|
|
for stmt in connector.to_sql(table):
|
|
cursor.execute(stmt)
|
|
|
|
cursor.execute("INSERT INTO system (name,value) "
|
|
"VALUES ('icu_tktmgr',%s)", (self.icu_tktmgr(),))
|
|
db.commit()
|
|
self.log.info('Database update: icu_tktmgr tables version %d ',
|
|
self.icu_tktmgr())
|
|
print 'icucodetools.ticketmgr: Note, first review will take a while.\n'
|
|
|
|
def youngest_rev(self,db):
|
|
if (self.known_youngest < 0):
|
|
#print('Did not know youngest value.')
|
|
cursor = db.cursor()
|
|
cursor.execute("SELECT value FROM system WHERE name='icu_tktmgr_youngest'")
|
|
row = cursor.fetchone()
|
|
if not row:
|
|
cursor.execute("INSERT INTO system (name,value) "
|
|
"VALUES ('icu_tktmgr_youngest','-1')")
|
|
db.commit()
|
|
self.known_youngest = -2
|
|
return -1
|
|
else:
|
|
known_youngest = int(row[0])
|
|
self.known_youngest = known_youngest
|
|
return self.known_youngest
|
|
|
|
def check_sync(self, log, db, repos):
|
|
ourYoungest = self.youngest_rev(db)
|
|
theirYoungest = repos.get_youngest_rev()
|
|
#log.info("TKT: check_sync %d/%d" % (ourYoungest,theirYoungest))
|
|
if(ourYoungest <= theirYoungest):
|
|
self.resync(log, db, repos, ourYoungest, theirYoungest)
|
|
|
|
def environment_needs_upgrade(self, db):
|
|
cursor = db.cursor()
|
|
cursor.execute("SELECT value FROM system WHERE name='icu_tktmgr'")
|
|
row = cursor.fetchone()
|
|
if not row or int(row[0]) < self.icu_tktmgr():
|
|
return True
|
|
|
|
def upgrade_environment(self, db):
|
|
cursor = db.cursor()
|
|
cursor.execute("SELECT value FROM system WHERE name='icu_tktmgr'")
|
|
row = cursor.fetchone()
|
|
if not row:
|
|
self.environment_created()
|
|
else:
|
|
self.log.info('Do not know how to upgrade icutraxctn_ticketmgr tables to %d',
|
|
self.icu_tktmgr())
|
|
cursor.close()
|
|
|
|
def resync(self, log, db, repos, ourYoungest, theirYoungest):
|
|
self.log.info('resync: ourYoungest=%d theirYoungest=%d' % (ourYoungest, theirYoungest))
|
|
if (ourYoungest < 0):
|
|
# start at rev 1
|
|
ourYoungest = 1
|
|
|
|
#self.ticket_pattern = self.env.config.get('icucodetools', 'ticket_pattern', '^cldrbug (\d+):')
|
|
|
|
# log.info("Pat: %s" % (self.ticket_pattern))
|
|
try:
|
|
self.ticket_match = re.compile(self.ticket_pattern)
|
|
except Exception, e:
|
|
found = self.env.config.get('icucodetools', 'ticket_pattern', 'NoneFound')
|
|
raise TracError('Could not compile icucodetools.ticket_pattern=/%s/ but /%s/: %s' % (self.ticket_pattern, found, exception_to_unicode(e, traceback=True)))
|
|
|
|
# self.ticket_match = re.compile(self.ticket_pattern.get())
|
|
# self.ticket_match = re.compile('.*')
|
|
for i in range(ourYoungest, theirYoungest+1):
|
|
#log.warning('syncing: %d [%d/%d+1]', i, theirYoungest)
|
|
cset = repos.get_changeset(i)
|
|
self.revision_changed(log, cset, i, db.cursor())
|
|
db.commit()
|
|
cursor = db.cursor();
|
|
cursor.execute("update system set value='%s' where name='icu_tktmgr_youngest'" % (theirYoungest))
|
|
db.commit()
|
|
#log.warn("self.known_youngest was %d [%d/%d]" % (self.known_youngest,ourYoungest,theirYoungest))
|
|
# update known youngest.
|
|
self.known_youngest = theirYoungest
|
|
#log.warn("self.known_youngest now %d [%d/%d]" % (self.known_youngest,ourYoungest,theirYoungest))
|
|
return
|
|
|
|
# IRepositoryObserver methods
|
|
def revision_changed(self, log, cset, next_youngest, cursor):
|
|
# sync the 'rev2ticket' table
|
|
message = cset.message or '--'
|
|
# can we load a ticket from it? "ticket:1234: Message"
|
|
res = self.ticket_match.match(message)
|
|
if res:
|
|
tickname = res.group(1)
|
|
try:
|
|
int(res.group(1)) # should be int
|
|
except Exception, e:
|
|
log.warning('Revision [%s] had unparseable ticket number [%s]: [%s]' %
|
|
(next_youngest, tickname, e))
|
|
return
|
|
try:
|
|
#log.warning('r%s=#%s' % (str(next_youngest), tickname))
|
|
cursor.execute("INSERT OR IGNORE INTO rev2ticket "
|
|
" (rev,ticket) "
|
|
"VALUES (%s,%s) ",
|
|
(str(next_youngest), tickname))
|
|
except Exception, e: # *another* 1.1. resync attempt won
|
|
log.warning('rev2ticket %s could not cache: %s' %
|
|
(next_youngest, e))
|
|
else:
|
|
log.warning('Revision %s had unmatched message %s' %
|
|
(next_youngest, cset.message))
|
|
|
|
def repository_resync(self, cursor):
|
|
cursor.execute("DELETE FROM rev2ticket");
|
|
|
|
def tkt2revs(self, log, db, repos, req, ticket):
|
|
"""Given a ticket, return a list of revs.
|
|
"""
|
|
|
|
self.check_sync(log, db, repos)
|
|
cursor = db.cursor()
|
|
cursor.execute("select rt.rev from rev2ticket as rt where rt.ticket = %d order by rt.rev" % int(ticket))
|
|
revs = []
|
|
for rev, in cursor:
|
|
rev = int(rev)
|
|
revs.append(rev)
|
|
cursor.close()
|
|
return revs
|