Author: hdu Date: Mon Dec 10 17:19:04 2012 New Revision: 1419594 URL: http://svn.apache.org/viewvc?rev=1419594&view=rev Log: added a script to extract info from an AOO revision range
Added: openoffice/devtools/scripts/ openoffice/devtools/scripts/svnlog2info.py (with props) Added: openoffice/devtools/scripts/svnlog2info.py URL: http://svn.apache.org/viewvc/openoffice/devtools/scripts/svnlog2info.py?rev=1419594&view=auto ============================================================================== --- openoffice/devtools/scripts/svnlog2info.py (added) +++ openoffice/devtools/scripts/svnlog2info.py Mon Dec 10 17:19:04 2012 @@ -0,0 +1,245 @@ +#! /usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Svn2Info - Create a HTML file with info about a revision range +# +# Example: +# python svnlog2info.py trunk 1405864 1418409 + +import sys +import re +import xmlrpclib +from subprocess import Popen, PIPE + + +# string constants for the Apache OpenOffice project +bzsoap = "https://issues.apache.org/ooo/xmlrpc.cgi" +issue_pattern = "^\s*(?:re)?(?:fix)?\s*(?:for)?\s*(?:bug|issue|problem)?\s*#?i?([1-9][0-9][0-9][0-9]+)[#: ]" +bugref_url = "https://issues.apache.org/ooo/show_bug.cgi?id=" +infoout_name = "izlist.htm" +svnout_name = "tmp_svn2info_svnout.txt" +bzout_name = "tmp_svn2info_bzout.txt" + + +class Revision(object): + """Constructor for a Revision object""" + def __init__( self, revnum, author, revlog, dirs_changed): + self.revnum = revnum + self.author = author + self.log = revlog + self.dirs_changed = dirs_changed + self.issue = get_issue( revlog) + + +def get_issue( revlog): + """Get the issue number referenced in a commit summary""" + issue_re = re.compile( issue_pattern, re.IGNORECASE) + issue_match = issue_re.search( revlog) + if not issue_match: + return None + issue_id = int(issue_match.group(1)) + return issue_id + + +def get_svn_log( svnurl, revmin, revmax): + """Run the svn log command for the requested revision range""" + # check input arguments + if int(revmin) > int(revmax): + print "start revision %d must be less than end revision %d!" % (revmin, revmax) + return None + + revmin_limit = 1162288 + revmax_limit = 3000000 + if revmin < revmin_limit: + print "revision %d is out of range" % (revmin) + return None + if revmax_limit < revmax: + print "revision %d is out of range" % (revmax) + return None + + svncmd = "svn log -v -r%d:%d %s" % (revmin, revmax, svnurl) + svnout = Popen( svncmd, shell=True, stdout=PIPE).communicate()[0] + open( svnout_name, "wb").write( svnout.encode("utf-8")) + return svnout + + +def parse_svn_log( svnout): + """Parse the output of the svn log command""" + all_revs = [] + s = svnout + while True: + (s,rev) = parse_svn_rev( s) + if not rev: + break + all_revs.append( rev) + return all_revs + + +def parse_svn_rev( s): + """Parse a revision from a svn log command""" + # parse the seperator line + sep_re = re.compile( "-----+") + sep_line = sep_re.match( s) + if not sep_line: + print "SVN revision log separator line not found: \"%s\"" % (s[0:80]) + return (s, None) + s = s[ sep_line.end()+1:] + if len(s) == 0: + return (s, None) + # parse the revision line + # :r1418023 | jani | 2012-12-06 19:30:45 +0100 (Thu, 06 Dec 2012) | 2 lines + rev_pattern = "r(\d+) \| (\w+) \| .* \| (\d+) lines?\n" + rev_re = re.compile( rev_pattern, re.MULTILINE) + m_rev = rev_re.match( s) + if m_rev == None: + print( "SVN revision header line not found: \"%s\" !!!" % (s[:200])) + return (s, None) + revnum = int(m_rev.group(1)) + author = m_rev.group(2) + linecnt = int(m_rev.group(3)) + s = s[ m_rev.end()+1:] + + # parse changed dirs + cdirs = [] + cpath_re = re.compile( "Changed paths?:\n", re.MULTILINE) + cpath_match = cpath_re.match( s) + if cpath_match: + s = s[ cpath_match.end():] + dir_re = re.compile( "\s+([MAD])\s+/?(.*?)$", re.MULTILINE) + while True: + m_dir = dir_re.match( s) + if m_dir == None: + break + cdirs.append( m_dir.group(2)) + s = s[ m_dir.end(2):] + + # parse commit comment + line_re = re.compile( ".*?$", re.MULTILINE) + idx = 0 + while linecnt > 0: + linecnt -= 1 + m_line = line_re.match(s,idx+1) + if m_line == None: + break + idx = m_line.end() + comment = s[:idx] + s = s[idx+2:] + return (s,Revision( revnum, author, comment, cdirs)) + + +def revs2info( htmlname, all_revs, svnurl, revmin, revmax): + """Create a HTML file with infos about revision range and its referenced issues""" + # emit html header to the info file + htmlfile = open( htmlname, "wb") + branchname = svnurl.split("/")[-1] + header = "<html><title>Annotated Log for r%d..r%d</title>\n" % (revmin, revmax) + header += "<body><h1>Revisions %d..%d from <a href=\"%s\">%s</a></h1>\n" % (revmin, revmax, svnurl, branchname) + htmlfile.write( header) + + # split revisions with issue references from other revisions + bugid_map = {} + other_revs = [] + for rev in all_revs: + if rev.issue: + bugid_map[ rev.issue] = True + else: + other_revs.append( rev.revnum) + + # emit info about issues referenced in revisions + if len(bugid_map): + htmlfile.write( "<h2>Issues addressed:</h2>\n<table border=\"0\">\n") + proxy = xmlrpclib.ServerProxy( bzsoap, verbose=False) + soaprc = proxy.Bug.get( {"ids" : bugid_map.keys()}) + open( bzout_name, "wb").write( str(soaprc)) + for bug in soaprc["bugs"]: + idnum = int( bug[ "id"]) + bug_url = bugref_url + str(idnum) + bug_desc = bug[ "summary"] + bug_type = bug[ "cf_bug_type"] + bug_target = bug[ "target_milestone"] + bug_status = bug[ "resolution"] + priority = int(bug[ "priority"][1:]) + + if bug_type == "DEFECT": + color = "#800000" + if priority <= 2: + color = "#F00000" + elif bug_type == "FEATURE": + color = "#008000#" + elif bug_type == "TASK": + color = "#000080#" + + line = "<tr>" + line += "<td><a href=\"%s\">#i%d#</a></td>" % (bug_url, idnum) + line += "<td>%s</td>" % (bug_type) + line += "<td>P%d</td>" % (priority) + line += "<td>%s</td>" % (bug_target) + line += "<td>%s</td>" % (bug_status) + line += "<td>" + if color: + line += "<font color=\"%s\">" % (color) + line += "%s" % (bug_desc.encode('utf-8', 'xmlcharrefreplace')) + if color: + line += "</font>" + line += "<td>" + line += "</tr>\n" + htmlfile.write( line) + + htmlfile.write( "</table>\n") + + # emit info about other revisions + if len(other_revs): + htmlfile.write( "<h2>Other Commits:</h2>\n<table border=\"0\">\n") + for rev in all_revs: + if rev.issue: + continue + line = "<tr>" + revurl = "http://svn-master.apache.org/viewvc?view=revision&revision=%d" % (rev.revnum) + line += "<td><a href=\"%s\">r%d</a></td>" % (revurl, rev.revnum) + summary = rev.log.splitlines()[0] + line += "<td>%s</td>" % (summary.encode('utf-8')) + line += "</tr>\n" + htmlfile.write( line) + + htmlfile.write( "</table>\n") + + # emit html footer to the info file + htmlfile.write( "</body></html>\n") + # print summary of the HTML file created + print "Processed %d revisions" % (len(all_revs)) + print "Found %d issues referenced" % (len(bugid_map)) + print "Wrote HTML file \"%s\"" % (htmlname) + + +def main(args): + if len(args) != 4: + print "Usage: " + args[0] + "branchname minrev maxrev" + sys.exit(1) + branchname = args[1] + revmin = int(args[2]) + revmax = int(args[3]) + + svnurl = "http://svn-master.apache.org/repos/asf/openoffice/%s" % (branchname) + svnout = open( svnout_name, "rb").read() + revlist = parse_svn_log( svnout) + revs2info( infoout_name, revlist, svnurl, revmin, revmax) + + +if __name__ == "__main__": + main(sys.argv[0:]) + Propchange: openoffice/devtools/scripts/svnlog2info.py ------------------------------------------------------------------------------ svn:executable = *