- two readmes, because users typically have the 0.11 and 0.12 directories checked out.
X-SVN-Rev: 40821
tools/release/java/src/com/ibm/icu/dev/tools/docs/genreport_xml.xslt -text
tools/scripts/icurun -text
tools/scripts/reticket -text
-tools/trac/IcuCodeTools/0.11/icucodetools/__init__.py -text
-tools/trac/IcuCodeTools/0.11/icucodetools/dcut.py -text
-tools/trac/IcuCodeTools/0.11/icucodetools/htdocs/css/icuxtn.css -text
-tools/trac/IcuCodeTools/0.11/icucodetools/htdocs/js/review.js -text
-tools/trac/IcuCodeTools/0.11/icucodetools/review.py -text
-tools/trac/IcuCodeTools/0.11/icucodetools/templates/nothing.html -text
-tools/trac/IcuCodeTools/0.11/icucodetools/templates/review.html -text
-tools/trac/IcuCodeTools/0.11/icucodetools/ticketmgr.py -text
-tools/trac/IcuCodeTools/0.11/icucodetools/tktlist.py -text
-tools/trac/IcuCodeTools/0.11/license.html -text
-tools/trac/IcuCodeTools/0.11/readme.txt -text
-tools/trac/IcuCodeTools/0.11/setup.cfg -text
-tools/trac/IcuCodeTools/0.11/setup.py -text
-tools/trac/IcuCodeTools/0.12/icucodetools/__init__.py -text
-tools/trac/IcuCodeTools/0.12/icucodetools/dcut.py -text
-tools/trac/IcuCodeTools/0.12/icucodetools/htdocs/css/icuxtn.css -text
-tools/trac/IcuCodeTools/0.12/icucodetools/htdocs/js/review.js -text
-tools/trac/IcuCodeTools/0.12/icucodetools/review.py -text
-tools/trac/IcuCodeTools/0.12/icucodetools/templates/nothing.html -text
-tools/trac/IcuCodeTools/0.12/icucodetools/templates/review.html -text
-tools/trac/IcuCodeTools/0.12/icucodetools/ticketmgr.py -text
-tools/trac/IcuCodeTools/0.12/icucodetools/tktlist.py -text
-tools/trac/IcuCodeTools/0.12/icucodetools/traccheck.py -text
-tools/trac/IcuCodeTools/0.12/license.html -text
-tools/trac/IcuCodeTools/0.12/readme.txt -text
-tools/trac/IcuCodeTools/0.12/setup.cfg -text
-tools/trac/IcuCodeTools/0.12/setup.py -text
tools/unicodetools/com/ibm/rbm/docs/images/TitleLogo_transparent.gif -text
tools/unicodetools/com/ibm/rbm/docs/images/arrow_bullet.gif -text
tools/unicodetools/com/ibm/rbm/docs/images/diamond_bullet.gif -text
tools/release/java/Makefile.local
tools/release/java/classes
tools/release/java/lib
-tools/trac/IcuCodeTools/0.11/*.egg-info
-tools/trac/IcuCodeTools/0.11/build
-tools/trac/IcuCodeTools/0.11/icucodetools/*.pyc
-tools/trac/IcuCodeTools/0.12/*.egg-info
-tools/trac/IcuCodeTools/0.12/build
-tools/trac/IcuCodeTools/0.12/dist
-tools/trac/IcuCodeTools/0.12/icucodetools/*.pyc
tools/unicode/c/genprops/*.d
tools/unicode/c/genprops/*.ncb
tools/unicode/c/genprops/*.o
+++ /dev/null
-# -*- coding: utf-8 -*-
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
-#
-#
-#from icutracxtn.web_ui import *
+++ /dev/null
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
-
-import re
-
-from trac.core import *
-from trac.util import Markup
-from trac.web import IRequestHandler
-from trac.web.chrome import add_stylesheet, INavigationContributor, \
- ITemplateProvider
-from trac.web.href import Href
-#from trac.versioncontrol.web_ui.changeset import IChangesetRangeLink
-from trac.wiki import wiki_to_html, wiki_to_oneliner, IWikiSyntaxProvider, \
- Formatter
-
-
-class DcutModule(Component):
-
- implements(IRequestHandler)
-# implements(IRequestHandler,IChangesetRangeLink)
-
- def revision_range_link(self, req, base, start, end):
- return ('DCUT Helper', req.href('dcut',old_path=base,new_path=base,old=start,new=end))
-
- _request_re = re.compile(r"/dcut(?:/([^/]+))?(/.*)?$")
-
- def match_request(self, req):
- match = re.match(self._request_re, req.path_info)
- if match:
- return True
-
- def process_request(self, req):
-
- idx = 0
- # srl
-# show_files = self.timeline_show_files
- db = self.env.get_db_cnx()
- ticketlist = {} # dict of ticket->???
- revlist = {} # dict of revision->
- # well. check it again,.
-
- srldebug=False
-
- repos = self.env.get_repository(req.authname)
-
- new_path = req.args.get('new_path')
- new_rev = req.args.get('new')
- old_path = req.args.get('old_path')
- old_rev = req.args.get('old')
-
- new_path = repos.normalize_path(new_path)
- new_rev = repos.normalize_rev(new_rev)
- old_path = repos.normalize_path(old_path)
- old_rev = repos.normalize_rev(old_rev)
-
- old_rev = int(old_rev)
- new_rev = int(new_rev)
-
- req.hdf['changeset.diff_href'] = req.href('changeset',old_path=old_path,new=new_rev,new_path=new_path,old=old_rev)
-
- req.hdf['is_dcut']=1
-
- req.hdf['changeset.old_rev'] = old_rev
- req.hdf['changeset.new_rev'] = new_rev
- req.hdf['changeset.old_path'] = old_path
- req.hdf['changeset.new_path'] = new_path
-
- if True:
- req.hdf['target_path'] = '.';
- # okay. manually tromp through 'em
- nrev = old_rev+1
- while nrev <= new_rev:
- chgset = repos.get_changeset(nrev)
- message = chgset.message or '--'
- # can we load a ticket from it?
- splits=message.split(':')
- if message.startswith('ticket:') and len(splits)>2:
- tickname=splits[1]
- try:
- ticknum=int(tickname)
- except Exception,e:
- nrev = nrev+1
- continue
- # yes, we have a ticket #
- files=[]
- for chg in chgset.get_changes():
- if not chg[0].startswith(old_path):
- continue
- files.append(chg)
- if len(files)==0:
- nrev = nrev+1
- continue # no relevant files
- titem=(ticknum,files,chgset)
- if ticknum in ticketlist:
- ticketlist[ticknum].append( titem )
- else:
- ticketlist[ticknum]=[ titem ]
- revlist[nrev]=titem
- else:
- print "malformed ticket? %s at %d" % (message,nrev) # don't know the syntax for die..
- nrev = nrev+1
- if len(ticketlist):
- tickets=ticketlist.keys()
- tickets.sort()
- for ticket in tickets:
- aticket=ticketlist[ticket] # (ticket,files,chg)
- cmt = 'ticket:%d - %d revs: ' % (ticket,len(aticket))
- for rev in aticket:
- revn = rev[2].rev
- filecount = len(rev[1])
- cmt = cmt + 'r%d - %d files (' % (revn,filecount)
- for file in rev[1]:
- cmt = cmt + file[0] + ' '
- cmt = cmt + ') '
- req.hdf['tickets.%d.comment' % ticket] = wiki_to_oneliner(cmt, self.env, db, shorten=False)
- req.hdf['tickets.%d.number' % ticket] = ticket
- if len(revlist):
- revs=revlist.keys()
- revs.sort()
- for rev in revs:
- arev=revlist[rev] # (ticket,files,chg)
- cmt = 'r%d ticket:%d ' % (arev[2].rev,arev[0])
- filecount = len(arev[1])
- cmt = cmt + ' - %d files (' % filecount
- shortfiles=''
- j = 0
- for file in arev[1]:
- req.hdf['revs.%d.files.%d.path' % (rev,j)] = file[0]
- req.hdf['revs.%d.files.%d.kind' % (rev,j)] = file[1]
- req.hdf['revs.%d.files.%d.change' % (rev,j)] = file[2]
- shortpath=file[0][len(old_path)+1:]
- req.hdf['revs.%d.files.%d.shortpath' % (rev,j)] = shortpath
- cmt = cmt + file[0] + ' '
- shortfiles = shortfiles + ' ' + shortpath
- j=j+1
- cmt = cmt + ') '
- req.hdf['revs.%d.comment' % rev] = wiki_to_oneliner(cmt, self.env, db, shorten=False)
- req.hdf['revs.%d.number' % rev] = rev
- req.hdf['revs.%d.shortfiles' % rev] = shortfiles
- req.hdf['revs.%d.backnumber' % rev] = (rev-1)
- req.hdf['revs.%d.ticket' % rev] = arev[0]
-
-
-# if isinstance(template, basestring):
-# req.hdf['admin.page_template'] = template
-# else:
-# req.hdf['admin.page_content'] = Markup(template.render())
-
- content_type = "text/html"
- add_stylesheet(req, 'css/icuxtn.css')
- return 'dcut.cs', content_type
-
+++ /dev/null
-/* @override http://bugs.icu-project.org/trac/chrome/icucodetools/css/icuxtn.css */
-
-/* Copyright (C) 2010-2012 International Business Machines Corporation and Others. All Rights Reserved. */
-
-/* @override http://unicode.org/cldr/trac/chrome/icucodetools/css/icuxtn.css */
-
-
-table.icureview {
- border-collapse: collapse;
- border: 1px solid gray;
-}
-
-table.icureview th, table.icureview td {
- text-align: left;
- border: 1px solid gray;
- padding: 2px;
-}
-
-table.icureview thead th {
- font-weight: bold;
-}
-
-table.icureview td.changes {
- text-align: right;
-}
-
-table.icureview td.overall {
- background-color: silver;
- font-style: italic;
- text-align: right;
-}
-
-.branch-unknown {
- font-weight: normal;
- font-style: italic;
-}
-.branch-tags {
- font-weight: bold;
- font-family: Georgia, "Times New Roman", Times, serif;
- color: white;
- background-color: navy;
- padding: 1px;
-}
-.branch-branches {
- font-weight: normal;
- color: #353;
-}
-
-.branch-trunk {
- font-weight: bold;
-}
-
-
+++ /dev/null
-// Copyright (C) 2007-2012 IBM and Others. All Rights Reserved
-
- var setBranchNames = function() {
- var cst = document.getElementById("changesettable");
- var trs=cst.getElementsByTagName("tr");
- for( i=1 ; i < trs.length ; i++ ) {
- var sec = trs[i].getElementsByTagName('td')[1]; // [0] is 'author', [1] is section.
- var brk = sec.getElementsByTagName('a');
- for(j=0;j<brk.length;j++) {
- var bri = brk[j];
- var str = bri.innerHTML;
- if(str.indexOf("trunk")>-1) {
- bri.className = 'branch-trunk';
- } else if(str.indexOf("branches")>-1) {
- bri.className = 'branch-branches';
- } else if(str.indexOf("tags")>-1) {
- bri.className = 'branch-tags';
- }
- }
- }
- }
-
-// http://ckon.wordpress.com/2008/07/25/stop-using-windowonload-in-javascript/
-if (window.attachEvent) {window.attachEvent('onload', setBranchNames);}
-else if (window.addEventListener) {window.addEventListener('load', setBranchNames, false);}
-else {document.addEventListener('load', setBranchNames, false);}
-
+++ /dev/null
-# Copyright (C) 2007-2012 International Business Machines Corporation and Others. All Rights Reserved.
-
-# Review module.
-# TODO: refactor ticket manipulation items into ticketmgr.
-
-import re
-
-from trac.core import Component, implements
-from trac.core import ComponentManager
-from trac.core import TracError
-from trac.util import Markup
-from trac.web import IRequestHandler
-from trac.web.chrome import add_stylesheet, add_script, ITemplateProvider, add_ctxtnav
-from trac.versioncontrol import Changeset
-from trac.web.api import IRequestFilter
-from trac.wiki import wiki_to_html, wiki_to_oneliner, IWikiSyntaxProvider
-
-from genshi.builder import tag
-#from trac.env import IEnvironmentSetupParticipant
-from trac.perm import IPermissionRequestor
-from trac.config import ListOption
-from icucodetools.ticketmgr import TicketManager
-from pkg_resources import resource_filename #@UnresolvedImport
-
-class ReviewModule(Component):
-
- implements(ITemplateProvider, IRequestFilter, IRequestHandler, IPermissionRequestor)
-
- # path to match for review
- path_match = re.compile(r'/icureview/([0-9]+)')
-
- voteable_paths = ListOption('icucodetools', 'paths', '/ticket*',
- doc='List of URL paths to show reviews on. Globs are supported.')
-
- # search for earliest match, and how many segments to include following
- # trunk
- # branches/maint/maint-4-8
- # tags/release-2-0
- branchList = [['trunk',0],['branches',2],['tags',1]]
-
- # IPermissionRequestor methods
- def get_permission_actions(self):
- return ['ICUREVIEW_VIEW']
-
- # ITemplateProvider methods
- def get_templates_dirs(self):
- try:
- return [resource_filename(__name__, 'templates')]
- except Exception, e:
- self.log.warning('Could not get template dir: %s: %s' %
- (type(e), e))
- return ""
-
-
- def get_htdocs_dirs(self):
- return [('icucodetools', resource_filename(__name__, 'htdocs'))]
-
- # IRequestFilter methods
- def pre_process_request(self, req, handler):
- if 'ICUREVIEW_VIEW' not in req.perm:
- return handler
-
- if self.match_ticketpage(req):
- self.render_reviewlink(req)
-
- return handler
-
- def post_process_request(self, req, template, data, content_type):
- return (template, data, content_type)
-
- def render_reviewlink(self, req):
- #add_stylesheet(req, 'icucodetools/css/icuxtn.css')
-
- els = []
-
- ticket_mgr = TicketManager(self.compmgr)
-
- db = self.env.get_db_cnx()
- repos = self.env.get_repository()
- if not repos:
- raise TracError("Could not get repository for %s" % (req.authname))
-
- revs = ticket_mgr.tkt2revs(self.log, db, repos, req, req.args['ticket'])
-
- if not revs:
- str = 'No commits.'
- li = tag.li(str)
- els.append(li)
- else:
- str = ' %d commits.' % len(revs)
- href = req.href.review(req.args['ticket'])
- a = tag.a('Review', href=href)
- li = tag.li(a + str)
- els.append(li)
-
- ul = tag.ul(els, class_='review')
- className = ''
- title = "Reviews"
- add_ctxtnav(req, tag.span(tag.object(ul), id='icureview', title=title, class_=className))
-
-
- def match_request(self, req):
- match = re.match('/review(?:/([^/]+))?(?:/([^/]+))?(?:/(.*)$)?', req.path_info)
- if match:
- req.args['ticket'] = match.group(1)
- return True
-
- def match_ticketpage(self, req):
- match = re.match('/ticket(?:/([^/]+))?(?:/([^/]+))?(?:/(.*)$)?', req.path_info)
- if match:
- req.args['ticket'] = match.group(1)
- return True
-
- def pathToBranchName(self, path):
- #return '/'.join(path.split('/')[0:2])
- windex = None
- win = None
- for branch in self.branchList:
- if(path == branch[0]): # catch changes to just 'trunk'
- idx = 0
- else:
- idx = path.find(branch[0]+'/')
- if(idx > -1 and (windex == None or windex > idx)):
- windex = idx
- win = branch
- if windex == None:
- segments = path.split('/')
- return '/'.join(segments[0:2])
- else:
- #print "found %s foll %s @ %d" % (win[0],win[1],windex)
- segments = path[windex:].split('/')
- return path[:windex] + ('/'.join(segments[0:win[1]+1])) # use specified # of following segments
-
- def changeToRange(self, c_new, change):
- # q: (u'trunk/Locale.java', 'file', 'add', None, u'-1') from r3
- # q: (u'trunk/util.c', 'file', 'edit', u'trunk/util.c', u'2') from r4
-# c_path = change[0]
-# c_itemtype = change[1]
- c_type = change[2]
- c_oldpath = change[3]
- c_old = int(change[4] or -1)
- if(c_type in (Changeset.COPY,Changeset.MOVE)):
- return (-1, c_new, c_type, c_old, c_oldpath) # ignore OLD rev for these
- elif(c_type in (Changeset.DELETE)):
- return (c_old, -1, c_type)
- else:
- return (c_old, c_new, c_type)
-
- def describeChange(self, file, change, req, db):
- what = change[2] or 'change'
- where = 'r%d:%d' % (change[0],change[1])
- if(change[0] == -1):
- if(change[1] == -1):
- url = None
- what = "noop"
- where = None
- else:
- #if change[2] == 'add+commits':
- url = req.href.browser(file, rev=change[1]) # 'add'
- where = 'r%d' % change[1]
- what = change[2]
- elif(change[1] == -1):
- url = None # deleted
- what = "deleted"
- where = None
- else:
- url = req.href.changeset(old_path=file, old=change[0], new_path=file, new=change[1])
- if url:
- what = Markup('<a href="%s">%s</a>' % (url,what))
- if where:
- return (what, tag.a(where, href=req.href.search(q=where)))
- #return (what, where)
- else:
- return (what, '')
-
-
- def process_request(self, req):
- #ok, what are we about.
- #db = self.env.get_db_cnx()
- #ticketlist = {} # dict of ticket->???
- #revlist = {} # dict of revision->
- repos = self.env.get_repository()
-
- new_path = req.args.get('new_path')
- new_rev = req.args.get('new')
- old_path = req.args.get('old_path')
- old_rev = req.args.get('old')
-
- new_path = repos.normalize_path(new_path)
- new_rev = repos.normalize_rev(new_rev)
- old_path = repos.normalize_path(old_path)
- old_rev = repos.normalize_rev(old_rev)
-
-
-# if not req.perm.has_permission('TICKET_MODIFY'):
-# return req.redirect(req.href.browser())
-
- old_rev = int(old_rev)
- new_rev = int(new_rev)
-
- ticket = req.args.get('ticket')
- try:
- ticket = int(ticket)
- except Exception:
- ticket = 0
-# req.hdf['review.ticket'] = ticket
-# req.hdf['review.tickethtml'] = tag.a(ticket, req.href.ticket(ticket))
-
- data = {}
-
- data['overall_y'] = 0
- data['ticket_id'] = req.args['ticket']
- data['ticket_href'] = req.href.ticket(req.args['ticket'])
-
- ticket_mgr = TicketManager(self.compmgr)
-
- db = self.env.get_db_cnx()
- repos = self.env.get_repository()
-
- revs = ticket_mgr.tkt2revs(self.log, db, repos, req, req.args['ticket'])
-
- if (not revs or len(revs)==0):
- # nothing to review. shouldn't happen
- return ('nothing.html', data, 'text/html')
- elif(len(revs)==1):
- # only one change - just do a changeset view
- return req.redirect(req.href.changeset(revs[0]))
-
- revcount = 0
- branches = {}
- files = {}
- # may be 0 revs.
- revisions = []
-
- for rev in revs:
- chgset = repos.get_changeset(rev)
- # q: (u'trunk/Locale.java', 'file', 'add', None, u'-1') from r3
- # q: (u'trunk/util.c', 'file', 'edit', u'trunk/util.c', u'2') from r4
- message = chgset.message or '--'
- revcount = revcount + 1
- revision = {}
- revision['rev'] = tag.a(rev, req.href.changeset(rev))
- revision['author'] = chgset.author
- revision['num'] = rev
- revision['comment'] = message #wiki_to_oneliner( message, self.env, db, shorten=False )
- rbranches = revision['branches'] = []
- for chg in chgset.get_changes():
- path = chg[0]
- if path in files:
- item = files[path]
- else:
- item = []
- files[path] = item;
- item.append(self.changeToRange(rev,chg))
- branch_name = self.pathToBranchName(path)
- if branch_name not in rbranches:
- rbranches.append(branch_name)
- revisions.append(revision)
- data['revisions'] = revisions
-
- if(revcount > 0):
- data['revcount'] = revcount
-
- # print "files: %d" % len(files)
- # go throuhg each file and calculate its minimum range
- filelist = files.keys()
- filelist.sort()
-# print 'bar to %d len of %s' % (len(filelist),str(filelist))
- for file in filelist:
- changes = files[file]
- i = 0
-# print " looping from %d to %d over %d " % (i,len(changes)-1,len(changes))
- while len(changes)>1 and i<(len(changes)-1):
- if changes[i][1] == changes[i+1][0]:
- if changes[i][0] == -1:
- changes[i+1] = (changes[i][0],changes[i+1][1],'add+commits') # retain 'first' rev
- else:
- changes[i+1] = (changes[i][0],changes[i+1][1],'multiple commits') # retain 'first' rev
-
- changes = changes[:i] + changes[i+1:] # and shift down
-# print "merged: %s" % str(changes)
- files[file] = changes
- else:
- i = i + 1
-
- # now, write 'em out
- sera = 0
- #files_data = []
- for file in filelist:
- sera = sera+1
- file_data = {}
- file_data['name'] = Markup('<a href="%s">%s</a>' % (req.href.browser(file),file))
- branch_name = self.pathToBranchName(file)
- #print "branch is: (%s)" % (branch_name)
- branches_data = branches.get(branch_name, {})
- files_data = branches_data.get('files',[])
-
- changes = files[file]
- cha = 0
- changes_data = []
- for change in changes:
- cha = cha + 1
-# print "%s output %s " % (file, str(change))
- changes_data.append(self.describeChange(file, change, req, db))
- file_data['changes'] = changes_data
- if(len(changes)>1):
- whathtml = self.describeChange(file, (changes[0][0], changes[len(changes)-1][1], 'overall'), req, db)
- file_data['overall'] = whathtml
- file_data['overall_y'] = 1
- data['overall_y'] = 1
- else:
- file_data['overall_y'] = 0
- files_data.append(file_data)
- # sets
- branches_data['files'] = files_data
- branches_data['len'] = len(files_data)
- branches_data['name'] = branch_name
- branches[branch_name] = branches_data
-
- # .. convert dict to array.
- branch_list = []
- for branch in branches:
- branch_list.append(branches[branch])
- data['branches'] = branch_list
- data['lastbranch'] = branch
- data['branchcount'] = len(branches)
-
- content_type = "text/html"
- add_stylesheet(req, 'icucodetools/css/icuxtn.css')
- add_script(req, 'icucodetools/js/review.js')
- return 'review.html', data, content_type
-
+++ /dev/null
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<!--
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
--->
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="layout.html" />
- <head>
- <title>Nothing to Review for ticket #${ticket_id}</title>
- </head>
-
- <body>
- <div id="ctxtnav" class="nav"></div>
-
- <div id="content" class="icucodereview">
- <h1>Nothing to review!</h1>
- <p>
- Nothing to review - no changesets in ticket <a href="${ticket_href}">#${ticket_id}</a>
- </p>
- </div>
- </body>
-</html>
+++ /dev/null
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<!--
-# Copyright (C) 2007-2012 IBM and Others. All Rights Reserved
--->
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="layout.html" />
- <head>
- <title>Review for ticket #${ticket_id}</title>
- </head>
-
- <body>
- <div id="ctxtnav" class="nav"></div>
-
- <div id="content" class="icucodereview">
-
-
- <h1>Ticket <a href='${href.ticket(ticket_id)}'>#${ticket_id}</a></h1>
-
-<py:if test="revcount">
-
- <h2>${revcount} Changesets</h2>
- <table id='changesettable' class='icureview'>
- <thead>
- <tr>
- <th>r</th>
- <th>author</th>
- <th>section(s)</th>
- <th>comment</th>
- </tr>
- </thead>
- <tbody>
- <py:for each="rev in revisions">
- <tr>
- <th>
- <a href="${href.changeset(rev.num)}">r${rev.num}</a>
- </th>
- <td>
- ${rev.author}
- </td>
- <td>
- <!-- sections -->
- <py:for each="branch in rev.branches">
- <b class='branchlist'>
- <a class='branch-unknown' href="#${branch}">${branch}</a>
- </b>
- </py:for>
- </td>
- <td>
- ${rev.comment}
- </td>
- </tr>
- </py:for>
- </tbody>
- </table>
-
-<py:if test="branchcount > 1">
-<h2>Files</h2>
-<h3>Jump to Sections</h3>
-<ul>
-<py:for each="branch in branches">
- <li><a href="#${branch.name}">${branch.name}</a> — ${branch.len} files</li>
-</py:for>
-</ul>
-</py:if>
-
-<py:for each="branch in branches">
-<hr/>
-<a name="${branch.name}">
- <h3>
- <a href="${href.browser(branch.name)}">${branch.name}</a> — (${branch.len} files changed)
- </h3>
-</a>
-
-<blockquote>
-
-<table class='icureview'>
-<thead>
-<tr>
- <th>File</th>
- <th>Changes</th>
- <th>Details</th>
- <py:if test="overall_y > 0">
- <th>Overall<br/><i>(including other changes)</i></th>
- <th>Details</th>
- </py:if>
-</tr>
-</thead>
-<tbody>
-<py:for each="file in branch.files">
- <tr>
- <th class='name'>${file.name}</th>
- <td class='changes'>
- <py:for each="change in file.changes">
- ${change[0]}<br/>
- </py:for>
- </td>
- <td class='details'>
- <py:for each="change in file.changes">
- ${change[1]}<br/>
- </py:for>
- </td>
-
- <py:if test="overall_y > 0">
- <py:if test="file.overall_y > 0">
- <td class='overall'>${file.overall[0]}</td>
- <td class='overall'>${file.overall[1]}</td>
- </py:if>
- </py:if>
- </tr>
-</py:for>
-</tbody>
-</table>
-
-</blockquote>
-
-</py:for>
-
-<hr/>
-
-<div style='display:none;'>
-<h2>Merge Commands</h2>
-Very experimental. Change ??? to the top of the tree you want to merge from (icu or icu4j)<br/>
-<textarea>svn merge -c <?cs each:rev = revisions ?><?cs var:rev.num ?>,<?cs /each ?> svn+ssh://source.icu-project.org/repos/icu/???/trunk</textarea>
-
-<hr/>
-</div>
-<hr/>
-<iframe src="http://sites.google.com/site/icucodetools/v1/review" width="100%" height="800px">
-<h1><a href="http://sites.google.com/site/icucodetools/v1/review">Help</a></h1>
-</iframe>
-
-</py:if>
-<hr/>
-<i>$Id: $</i>
-</div>
-</body>
-</html>
+++ /dev/null
-# -*- 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
+++ /dev/null
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
-
-import re
-
-import sys
-
-from trac.core import *
-from trac.util import Markup
-from trac.web import IRequestHandler
-from trac.web.chrome import add_stylesheet, INavigationContributor, \
- ITemplateProvider
-from trac.web.href import Href
-#from trac.versioncontrol.web_ui.changeset import IChangesetRangeLink
-from trac.wiki import wiki_to_html, wiki_to_oneliner, IWikiSyntaxProvider, \
- Formatter
-from trac.ticket import Ticket
-
-
-
-class TicketlistModule(Component):
-
- implements(IRequestHandler)
-# implements(IRequestHandler,IChangesetRangeLink)
-
- def revision_range_link(self, req, base, start, end):
- return ('Ticket List', req.href('tktlist',old_path=base,new_path=base,old=start,new=end))
-
- _request_re = re.compile(r"/tktlist(?:/([^/]+))?(/.*)?$")
-
- def match_request(self, req):
- match = re.match(self._request_re, req.path_info)
- if match:
- return True
-
- def process_request(self, req):
- #ok, what are we about.
- db = self.env.get_db_cnx()
- ticketlist = {} # dict of ticket->???
- revlist = {} # dict of revision->
- repos = self.env.get_repository(req.authname)
-
- if not req.perm.has_permission('TICKET_MODIFY'):
- return req.redirect(req.href.browser())
-
- # shortcut - if "revs" is set, just use that
- revs = req.args.get('revs')
- if revs and len(revs)>0:
- content_type = "text/html"
- add_stylesheet(req, 'css/icuxtn.css')
- req.hdf['tix.revs'] = revs
- items = revs.split()
- outstr = '1=0 '
- for item in items:
- rev = int(item) # may fail
- outstr = 'rt.rev=%d'%(rev)
- req.hdf['is_dcut']=1
- req.hdf['tix.sql'] = outstr
- # test - get relevant revs
- # print "otime=%s, ntime=%s"%(type(otime),type(ntime))
- #cursor.execute("select distinct t.id,t.summary from ticket as t,revision as r, rev2ticket as rt "
- # " where t.id = rt.ticket and (%s) order by t.id"%(outstr))
- allsql = "select distinct ticket from rev2ticket as rt where %s order by rt.ticket"%(outstr)
- allsql = "select ticket from rev2ticket where rev=%s order by ticket"
- cursor = db.cursor()
- # cursor.execute("select ticket from rev2ticket where rev=%s order by ticket",("22913",))
- cursor.execute("select rt.rev from rev2ticket as rt where rt.ticket = %d order by rt.rev" % int(6010))
- ticket = 0
- req.hdf['tix.sql'] = allsql
- req.hdf['tix.sql']="zero"
- for tkt in cursor:
- req.hdf['tix.sql']=tkt
- summ = "";
- #sys.stderr.write(" tkt %s summ %s from (d-d)" % (tkt,summ))
- ticket = ticket + 1
- try:
- req.hdf['tickets.%d.comment' % ticket] = summ
- #req.hdf['tickets.%d.commenthtml' % ticket] = wiki_to_oneliner( summ, self.env, db, shorten=True )
- except Exception,e:
- req.hdf['tix.sql']=e
- #req.hdf['tickets.%d.commenthtml' % ticket] = ''
- req.hdf['tickets.%d.comment' % ticket] = ''
- req.hdf['tickets.%d.number' % ticket] = tkt
- #aa = Markup("<a class=\"new ticket\" href=\"%s\" title=\"Ticket x (new)\">#%s</a>"%(req.href.ticket(tkt),tkt))
- #req.hdf['tickets.%d.html' % ticket] = aa
- # set RDF here
- return 'tktrevs.cs', content_type
-
- new_path = req.args.get('new_path')
- new_rev = req.args.get('new')
- old_path = req.args.get('old_path')
- old_rev = req.args.get('old')
-
- new_path = repos.normalize_path(new_path)
- new_rev = repos.normalize_rev(new_rev)
- old_path = repos.normalize_path(old_path)
- old_rev = repos.normalize_rev(old_rev)
-
-
- old_rev = int(old_rev)
- new_rev = int(new_rev)
-
- req.hdf['changeset.diff_href'] = req.href('changeset',old_path=old_path,new=new_rev,new_path=new_path,old=old_rev)
-
- req.hdf['is_dcut']=1
-
- req.hdf['changeset.old_rev'] = old_rev
- req.hdf['changeset.new_rev'] = new_rev
- req.hdf['changeset.old_path'] = old_path
- req.hdf['changeset.new_path'] = new_path
- content_type = "text/html"
- add_stylesheet(req, 'css/icuxtn.css')
-
-
-
- # first, get relevant changes.
- req.hdf['target_path'] = '.';
- # okay. manually tromp through 'em
- oset = repos.get_changeset(old_rev);
- nset = repos.get_changeset(new_rev);
- otime = int(oset.date)
- ntime = int(nset.date)
-
- norm_tr="style='border: 1px dashed green; background-color: #CFC;'"
- closed_tr="style='color: #666;'"
- norev_tr="style='background-color:#FDD; border: 1px solid #F99; font-weight: bold;'"
-
- req.hdf['sample.norm.tr'] = norm_tr
- req.hdf['sample.closed.tr'] = closed_tr
- req.hdf['sample.norev.tr'] = norev_tr
-
-# print " searching in (%s-%s)" % (otime, ntime)
-
- # test - get relevant revs
- cursor = db.cursor()
-# print "otime=%s, ntime=%s"%(type(otime),type(ntime))
- cursor.execute("select distinct t.id,t.summary,t.owner, t.milestone, t.status "
- " , c.value "
- " from ticket as t,revision as r, rev2ticket as rt "
- " left join ticket_custom as c "
- " on ( c.name = 'revw' AND c.ticket = t.id ) "
-# " , ticket_custom as c "
- " where t.id = rt.ticket and rt.rev = r.rev and r.time > %s and r.time <= %s "
- "and exists ( select nc.rev from node_change as nc where nc.rev=r.rev and nc.path like %s ) "
- "order by t.id", (str(otime), str(ntime), (old_path + "%")))
- ticket = 0
- for tkt,summ,ownr,milestone,status, revw in cursor:
-# print " tkt %s summ %s from (%d-%d)" % (tkt,summ, otime, ntime)
- ticket = ticket + 1
- try:
- req.hdf['tickets.%d.comment' % ticket] = summ
- req.hdf['tickets.%d.commenthtml' % ticket] = wiki_to_oneliner( summ, self.env, db, shorten=True )
- except Exception,e:
- req.hdf['tickets.%d.commenthtml' % ticket] = ''
- req.hdf['tickets.%d.comment' % ticket] = ''
- req.hdf['tickets.%d.number' % ticket] = tkt
- aa = Markup("<a class=\"new ticket\" href=\"%s\" title=\"Ticket x (new)\">#%s</a>"%(req.href.ticket(tkt),tkt))
- req.hdf['tickets.%d.html' % ticket] = aa
- aa = Markup("<a class=\"new ticket\" href=\"%s\" title=\"Ticket x (new)\">#%s</a>"%(req.href.ticket(tkt),tkt))
- req.hdf['tickets.%d.owner' % ticket] = ownr
- req.hdf['tickets.%d.milestone' % ticket] = wiki_to_oneliner( "milestone:%s"%milestone , self.env, db, shorten=False )
- req.hdf['tickets.%d.reviewer' % ticket] = revw
- req.hdf['tickets.%d.statushtml' % ticket] = wiki_to_oneliner( "#%s"%(tkt), self.env, db, shorten=False )
- req.hdf['tickets.%d.html' % ticket] = aa
- req.hdf['tickets.%d.tr' % ticket] = norm_tr
- if status and status.startswith('closed'):
- req.hdf['tickets.%d.tr' % ticket] = closed_tr
- if ( not revw ) or len(revw)<1:
- req.hdf['tickets.%d.tr' % ticket] = norev_tr
-
- return 'tktlist.cs', content_type
-
+++ /dev/null
-<html>
-
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></meta>
-<title>ICU License - ICU 1.8.1 and later</title>
-</head>
-
-<body BGCOLOR="#ffffff">
-<h2>ICU License - ICU 1.8.1 and later</h2>
-
-<p>COPYRIGHT AND PERMISSION NOTICE</p>
-
-<p>
-Copyright (c) 1995-2010 International Business Machines Corporation and others
-</p>
-<p>
-All rights reserved.
-</p>
-<p>
-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, and/or sell
-copies of the Software, and to permit persons
-to whom the Software is furnished to do so, provided that the above
-copyright notice(s) and this permission notice appear in all copies
-of the Software and that both the above copyright notice(s) and this
-permission notice appear in supporting documentation.
-</p>
-<p>
-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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL
-THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM,
-OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
-RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
-USE OR PERFORMANCE OF THIS SOFTWARE.
-</p>
-<p>
-Except as contained in this notice, the name of a copyright holder shall not be
-used in advertising or otherwise to promote the sale, use or other dealings in
-this Software without prior written authorization of the copyright holder.
-</p>
-
-<hr>
-<p><small>
-All trademarks and registered trademarks mentioned herein are the property of their respective owners.
-</small></p>
-</body>
-</html>
-ICU Code Tools plugin
-
-Copyright (C) 2010 IBM Corporation and Others. All Rights Reserved.
-See license.html for the license file. This file is part of the
-ICU project and is under the same license.
-
-Requirements:
- Trac (0.11 or 0.12+?)
- Repository
-
-Installing:
- 1. install the plugin - at least the ticketmanager and review portion.
-
- a. There is no source release at this time: I recommend
- that you check out this code with svn
- and in this directory, run:
- "python setup.py develop"
-
- b. In trac.ini under '[components]' add:
- icucodetools.review.reviewmodule = enabled
- icucodetools.ticketmgr.ticketmanager = enabled
-
- NOTE: DCUT and TKTLIST parts are not working yet.
- Don't bother to enable them.
-
- 2. in your trac.ini describe how your changesets describe a ticket.
- Our changesets look like this: "ticket:1234: fixed the broken code"
- We use this regex:
-
- [icucodetools]
- ticket_pattern = ^ticket:(\d+)
-
- 3. you may need to run trac-admin <environment> upgrade
-
- 4. Grant permission of ICUREVIEW_VIEW to whomever you want to
- be able to review tickets.
-
- 5. Now, any ticket will have something in the top right corner which says:
- "No commits" - no commits against this ticket
-
- "Review 1 commits" - there is only one commit. Clicking this link
- will just take you to that single changeset.
-
- "Review n commits" - there are more than one commits against this
- ticket.
-
-
-Troubleshooting:
-
-Q: My commits aren't being found!
-A: Check the debug log. It will note commits with unparseable messages
-
-Q: How do I resync the commits?
-A: Until we implement trac 0.12 changeset listeners, you can do this:
-
- 0. back up your path/to/env/db/trac.db
-
- 1. $ sqlite3 path/to/env/db/trac.db
-
- 2. sqlite> delete from rev2ticket;
-
- 3. sqlite> update system set value='-1' where name='icu_tktmgr_youngest';
-
- 4. sqlite> .quit
-
-Now the ticket manager will re-sync the first time you hit a ticket.
-
-FILING BUGS/FEATURE REQUESTS:
- - Use ICU's trac repository at http://bugs.icu-project.org/trac
- - Use the 'infrastructure' component and clearly identify the 'ICU Code Tools
- for Trac' when you file the bug.
-
-
+© 2016 and later: Unicode, Inc. and others.
+License & terms of use: http://www.unicode.org/copyright.html
+moved to https://github.com/unicode-org/icu-trac-tools.git
+++ /dev/null
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
-[egg_info]
-tag_build = dev
-tag_svn_revision = true
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007-2012 IBM and Others. All Rights Reserved.
-# All rights reserved.
-#
-
-from setuptools import setup, find_packages
-
-PACKAGE = 'IcuCodeTools'
-VERSION = '0.0.1'
-
-setup(
- name=PACKAGE, version=VERSION,
- description='Miscellaneous ICU Extensions to Trac',
- author="Steven R. Loomis", author_email="srl@icu-project.org",
- license='BSD', url='http://icu-project.org',
- packages=find_packages(exclude=['ez_setup', '*.tests*']),
- package_data={
- 'icucodetools': [
- 'htdocs/css/*.css',
- 'templates/*.html',
-## 'htdocs/img/*.png',
- 'htdocs/js/*.js',
- ]
- },
- entry_points = {
- 'trac.plugins': [
- 'icucodetools.ticketmgr = icucodetools.ticketmgr',
- 'icucodetools.review = icucodetools.review',
- 'icucodetools.tktlist = icucodetools.tktlist',
- 'icucodetools.dcut = icucodetools.dcut'
- ]
- }
-)
+++ /dev/null
-# -*- coding: utf-8 -*-
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
-#
-#
-#from icutracxtn.web_ui import *
+++ /dev/null
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
-
-import re
-
-from trac.core import *
-from trac.util import Markup
-from trac.web import IRequestHandler
-from trac.web.chrome import add_stylesheet, INavigationContributor, \
- ITemplateProvider
-from trac.web.href import Href
-#from trac.versioncontrol.web_ui.changeset import IChangesetRangeLink
-from trac.wiki import wiki_to_html, wiki_to_oneliner, IWikiSyntaxProvider, \
- Formatter
-
-
-class DcutModule(Component):
-
- implements(IRequestHandler)
-# implements(IRequestHandler,IChangesetRangeLink)
-
- def revision_range_link(self, req, base, start, end):
- return ('DCUT Helper', req.href('dcut',old_path=base,new_path=base,old=start,new=end))
-
- _request_re = re.compile(r"/dcut(?:/([^/]+))?(/.*)?$")
-
- def match_request(self, req):
- match = re.match(self._request_re, req.path_info)
- if match:
- return True
-
- def process_request(self, req):
-
- idx = 0
- # srl
-# show_files = self.timeline_show_files
- db = self.env.get_db_cnx()
- ticketlist = {} # dict of ticket->???
- revlist = {} # dict of revision->
- # well. check it again,.
-
- srldebug=False
-
- repos = self.env.get_repository(req.authname)
-
- new_path = req.args.get('new_path')
- new_rev = req.args.get('new')
- old_path = req.args.get('old_path')
- old_rev = req.args.get('old')
-
- new_path = repos.normalize_path(new_path)
- new_rev = repos.normalize_rev(new_rev)
- old_path = repos.normalize_path(old_path)
- old_rev = repos.normalize_rev(old_rev)
-
- old_rev = int(old_rev)
- new_rev = int(new_rev)
-
- req.hdf['changeset.diff_href'] = req.href('changeset',old_path=old_path,new=new_rev,new_path=new_path,old=old_rev)
-
- req.hdf['is_dcut']=1
-
- req.hdf['changeset.old_rev'] = old_rev
- req.hdf['changeset.new_rev'] = new_rev
- req.hdf['changeset.old_path'] = old_path
- req.hdf['changeset.new_path'] = new_path
-
- if True:
- req.hdf['target_path'] = '.';
- # okay. manually tromp through 'em
- nrev = old_rev+1
- while nrev <= new_rev:
- chgset = repos.get_changeset(nrev)
- message = chgset.message or '--'
- # can we load a ticket from it?
- splits=message.split(':')
- if message.startswith('ticket:') and len(splits)>2:
- tickname=splits[1]
- try:
- ticknum=int(tickname)
- except Exception,e:
- nrev = nrev+1
- continue
- # yes, we have a ticket #
- files=[]
- for chg in chgset.get_changes():
- if not chg[0].startswith(old_path):
- continue
- files.append(chg)
- if len(files)==0:
- nrev = nrev+1
- continue # no relevant files
- titem=(ticknum,files,chgset)
- if ticknum in ticketlist:
- ticketlist[ticknum].append( titem )
- else:
- ticketlist[ticknum]=[ titem ]
- revlist[nrev]=titem
- else:
- print "malformed ticket? %s at %d" % (message,nrev) # don't know the syntax for die..
- nrev = nrev+1
- if len(ticketlist):
- tickets=ticketlist.keys()
- tickets.sort()
- for ticket in tickets:
- aticket=ticketlist[ticket] # (ticket,files,chg)
- cmt = 'ticket:%d - %d revs: ' % (ticket,len(aticket))
- for rev in aticket:
- revn = rev[2].rev
- filecount = len(rev[1])
- cmt = cmt + 'r%d - %d files (' % (revn,filecount)
- for file in rev[1]:
- cmt = cmt + file[0] + ' '
- cmt = cmt + ') '
- req.hdf['tickets.%d.comment' % ticket] = wiki_to_oneliner(cmt, self.env, db, shorten=False)
- req.hdf['tickets.%d.number' % ticket] = ticket
- if len(revlist):
- revs=revlist.keys()
- revs.sort()
- for rev in revs:
- arev=revlist[rev] # (ticket,files,chg)
- cmt = 'r%d ticket:%d ' % (arev[2].rev,arev[0])
- filecount = len(arev[1])
- cmt = cmt + ' - %d files (' % filecount
- shortfiles=''
- j = 0
- for file in arev[1]:
- req.hdf['revs.%d.files.%d.path' % (rev,j)] = file[0]
- req.hdf['revs.%d.files.%d.kind' % (rev,j)] = file[1]
- req.hdf['revs.%d.files.%d.change' % (rev,j)] = file[2]
- shortpath=file[0][len(old_path)+1:]
- req.hdf['revs.%d.files.%d.shortpath' % (rev,j)] = shortpath
- cmt = cmt + file[0] + ' '
- shortfiles = shortfiles + ' ' + shortpath
- j=j+1
- cmt = cmt + ') '
- req.hdf['revs.%d.comment' % rev] = wiki_to_oneliner(cmt, self.env, db, shorten=False)
- req.hdf['revs.%d.number' % rev] = rev
- req.hdf['revs.%d.shortfiles' % rev] = shortfiles
- req.hdf['revs.%d.backnumber' % rev] = (rev-1)
- req.hdf['revs.%d.ticket' % rev] = arev[0]
-
-
-# if isinstance(template, basestring):
-# req.hdf['admin.page_template'] = template
-# else:
-# req.hdf['admin.page_content'] = Markup(template.render())
-
- content_type = "text/html"
- add_stylesheet(req, 'css/icuxtn.css')
- return 'dcut.cs', content_type
-
+++ /dev/null
-/* Copyright (C) 2010-2013 International Business Machines Corporation and Others. All Rights Reserved. */
-
-/* @override http://unicode.org/cldr/trac/chrome/icucodetools/css/icuxtn.css */
-
-table.icureview tr:hover,
-table.icureview tr:hover td,
-table.icureview tr:hover th {
- background-color: yellow !important;
-}
-
-table.icureview {
- border-collapse: collapse;
- border: 1px solid gray;
-}
-
-table.icureview th, table.icureview td {
- text-align: left;
- border: 1px solid gray;
- padding: 2px;
-}
-
-table.icureview thead th {
- font-weight: bold;
-}
-
-table.icureview td.changes {
- text-align: right;
-}
-
-table.icureview td.overall {
- background-color: silver;
- font-style: italic;
- text-align: right;
-}
-
-.branch-unknown {
- font-weight: normal;
- font-style: italic;
-}
-.branch-tags {
- font-weight: bold;
- font-family: Georgia, "Times New Roman", Times, serif;
- color: white;
- background-color: navy;
- padding: 1px;
-}
-.branch-branches {
- font-weight: normal;
- color: #353;
-}
-
-.branch-trunk {
- font-weight: bold;
-}
-
-
+++ /dev/null
-// Copyright (C) 2007-2012 IBM and Others. All Rights Reserved
-
- var setBranchNames = function() {
- var cst = document.getElementById("changesettable");
- var trs=cst.getElementsByTagName("tr");
- for( i=1 ; i < trs.length ; i++ ) {
- var sec = trs[i].getElementsByTagName('td')[1]; // [0] is 'author', [1] is section.
- var brk = sec.getElementsByTagName('a');
- for(j=0;j<brk.length;j++) {
- var bri = brk[j];
- var str = bri.innerHTML;
- if(str.indexOf("trunk")>-1) {
- bri.className = 'branch-trunk';
- } else if(str.indexOf("branches")>-1) {
- bri.className = 'branch-branches';
- } else if(str.indexOf("tags")>-1) {
- bri.className = 'branch-tags';
- }
- }
- }
- }
-
-// http://ckon.wordpress.com/2008/07/25/stop-using-windowonload-in-javascript/
-if (window.attachEvent) {window.attachEvent('onload', setBranchNames);}
-else if (window.addEventListener) {window.addEventListener('load', setBranchNames, false);}
-else {document.addEventListener('load', setBranchNames, false);}
-
+++ /dev/null
-# Copyright (C) 2007-2015 International Business Machines Corporation and Others. All Rights Reserved.
-
-# Review module.
-# TODO: refactor ticket manipulation items into ticketmgr.
-
-import re
-
-import traceback
-
-from trac.core import Component, implements
-from trac.core import ComponentManager
-from trac.core import TracError
-from trac.util import Markup
-from trac.web import IRequestHandler
-from trac.web.chrome import add_stylesheet, add_script, ITemplateProvider, add_ctxtnav
-from trac.versioncontrol import Changeset
-from trac.web.api import IRequestFilter
-from trac.wiki import wiki_to_html, format_to_oneliner, IWikiSyntaxProvider
-from trac.mimeview import Context
-
-from genshi.builder import tag
-#from trac.env import IEnvironmentSetupParticipant
-from trac.perm import IPermissionRequestor
-from trac.config import ListOption
-from icucodetools.ticketmgr import TicketManager
-from pkg_resources import resource_filename #@UnresolvedImport
-
-class ReviewModule(Component):
-
- implements(ITemplateProvider, IRequestFilter, IRequestHandler, IPermissionRequestor)
-
- # path to match for review
- path_match = re.compile(r'/icureview/([0-9]+)')
-
- voteable_paths = ListOption('icucodetools', 'paths', '/ticket*',
- doc='List of URL paths to show reviews on. Globs are supported.')
-
- # search for earliest match, and how many segments to include following
- # trunk
- # branches/maint/maint-4-8
- # tags/release-2-0
- branchList = [['trunk',0],['branches',2],['tags',1]]
-
- # IPermissionRequestor methods
- def get_permission_actions(self):
- return ['ICUREVIEW_VIEW']
-
- # ITemplateProvider methods
- def get_templates_dirs(self):
- try:
- return [resource_filename(__name__, 'templates')]
- except Exception, e:
- self.log.warning('Could not get template dir: %s: %s' %
- (type(e), e))
- return ""
-
-
- def get_htdocs_dirs(self):
- return [('icucodetools', resource_filename(__name__, 'htdocs'))]
-
- # IRequestFilter methods
- def pre_process_request(self, req, handler):
- if 'ICUREVIEW_VIEW' not in req.perm:
- return handler
-
- if self.match_ticketpage(req):
- self.render_reviewlink(req)
-
- return handler
-
- def post_process_request(self, req, template, data, content_type):
- return (template, data, content_type)
-
- def render_reviewlink(self, req):
- """Render the "143 commits." box that shows in the topnav."""
- #add_stylesheet(req, 'icucodetools/css/icuxtn.css')
-
- els = []
-
- ticket_mgr = TicketManager(self.compmgr)
-
- db = self.env.get_db_cnx()
- repos = self.env.get_repository()
- if not repos:
- raise TracError("Could not get repository for %s" % (req.authname))
-
- revs = ticket_mgr.tkt2revs(self.log, db, repos, req, req.args['ticket'])
-
- if not revs:
- str = 'No commits.'
- li = tag.li(str)
- els.append(li)
- else:
- str = ' %d commits.' % len(revs)
- href = req.href.review(req.args['ticket'])
- a = tag.a('Review' + str, href=href)
- li = tag.li(a)
- els.append(li)
-
- ul = tag.ul(els, class_='review')
- className = ''
- title = "Reviews"
- add_ctxtnav(req, tag.span(ul, id='icureview', title=title, class_=className))
-
-
- def match_request(self, req):
- """Is this a review URL?"""
- match = re.match('/review(?:/([^/]+))?(?:/([^/]+))?(?:/(.*)$)?', req.path_info)
- if match:
- req.args['ticket'] = match.group(1)
- return True
-
- def match_ticketpage(self, req):
- """Is this the ticket URL?"""
- match = re.match('/ticket(?:/([^/]+))?(?:/([^/]+))?(?:/(.*)$)?', req.path_info)
- if match:
- req.args['ticket'] = match.group(1)
- return True
-
- def pathToBranchName(self, path):
- """convert a full path name to the 'branch' it applies to."""
- #return '/'.join(path.split('/')[0:2])
- windex = None
- win = None
- for branch in self.branchList:
- if(path == branch[0]): # catch changes to just 'trunk'
- idx = 0
- else:
- idx = path.find(branch[0]+'/')
- if(idx > -1 and (windex == None or windex > idx)):
- windex = idx
- win = branch
- if windex == None:
- segments = path.split('/')
- return '/'.join(segments[0:2])
- else:
- #print "found %s foll %s @ %d" % (win[0],win[1],windex)
- segments = path[windex:].split('/')
- return path[:windex] + ('/'.join(segments[0:win[1]+1])) # use specified # of following segments
-
- def changeToRange(self, c_new, change, repos):
- """preprocess a chgset.get_changes[n] entry. Returns (srcrev,dstrev,type) + change. The specially processed srcrev and dstrev are -1 for none, and the type gets munged a bit."""
- # q: (u'trunk/Locale.java', 'file', 'add', None, u'-1') from r3
- # q: (u'trunk/util.c', 'file', 'edit', u'trunk/util.c', u'2') from r4
- c_path = change[0] # new path
-# c_itemtype = change[1] # 'file' or ?
- c_type = change[2]
- c_oldpath = change[3]
- c_dstrev = c_new
- c_srcrev = c_old = int(change[4] or -1)
- if(c_type in (Changeset.COPY,Changeset.MOVE)):
- c_srcrev = -1
- elif(c_type in (Changeset.DELETE)):
- c_dstrev = -1
- elif(c_type in (Changeset.EDIT, Changeset.ADD)):
- if c_path != c_oldpath and c_oldpath != None and c_path != None: # did the path change? (copy or move)
- if(c_old != -1): # if we have an old rev, track it
- ## SHOULD call repos.get_path_history(c_path, c_new, c_old)
- ## and then look for 'copy' or 'move' here.
- ## Code below will only return the EDIT (etc) operation *before* the copy/move.
- # oldchange = repos.get_changeset(c_old) # old rev
- # found = None
- # for oldchg in oldchange.get_changes():
- # if oldchg[0] == c_path or oldchg[3] == c_oldpath:
- # found = oldchg
- # if found:
- # # "found" is the source location (pre copy)
- # # however, change[] will have the correct from/to
- # #
- # c_type = "["+str(c_old)+":"+str(c_new)+"]"+found[2] + "+" +c_type
- # else:
- # c_type = "???+" + c_type
- c_type = "(copy/move)+" + c_type
- else:
- c_type = "(???)+" + c_type
- else:
- c_type = c_type +" ???"
- return (c_srcrev, c_dstrev, c_type) + change + (1,) # preprocessed + (change) + (mergecount)
-
- def describeChange(self, file, change, req, db):
- """HTMLize a changeset (the 'details' column)"""
- what = change[2] or 'change'
- where = 'r%d:%d' % (change[0],change[1])
- if(change[2] == 'move'):
- url = req.href.changeset(change[1])
- where = 'r%d' % change[1]
- what = change[2]
- elif(change[0] == -1):
- if(change[1] == -1):
- url = None
- what = "noop"
- where = None
- else:
- #if change[2] == 'add+commits':
- url = req.href.browser(file, rev=change[1]) # 'add'
- where = 'r%d' % change[1]
- what = change[2]
- elif(change[1] == -1):
- url = None # deleted
- what = "deleted"
- where = None
- else:
- url = req.href.changeset(old_path=change[6] or file, old=change[0], new_path=change[3] or file, new=change[1])
-
- # multi change
- if(change[8]>1):
- what = u"%s\u00d7%d" % (what, change[8])
-
- # urlize
- if url:
- what = Markup('<a href="%s">%s</a>' % (url,what))
-
- if where:
- # search query?
- return (what, tag.a(where, href=req.href.search(q=where)))
- #return (what, where)
- else:
- # specific url
- return (what, '')
-
-
- def process_request(self, req):
- """This is the 'main' of this module."""
- #db = self.env.get_db_cnx()
- #ticketlist = {} # dict of ticket->???
- #revlist = {} # dict of revision->
- repos = self.env.get_repository()
- context = Context.from_request(req, False)
-
- new_path = req.args.get('new_path')
- new_rev = req.args.get('new')
- old_path = req.args.get('old_path')
- old_rev = req.args.get('old')
-
- new_path = repos.normalize_path(new_path)
- new_rev = repos.normalize_rev(new_rev)
- old_path = repos.normalize_path(old_path)
- old_rev = repos.normalize_rev(old_rev)
-
-
-# if not req.perm.has_permission('TICKET_MODIFY'):
-# return req.redirect(req.href.browser())
-
- old_rev = int(old_rev)
- new_rev = int(new_rev)
-
- ticket = req.args.get('ticket')
- try:
- ticket = int(ticket)
- except Exception:
- ticket = 0
-# req.hdf['review.ticket'] = ticket
-# req.hdf['review.tickethtml'] = tag.a(ticket, req.href.ticket(ticket))
-
- data = {}
-
- data['overall_y'] = 0
- data['ticket_id'] = req.args['ticket']
- data['ticket_summary'] = ''
- data['ticket_href'] = req.href.ticket(req.args['ticket'])
-
- ticket_mgr = TicketManager(self.compmgr)
-
- db = self.env.get_db_cnx()
- repos = self.env.get_repository()
-
- revs = ticket_mgr.tkt2revs(self.log, db, repos, req, req.args['ticket'])
-
- if (not revs or len(revs)==0):
- # nothing to review. shouldn't happen
- return ('nothing.html', data, 'text/html')
- elif(len(revs)==1):
- # only one change - just do a changeset view
- return req.redirect(req.href.changeset(revs[0]))
-
- revcount = 0
- branches = {} # track each branch separately.
- files = {} # track all of the files which are affected
- # may be 0 revs.
- revisions = [] # array of munged revisions
-
- for rev in revs:
- chgset = repos.get_changeset(rev)
- # q: (u'trunk/Locale.java', 'file', 'add', None, u'-1') from r3
- # q: (u'trunk/util.c', 'file', 'edit', u'trunk/util.c', u'2') from r4
- message = chgset.message or '--'
- revcount = revcount + 1
- revision = {}
- revision['rev'] = tag.a(rev, req.href.changeset(rev))
- revision['author'] = chgset.author
- revision['num'] = rev
- revision['comment'] = message #wiki_to_oneliner( message, self.env, db, shorten=False )
- try:
- revision['comment_wiki'] = format_to_oneliner( self.env, context, message, shorten=False )
- except Exception, e:
- self.env.log.warn(e)
- revision['comment_wiki'] = "%s (could not format - %s)" % (message, str(e))
-
- rbranches = revision['branches'] = []
- # walk through all changes in this Changeset and apply them to the files[] array
- for chg in chgset.get_changes():
- path = chg[0] # new path
- if path in files:
- item = files[path] # known file
- else:
- item = []
- files[path] = item; # new file
- item.append(self.changeToRange(rev,chg,repos))
- branch_name = self.pathToBranchName(path)
- if branch_name not in rbranches:
- # first time we have seen this branch
- rbranches.append(branch_name)
- revisions.append(revision)
- data['revisions'] = revisions
-
- if(revcount > 0):
- data['revcount'] = revcount
-
- # print "files: %d" % len(files)
- # go throuhg each file and calculate its minimum range
- filelist = files.keys()
- filelist.sort()
-# print 'bar to %d len of %s' % (len(filelist),str(filelist))
- # see changeToRange() for definition of the elements here.
- # (oldrev, newrev, type, (change...) )
- for file in filelist:
- changes = files[file]
- i = 0
-# print " looping from %d to %d over %d " % (i,len(changes)-1,len(changes))
- while len(changes)>1 and i<(len(changes)-1):
- merge = None
- if changes[i][1] == changes[i+1][0]: # if this change is exactly subsequent to the previous
- if changes[i][0] == -1:
- if changes[i][2] == Changeset.ADD and changes[i+1][2] == Changeset.EDIT:
- merge = (changes[i][0],changes[i+1][1],'add+commits') # merge, retain 'first' rev
- elif changes[i][2] == '(copy/move)+edit' and changes[i+1][2] == Changeset.EDIT:
- merge = (changes[i][0],changes[i+1][1],'(copy/move)+edit') # retain 'first' rev
- elif changes[i][2] == Changeset.EDIT and changes[i+1][2] == Changeset.EDIT:
- merge = (changes[i][0],changes[i+1][1],'edit') # retain 'first' rev
- if merge:
- # preserve paths
- changes[i+1] = merge + (changes[i+1][3], changes[i+1][4], changes[i][5]+"+"+changes[i+1][5], changes[i][6], changes[i+1][7], changes[i][8]+1)
- changes = changes[:i] + changes[i+1:] # and shift down
-# print "merged: %s" % str(changes)
- files[file] = changes
- else:
- i = i + 1
-
- # now, write 'em out
- sera = 0
- #files_data = []
- for file in filelist:
- sera = sera+1
- file_data = {}
- file_data['name'] = Markup('<a href="%s">%s</a>' % (req.href.browser(file),file))
- branch_name = self.pathToBranchName(file)
- #print "branch is: (%s)" % (branch_name)
- branches_data = branches.get(branch_name, {})
- files_data = branches_data.get('files',[])
-
- changes = files[file]
- cha = 0
- changes_data = []
- for change in changes:
- cha = cha + 1
-# print "%s output %s " % (file, str(change))
- changes_data.append(self.describeChange(file, change, req, db))
- file_data['changes'] = changes_data
- if(len(changes)>1):
- whathtml = self.describeChange(file, (int(changes[0][7] or -1), int(changes[len(changes)-1][1] or -1), 'overall', changes[len(changes)-1][3], None, None, changes[0][6], None, len(changes)), req, db)
- file_data['overall'] = whathtml
- file_data['overall_y'] = 1
- data['overall_y'] = 1
- else:
- file_data['overall_y'] = 0
- files_data.append(file_data)
- # sets
- branches_data['files'] = files_data
- branches_data['len'] = len(files_data)
- branches_data['name'] = branch_name
- branches[branch_name] = branches_data
-
- # .. convert dict to array.
- branch_list = []
- branch_keys = branches.keys()
- branch_keys.sort()
- for branch in branch_keys:
- branch_list.append(branches[branch])
- data['branches'] = branch_list
- data['lastbranch'] = branch
- data['branchcount'] = len(branches)
-
- content_type = "text/html"
- add_stylesheet(req, 'icucodetools/css/icuxtn.css')
- add_script(req, 'icucodetools/js/review.js')
- return 'review.html', data, content_type
-
+++ /dev/null
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<!--
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
--->
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="layout.html" />
- <head>
- <title>Nothing to Review for ticket #${ticket_id}</title>
- </head>
-
- <body>
- <div id="ctxtnav" class="nav"></div>
-
- <div id="content" class="icucodereview">
- <h1>Nothing to review!</h1>
- <p>
- Nothing to review - no changesets in ticket <a href="${ticket_href}">#${ticket_id}</a>
- </p>
- </div>
- </body>
-</html>
+++ /dev/null
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<!--
-# Copyright (C) 2007-2013 IBM and Others. All Rights Reserved
--->
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="layout.html" />
- <head>
- <title>Review for ticket #${ticket_id}</title>
- </head>
-
- <body>
- <div id="ctxtnav" class="nav"></div>
-
- <div id="content" class="icucodereview">
-
-
- <h1>Ticket <a href='${href.ticket(ticket_id)}'>#${ticket_id}</a></h1>
- <p>
- <span class="icureview_summary">${ticket_summary}</span>
- </p>
-<py:if test="revcount">
-
- <h2>${revcount} Changesets</h2>
- <table id='changesettable' class='icureview'>
- <thead>
- <tr>
- <th>r</th>
- <th>author</th>
- <th>section(s)</th>
- <th>comment</th>
- </tr>
- </thead>
- <tbody>
- <py:for each="rev in revisions">
- <tr>
- <th>
- <a href="${href.changeset(rev.num)}">r${rev.num}</a>
- </th>
- <td>
- ${rev.author}
- </td>
- <td>
- <!-- sections -->
- <py:for each="branch in rev.branches">
- <b class='branchlist'>
- <a class='branch-unknown' href="#${branch}">${branch}</a>
- </b>
- </py:for>
- </td>
- <td>
- ${rev.comment_wiki}
- </td>
- </tr>
- </py:for>
- </tbody>
- </table>
-
-<py:if test="branchcount > 1">
-<h2>Files</h2>
-<h3>Jump to Sections</h3>
-<ul>
-<py:for each="branch in branches">
- <li><a href="#${branch.name}">${branch.name}</a> — ${branch.len} files</li>
-</py:for>
-</ul>
-</py:if>
-
-<py:for each="branch in branches">
-<hr/>
-<a name="${branch.name}">
- <h3>
- <a href="${href.browser(branch.name)}">${branch.name}</a> — (${branch.len} files changed)
- </h3>
-</a>
-
-<blockquote>
-
-<table class='icureview'>
-<thead>
-<tr>
- <th>File</th>
- <th>Changes</th>
- <th>Details</th>
- <py:if test="overall_y > 0">
- <th>Overall<br/><i>(including other changes)</i></th>
- <th>Details</th>
- </py:if>
-</tr>
-</thead>
-<tbody>
-<py:for each="file in branch.files">
- <tr>
- <th class='name'>${file.name}</th>
- <td class='changes'>
- <py:for each="change in file.changes">
- ${change[0]}<br/>
- </py:for>
- </td>
- <td class='details'>
- <py:for each="change in file.changes">
- ${change[1]}<br/>
- </py:for>
- </td>
-
- <py:if test="overall_y > 0">
- <py:if test="file.overall_y > 0">
- <td class='overall'>${file.overall[0]}</td>
- <td class='overall'>${file.overall[1]}</td>
- </py:if>
- </py:if>
- </tr>
-</py:for>
-</tbody>
-</table>
-
-</blockquote>
-
-</py:for>
-
-<hr/>
-
-<div style='display:none;'>
-<h2>Merge Commands</h2>
-Very experimental. Change ??? to the top of the tree you want to merge from (icu or icu4j)<br/>
-<textarea>svn merge -c <?cs each:rev = revisions ?><?cs var:rev.num ?>,<?cs /each ?> svn+ssh://source.icu-project.org/repos/icu/???/trunk</textarea>
-
-<hr/>
-</div>
-<hr/>
-<iframe src="http://sites.google.com/site/icucodetools/v1/review" width="100%" height="800px">
-<h1><a href="http://sites.google.com/site/icucodetools/v1/review">Help</a></h1>
-</iframe>
-
-</py:if>
-<hr/>
-<i>$Id: $</i>
-</div>
-</body>
-</html>
+++ /dev/null
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007-2012 IBM and Others. All Rights Reserved
-# Author: <srl@icu-project.org>
-#
-
-#
-# Ticket management.
-# This component manages the revision to ticket map.
-#
-# 2011-jan-27 srl adding IRepositoryChangeListener functionality (requires trac 0.12)
-
-
-
-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
-from trac.versioncontrol.api import IRepositoryChangeListener
-
-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, IRepositoryChangeListener)
-
- 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
-
- # IRepositoryChangeListener methods
- # Must call with: trac-admin /home/icutrac changeset modified '(default)' 29330 29333 - ugly, http://www.mail-archive.com/trac-dev@googlegroups.com/msg04568.html
- def changeset_modified(self, repos, changeset, old_changeset):
- 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)))
- db = self.env.get_db_cnx()
- cursor = db.cursor()
- cursor.execute("DELETE FROM rev2ticket "
- " "
- "where rev= %s " %
- str(changeset.rev))
- self.revision_changed(self.log, changeset, changeset.rev, db.cursor())
- db.commit()
- #self.log.error("changeset_added: %s\n" % changeset.rev)
-
- def changeset_added(self, repos, changeset):
- message = changeset.message or '--'
- #self.log.error("changeset_added: %s\n" % changeset.rev)
-
- # IRepositoryObserver function
- 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.strip())
- if res:
- tickname = res.group(1)
- try:
- int(res.group(1)) # should be int
- except Exception, e:
- self.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" for pattern /%s/' %
- (next_youngest, cset.message, self.ticket_pattern))
-
- 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
+++ /dev/null
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
-
-import re
-
-import sys
-
-from trac.core import *
-from trac.util import Markup
-from trac.web import IRequestHandler
-from trac.web.chrome import add_stylesheet, INavigationContributor, \
- ITemplateProvider
-from trac.web.href import Href
-#from trac.versioncontrol.web_ui.changeset import IChangesetRangeLink
-from trac.wiki import wiki_to_html, wiki_to_oneliner, IWikiSyntaxProvider, \
- Formatter
-from trac.ticket import Ticket
-
-
-
-class TicketlistModule(Component):
-
- implements(IRequestHandler)
-# implements(IRequestHandler,IChangesetRangeLink)
-
- def revision_range_link(self, req, base, start, end):
- return ('Ticket List', req.href('tktlist',old_path=base,new_path=base,old=start,new=end))
-
- _request_re = re.compile(r"/tktlist(?:/([^/]+))?(/.*)?$")
-
- def match_request(self, req):
- match = re.match(self._request_re, req.path_info)
- if match:
- return True
-
- def process_request(self, req):
- #ok, what are we about.
- db = self.env.get_db_cnx()
- ticketlist = {} # dict of ticket->???
- revlist = {} # dict of revision->
- repos = self.env.get_repository(req.authname)
-
- if not req.perm.has_permission('TICKET_MODIFY'):
- return req.redirect(req.href.browser())
-
- # shortcut - if "revs" is set, just use that
- revs = req.args.get('revs')
- if revs and len(revs)>0:
- content_type = "text/html"
- add_stylesheet(req, 'css/icuxtn.css')
- req.hdf['tix.revs'] = revs
- items = revs.split()
- outstr = '1=0 '
- for item in items:
- rev = int(item) # may fail
- outstr = 'rt.rev=%d'%(rev)
- req.hdf['is_dcut']=1
- req.hdf['tix.sql'] = outstr
- # test - get relevant revs
- # print "otime=%s, ntime=%s"%(type(otime),type(ntime))
- #cursor.execute("select distinct t.id,t.summary from ticket as t,revision as r, rev2ticket as rt "
- # " where t.id = rt.ticket and (%s) order by t.id"%(outstr))
- allsql = "select distinct ticket from rev2ticket as rt where %s order by rt.ticket"%(outstr)
- allsql = "select ticket from rev2ticket where rev=%s order by ticket"
- cursor = db.cursor()
- # cursor.execute("select ticket from rev2ticket where rev=%s order by ticket",("22913",))
- cursor.execute("select rt.rev from rev2ticket as rt where rt.ticket = %d order by rt.rev" % int(6010))
- ticket = 0
- req.hdf['tix.sql'] = allsql
- req.hdf['tix.sql']="zero"
- for tkt in cursor:
- req.hdf['tix.sql']=tkt
- summ = "";
- #sys.stderr.write(" tkt %s summ %s from (d-d)" % (tkt,summ))
- ticket = ticket + 1
- try:
- req.hdf['tickets.%d.comment' % ticket] = summ
- #req.hdf['tickets.%d.commenthtml' % ticket] = wiki_to_oneliner( summ, self.env, db, shorten=True )
- except Exception,e:
- req.hdf['tix.sql']=e
- #req.hdf['tickets.%d.commenthtml' % ticket] = ''
- req.hdf['tickets.%d.comment' % ticket] = ''
- req.hdf['tickets.%d.number' % ticket] = tkt
- #aa = Markup("<a class=\"new ticket\" href=\"%s\" title=\"Ticket x (new)\">#%s</a>"%(req.href.ticket(tkt),tkt))
- #req.hdf['tickets.%d.html' % ticket] = aa
- # set RDF here
- return 'tktrevs.cs', content_type
-
- new_path = req.args.get('new_path')
- new_rev = req.args.get('new')
- old_path = req.args.get('old_path')
- old_rev = req.args.get('old')
-
- new_path = repos.normalize_path(new_path)
- new_rev = repos.normalize_rev(new_rev)
- old_path = repos.normalize_path(old_path)
- old_rev = repos.normalize_rev(old_rev)
-
-
- old_rev = int(old_rev)
- new_rev = int(new_rev)
-
- req.hdf['changeset.diff_href'] = req.href('changeset',old_path=old_path,new=new_rev,new_path=new_path,old=old_rev)
-
- req.hdf['is_dcut']=1
-
- req.hdf['changeset.old_rev'] = old_rev
- req.hdf['changeset.new_rev'] = new_rev
- req.hdf['changeset.old_path'] = old_path
- req.hdf['changeset.new_path'] = new_path
- content_type = "text/html"
- add_stylesheet(req, 'css/icuxtn.css')
-
-
-
- # first, get relevant changes.
- req.hdf['target_path'] = '.';
- # okay. manually tromp through 'em
- oset = repos.get_changeset(old_rev);
- nset = repos.get_changeset(new_rev);
- otime = int(oset.date)
- ntime = int(nset.date)
-
- norm_tr="style='border: 1px dashed green; background-color: #CFC;'"
- closed_tr="style='color: #666;'"
- norev_tr="style='background-color:#FDD; border: 1px solid #F99; font-weight: bold;'"
-
- req.hdf['sample.norm.tr'] = norm_tr
- req.hdf['sample.closed.tr'] = closed_tr
- req.hdf['sample.norev.tr'] = norev_tr
-
-# print " searching in (%s-%s)" % (otime, ntime)
-
- # test - get relevant revs
- cursor = db.cursor()
-# print "otime=%s, ntime=%s"%(type(otime),type(ntime))
- cursor.execute("select distinct t.id,t.summary,t.owner, t.milestone, t.status "
- " , c.value "
- " from ticket as t,revision as r, rev2ticket as rt "
- " left join ticket_custom as c "
- " on ( c.name = 'revw' AND c.ticket = t.id ) "
-# " , ticket_custom as c "
- " where t.id = rt.ticket and rt.rev = r.rev and r.time > %s and r.time <= %s "
- "and exists ( select nc.rev from node_change as nc where nc.rev=r.rev and nc.path like %s ) "
- "order by t.id", (str(otime), str(ntime), (old_path + "%")))
- ticket = 0
- for tkt,summ,ownr,milestone,status, revw in cursor:
-# print " tkt %s summ %s from (%d-%d)" % (tkt,summ, otime, ntime)
- ticket = ticket + 1
- try:
- req.hdf['tickets.%d.comment' % ticket] = summ
- req.hdf['tickets.%d.commenthtml' % ticket] = wiki_to_oneliner( summ, self.env, db, shorten=True )
- except Exception,e:
- req.hdf['tickets.%d.commenthtml' % ticket] = ''
- req.hdf['tickets.%d.comment' % ticket] = ''
- req.hdf['tickets.%d.number' % ticket] = tkt
- aa = Markup("<a class=\"new ticket\" href=\"%s\" title=\"Ticket x (new)\">#%s</a>"%(req.href.ticket(tkt),tkt))
- req.hdf['tickets.%d.html' % ticket] = aa
- aa = Markup("<a class=\"new ticket\" href=\"%s\" title=\"Ticket x (new)\">#%s</a>"%(req.href.ticket(tkt),tkt))
- req.hdf['tickets.%d.owner' % ticket] = ownr
- req.hdf['tickets.%d.milestone' % ticket] = wiki_to_oneliner( "milestone:%s"%milestone , self.env, db, shorten=False )
- req.hdf['tickets.%d.reviewer' % ticket] = revw
- req.hdf['tickets.%d.statushtml' % ticket] = wiki_to_oneliner( "#%s"%(tkt), self.env, db, shorten=False )
- req.hdf['tickets.%d.html' % ticket] = aa
- req.hdf['tickets.%d.tr' % ticket] = norm_tr
- if status and status.startswith('closed'):
- req.hdf['tickets.%d.tr' % ticket] = closed_tr
- if ( not revw ) or len(revw)<1:
- req.hdf['tickets.%d.tr' % ticket] = norev_tr
-
- return 'tktlist.cs', content_type
-
+++ /dev/null
-#!/usr/bin/python
-
-# Copyright (C) 2014 IBM Corporation and Others. All Rights Reserved.
-#
-
-# This script should be invoked from the subversion pre-commit hook just like the trac plugin
-#
-# REPOS="$1"
-# TXN="$2"
-# TRAC_ENV="/somewhere/trac/project/"
-# LOG=`/usr/bin/svnlook log -t "$TXN" "$REPOS"`
-# /path/to/traccheck "$TRAC_ENV" "$LOG" >&2 || exit 1
-
-import sys, re
-from trac.core import TracError
-from trac.env import open_environment
-from trac.resource import ResourceNotFound
-from trac.ticket.model import Ticket
-from trac.util.text import exception_to_unicode
-
-okstatus = ['design','new','accepted','reviewing','reviewfeedback']
-
-def run(args=None):
- """trac check script"""
- if args is None:
- args = sys.argv[1:]
- env = open_environment(args[0])
-
- ticket_pattern = env.config.get('icucodetools', 'ticket_pattern', 'NoneFound')
- ticket_match = None
-
- def lusage():
- print "Please make your message match /%s/\n and use an open ticket (One of these: %s)" % (ticket_pattern, str(okstatus))
- print "See %s/wiki/TracCheck for more details." % env.base_url
-
- try:
- ticket_match = re.compile(ticket_pattern)
- except Exception, e:
- # not sorry?
- raise TracError('*** INTERNAL ERROR: Could not compile icucodetools.ticket_pattern=/%s/: %s' % (ticket_pattern, exception_to_unicode(e, traceback=True)))
- res = ticket_match.match(args[1].strip())
- if res:
- tickname = res.group(1)
- try:
- int(res.group(1)) # should be int
- except Exception, e:
- print('*** Sorry, "%s" is not a valid number when parsing "%s": %s.' %
- (tickname, args[1], e))
- lusage()
- sys.exit(1)
- else:
- print('*** Sorry, could not parse a ticket number from your commit message "%s".' %
- (args[1]))
- lusage()
- sys.exit(1)
- id = int(res.group(1))
- try:
- ticket = Ticket(env, id)
- status = ticket.values['status']
- if status in okstatus:
- # print "Okay! You are committing against ticket #%d which is in state '%s': %s" % (id,status,ticket.values['summary']) # (fails with codec error- and, unneeded. )
- sys.exit(0)
- else:
- print "*** Sorry, ticket #%d is '%s' and is not open for commits: %s" % (id,status,ticket.values['summary'])
- lusage()
- sys.exit(1)
- except (ResourceNotFound):
- print "*** Sorry, ticket #%d does not exist." % (id)
- lusage()
- sys.exit(1)
- sys.exit(0)
-
-# make this file runnable
-if __name__ == '__main__':
- sys.exit(run())
+++ /dev/null
-<html>
-
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></meta>
-<title>ICU License - ICU 1.8.1 and later</title>
-</head>
-
-<body BGCOLOR="#ffffff">
-<h2>ICU License - ICU 1.8.1 and later</h2>
-
-<p>COPYRIGHT AND PERMISSION NOTICE</p>
-
-<p>
-Copyright (c) 1995-2010 International Business Machines Corporation and others
-</p>
-<p>
-All rights reserved.
-</p>
-<p>
-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, and/or sell
-copies of the Software, and to permit persons
-to whom the Software is furnished to do so, provided that the above
-copyright notice(s) and this permission notice appear in all copies
-of the Software and that both the above copyright notice(s) and this
-permission notice appear in supporting documentation.
-</p>
-<p>
-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 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL
-THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM,
-OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
-RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
-USE OR PERFORMANCE OF THIS SOFTWARE.
-</p>
-<p>
-Except as contained in this notice, the name of a copyright holder shall not be
-used in advertising or otherwise to promote the sale, use or other dealings in
-this Software without prior written authorization of the copyright holder.
-</p>
-
-<hr>
-<p><small>
-All trademarks and registered trademarks mentioned herein are the property of their respective owners.
-</small></p>
-</body>
-</html>
-ICU Code Tools plugin
+© 2016 and later: Unicode, Inc. and others.
+License & terms of use: http://www.unicode.org/copyright.html
-Copyright (C) 2010-2014 IBM Corporation and Others. All Rights Reserved.
-See license.html for the license file. This file is part of the
-ICU project and is under the same license.
-
-Docs: https://sites.google.com/site/icucodetools/home
-
-Requirements:
- Trac (0.11 or 0.12+?)
- Repository
-
-Installing:
- 1. install the plugin - at least the ticketmanager and review portion.
-
- a. There is no source release at this time: I recommend
- that you check out this code with svn
- and in this directory, run:
- "python setup.py develop"
-
- b. In trac.ini under '[components]' add:
- icucodetools.review.reviewmodule = enabled
- icucodetools.ticketmgr.ticketmanager = enabled
-
- NOTE: DCUT and TKTLIST parts are not working yet.
- Don't bother to enable them.
-
- 2. in your trac.ini describe how your changesets describe a ticket.
- Our changesets look like this: "ticket:1234: fixed the broken code"
- We use this regex:
-
- [icucodetools]
- ticket_pattern = ^ticket:(\d+)
-
- 3. you may need to run trac-admin <environment> upgrade
-
- 4. Grant permission of ICUREVIEW_VIEW to whomever you want to
- be able to review tickets.
-
- 5. Now, any ticket will have something in the top right corner which says:
- "No commits" - no commits against this ticket
-
- "Review 1 commits" - there is only one commit. Clicking this link
- will just take you to that single changeset.
-
- "Review n commits" - there are more than one commits against this
- ticket.
-
-
-Troubleshooting:
-
-Q: My commits aren't being found!
-A: Check the debug log. It will note commits with unparseable messages
-
-Q: How do I resync the commits?
-A: Until we implement trac 0.12 changeset listeners, you can do this:
-
- 0. back up your path/to/env/db/trac.db
-
- 1. $ sqlite3 path/to/env/db/trac.db
-
- 2. sqlite> delete from rev2ticket;
-
- 3. sqlite> update system set value='-1' where name='icu_tktmgr_youngest';
-
- 4. sqlite> .quit
-
-Now the ticket manager will re-sync the first time you hit a ticket.
-
-RESTRICT CHECKINS
- See the comments at the top of icucodetools/traccheck.py.
- note that /path/to/traccheck is the path to the installed "traccheck" script,
- not the 'traccheck.py' source file.
-
-FILING BUGS/FEATURE REQUESTS:
- - See https://sites.google.com/site/icucodetools/home to file or view bugs.
+moved to https://github.com/unicode-org/icu-trac-tools.git
+++ /dev/null
-# Copyright (C) 2007-2010 IBM and Others. All Rights Reserved
-[egg_info]
-tag_build = dev
-tag_svn_revision = true
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007-2014 IBM and Others. All Rights Reserved.
-# All rights reserved.
-#
-
-from setuptools import setup, find_packages
-
-PACKAGE = 'IcuCodeTools'
-VERSION = '0.0.2'
-
-setup(
- name=PACKAGE, version=VERSION,
- description='Miscellaneous ICU Extensions to Trac',
- author="Steven R. Loomis", author_email="srl@icu-project.org",
- license='BSD', url='http://icu-project.org',
- packages=find_packages(exclude=['ez_setup', '*.tests*']),
- package_data={
- 'icucodetools': [
- 'htdocs/css/*.css',
- 'templates/*.html',
-## 'htdocs/img/*.png',
- 'htdocs/js/*.js',
- ]
- },
- entry_points = {
- 'trac.plugins': [
- 'icucodetools.ticketmgr = icucodetools.ticketmgr',
- 'icucodetools.review = icucodetools.review',
- 'icucodetools.tktlist = icucodetools.tktlist',
- 'icucodetools.dcut = icucodetools.dcut'
- ],
- 'console_scripts': [
- 'traccheck = icucodetools.traccheck:run'
- ]
- }
-)