ooo-build r13527 - trunk/scratch/rcsutil
- From: michael svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r13527 - trunk/scratch/rcsutil
- Date: Tue, 12 Aug 2008 16:01:22 +0000 (UTC)
Author: michael
Date: Tue Aug 12 16:01:21 2008
New Revision: 13527
URL: http://svn.gnome.org/viewvc/ooo-build?rev=13527&view=rev
Log:
more work.
Added:
trunk/scratch/rcsutil/contributors.py
Modified:
trunk/scratch/rcsutil/parse_rcs.py
Added: trunk/scratch/rcsutil/contributors.py
==============================================================================
--- (empty file)
+++ trunk/scratch/rcsutil/contributors.py Tue Aug 12 16:01:21 2008
@@ -0,0 +1,979 @@
+#!/usr/bin/env python
+
+import sys, popen2, os.path, os
+import re
+import time, datetime
+import optparse
+
+# import local modules.
+sys.path.append(sys.path[0]+"/src")
+import revision, globals
+
+# just examine source code, avoiding binary bits & so on
+sourceExtension = {
+ '.c':1, '.cc':1, '.cpp':1, '.cs':1, '.csc':1, '.cxx':1,
+ '.h':1, '.hpp':1, '.hxx':1, '.idl':1, '.java':1,
+ '.py':1, '.sh':1, '.y':1}
+
+currentAffiliations = {
+ 'ab': 'Sun', # Andreas Bregas
+ 'abi': 'Sun', # Andreas Bille
+ 'ace_dent': 'unaffiliated', # Andrew Dent
+ 'af': 'Sun', # Andre Fischer
+ 'aidan': 'unaffiliated', # Aidan Butler
+ 'akhva': 'Sun', # Artem Khvat
+ 'aklitzing': 'unaffiliated', # Andre Klitzing (2006 GSoC student)
+ 'ama': 'Sun', # Andreas Martens
+ 'antoxu': 'Intel', # Antonio Xu
+ 'armin': 'Sun', # Armin Theissen
+ 'armin.theissen': 'Sun', # Armin Theissen
+ 'as': 'Sun', # Andreas Schluens
+ 'asrail': 'BrOffice.org', # Caio Tiago Oliveira
+ 'aw': 'Sun', # Armin Weiss
+ 'b_michaelsen': 'Sun', # Bjorn Michaelsen
+ 'bc': 'Sun', # Behrend Cornelius
+ 'bei': 'Sun', # Bernd Eilers
+ 'beppec56': 'unaffiliated', # Giuseppe Castagno
+ 'BerryJia': 'Sun', # Berry Jia
+ 'bh': 'Sun', # Bettina Haberer
+ 'Bibek': 'Trees For Life', # Bibek Sahu
+ 'bluedwarf': 'unaffiliated', # Takashi Nakamoto
+ 'bm': 'Sun', # Bjorn Milcke
+ 'bmahbod': 'unaffiliated', # Babak Mahbod
+ 'bnolte': 'unaffiliated', # Bertram Nolte
+ 'bustamam': 'unaffiliated', # Bustamam Harun
+ 'cd': 'Sun', # Carsten Driesner
+ 'ch2000liuy': 'Redflag', # YU Liu
+ 'chainchen': 'Redflag', # Jinhong Chen
+ 'cj': 'Sun', # Christian Jansen
+ 'cl': 'Sun', # Christian Lippka
+ 'cloph': 'unaffiliated', # Christian Lohmaier
+ 'cmc': 'RedHat', # Caolan McNamara
+ 'cn': 'Sun', # Christoph Neumann
+ 'coni': 'Sun', # Rafaella Braconi
+ 'cp': 'Sun', # Christof Pintaske
+ 'cphennessy': 'OpenApp', # Con Hennessy
+ 'cremlae': 'unaffiliated', # Omer Bar-or
+ 'cs': 'ProFOSS', # Claus Sorensen
+ 'Cyb': 'Trees For Life', # Christian Junker
+ 'cyrillem': 'Sun', # Cyrille Moureaux
+ 'davidfraser': 'translate.org.za', # David Fraser
+ 'dbo': 'Sun', # Daniel Boelzle
+ 'dfoster': 'Sun', # Duncan Foster
+ 'dg': 'Sun', # Dirk Grobler
+ 'dkeskar': 'Intel', # Dhananjay Keskar
+ 'dl': 'Sun', # Dieter Loeschky
+ 'doko': 'Canonical', # Matthias Klose
+ 'donqg': 'Redflag', # Quangang Dong
+ 'dr': 'Sun', # Daniel Rentz
+ 'drbyte': 'bytebot.net', # Colin Charles
+ 'dsherwin': 'Propylon', # Darragh Sherwin
+ 'duyunfen': 'Redflag', # Yunfen Du
+ 'dv': 'Sun', # Dirk Volzke
+ 'dvo': 'unaffiliated', # Daniel Vogelheim
+ 'ebischoff': 'Bureau Cornavin', # Eric Bischoff
+ 'ekato': 'unaffiliated', # Etsushi Kato
+ 'er': 'Sun', # Eike Rathke
+ 'erack': 'Sun', # Eike Rathke
+ 'ericb': 'unaffiliated', # Eric Bachard
+ 'fa': 'RedHat', # Dan Williams
+ 'fangyq': 'Redflag', # Yaqiong Fang
+ 'fdechelle': 'unaffiliated', # Francois Dechelle (works in api/exthome)
+ 'federicomena': 'Novell', # Federico Mena-Quinter
+ 'fheckl': 'unaffiliated', # Florian Heckl
+ 'filhocf': 'BrOffice.org', # Claudio F Filho
+ 'fl': 'Sun', # Frank Loehmann
+ 'flr': 'Novell', # Florian Reuter
+ 'fma': 'Sun', # Frank Mau
+ 'fme': 'Sun', # Frank Meies
+ 'fne': 'Sun', # Frank Neumann
+ 'fpe': 'Sun', # Frank Peters
+ 'fridrich_strba': 'Novell', # Fridrich Strba
+ 'fs': 'Sun', # Frank Schonheit
+ 'ganaya': 'unaffiliated', # Gene Anaya
+ 'Gao Peng': 'Redflag', # Peng Gao
+ 'gaozemin': 'Redflag', # Zemin Gao
+ 'georgez': 'unaffiliated', # George Zahopoulos
+ 'gh': 'Sun', # Gregor Hartmann
+ 'ghiggins': 'Sun', # Geoff Higgins
+ 'gm': 'Sun', # Gerd Weiss
+ 'grichter': 'MySQL', # Georg Richter
+ 'grsingleton': 'pathtech.org', # G. Roderick Singleton
+ 'gt': 'Sun', # Gunnar Timm (last commit in 2004)
+ 'gyang': 'Sun', ### unkown (2002 - 2005)
+ 'haggai': 'Debian', # Chris Halls
+ 'hbrinkm': 'Sun', # Henning Brinkmann
+ 'hdu': 'Sun', # Herbert Duerr
+ 'hjs': 'Sun', # Hans-Joachim Lankenau
+ 'hr': 'Sun', # Jens-Heiner Rechtien
+ 'hro': 'Sun', # Hennes Rohling
+ 'hub': 'Novell', # Hubert Figuiere
+ 'icobgr': 'unaffiliated', # Hristo Hristov
+ 'ih': 'Sun', # Ilko Hoepping (works on installation)
+ 'iha': 'Sun', # Ingrid Halama
+ 'ihi': 'Sun', # Ivo Hinkelmann
+ 'is': 'Sun', # Ingo Schmidt
+ 'isma87': 'unaffiliated', # Ismael Merzaq
+ 'ja': 'Sun', # Joost Andrae
+ 'jacky23': 'Redflag', # Sheng zhao
+ 'jakob_lechner': 'Fabalabs', # Jakob Lechner
+ 'jayant_madavi': 'Novell', # Jayant Balraj Madavi
+ 'jb': 'Sun', # Jorg Barfurth
+ 'jbrunsmann': 'unaffiliated', # Jorg Brunsmann
+ 'jbu': 'Sun', # Jorg Budischewski
+ 'jcn': 'Novell', # Jan Nieuwenhuizen
+ 'jiamingfei': 'IBM', # Mingfei Jia
+ 'jiangc': 'Redflag', # Chuang Jiang
+ 'jimmac': 'Novell', # Jacob Steiner
+ 'jj': 'Sun', # Jorg Jahnke
+ 'jl': 'Sun', # Joachim Lingner
+ 'jmarmion': 'Sun', # John Marmion
+ 'jmeng': 'Sun', ### unknown (2002 - 2005)
+ 'jobin': 'CollabNet', # Jobin Thomas
+ 'john.marmion': 'Sun', # John Marmion
+ 'jnavrati': 'RedHat', # Jan Navratil
+ 'jodygoldberg': 'Novell', # Jody Goldberg
+ 'jp': 'Sun', # Juergen Pingel (last commit in 2002)
+ 'jpryor': 'Novell', # Jonathan Pryor
+ 'jsc': 'Sun', # Jurgen Schmidt
+ 'jspindler': 'unaffiliated', # Jorg Spindler
+ 'jza': 'unaffiliated', # Alexandro Colorado
+ 'ka': 'Sun', # Kai Ahrens
+ 'kaib': 'Google', # Kai Backman
+ 'kangjingchuan': 'Redflag', # Jingchuan Kang
+ 'kcarr': 'Progbits', # Scott Carr
+ 'kendy': 'Novell', # Jan Holesovsky
+ 'khendricks': 'unaffiliated', # Kevin Hendricks
+ 'khirano': 'unaffiliated', # Hirano Kazunari
+ 'khong': 'Sun', # Karl Hong
+ 'kohei': 'Novell', # Kohei Yoshida
+ 'kr': 'Sun', # Kay Ramme
+ 'kso': 'Sun', # Kai Sommerfeld
+ 'kstribley': 'unaffiliated', # Keith Stribley
+ 'kz': 'Sun', # Kurt Zenker
+ 'larsbehr': 'Sun', # Lars Behrmann (AODL library, toolkit)
+ 'laurentgodard': 'inDesko/Nuxeo', # Laurent Godard
+ 'lh': 'Sun', # Lutz Hoeger
+ 'liangweike': 'Redflag', # Weike Liang
+ 'lijian': 'Redflag', # Jian Li
+ 'liujl': 'Redflag', # Jianli Liu
+ 'liutao': 'Redflag', # LiuTao
+ 'liuyuhua': 'Redflag', # Yuhua Liu
+ 'lixxing': 'IBM', # Xing Li
+ 'liyuan': 'Redflag', # Yuan Li
+ 'lkovacs': 'unaffiliated', # Laszlo Kovacs
+ 'lla': 'Sun', # Lars Langhans
+ 'lo': 'Sun', # Lars Oppermann
+ 'louis': 'Sun', # Louis Suarez-Potts
+ 'Luo Jingrong': 'Redflag', # Jingrong Luo
+ 'lvxg': 'Redflag', # Xugang Lv
+ 'lvyue': 'Redflag', # Yue Lv
+ 'maho': 'unaffiliated', # Nakata Maho
+ 'maoyonggang': 'Redflag', # Yonggang Mao
+ 'mav': 'Sun', # Mikhail Voitenko
+ 'maveric': 'unaffiliated', # Eric Hoch
+ 'mba': 'Sun', # Mathias Bauer
+ 'mbu': 'Sun', # Michael Buettner
+ 'mci': 'unaffiliated', # Michael Cziebalski
+ 'mfe': 'Sun', # Michael Ralf Fehr
+ 'mh': 'Sun', # Martin Hollmichel
+ 'mhu': 'Sun', # Matthias Huetsch
+ 'mi': 'Sun', # Michael Honnig
+ 'mib': 'Sun', # Michael Brauer
+ 'mikeleib': 'Intel', # Michael Leibowitz
+ 'mindyliu': 'unaffiliated', # Mindy Liu
+ 'mkretzschmar': 'Google', # Martin Kretzschmar
+ 'mloiseleur': 'Linagora', # Michel Loiseleur
+ 'mmaher': 'unaffiliated', # Martin Maher
+ 'mmeeks': 'Novell', # Michael Meeks
+ 'mmi': 'unaffiliated', # Michael Mi
+ 'mmp': 'Sun', # Matthias Muller-Prove
+ 'mnicel': 'Novell', # NicelKM
+ 'mod': 'unaffiliated', # Maximilian Odendahl
+ 'mox': 'unaffiliated', # Mox Soini
+ 'mrauch': 'unaffiliated', # Michael Rauch
+ 'msicotte': 'unaffiliated', # Michael Sicotte (Aqua port)
+ 'mst': 'Sun', # Michael Stahl (2007-current)
+ 'mt': 'Sun', # Malte Timmermann
+ 'mtg': 'unaffiliated', # Martin Gallwey
+ 'muthusuba': 'unaffiliated', # Muthu Subramanian
+ 'mwu': 'Sun', # Minna Wu (Sun China?)
+ 'nemeth': 'unaffiliated',
+ 'nf': 'Sun', # Nils Fuhrmann
+ 'nick': 'unaffiliated', # Nick Blievers
+ 'nn': 'Sun', # Niklas Nebel
+ 'np': 'Sun', # Nikolai Pretzell
+ 'npower': 'Novell', # Noel Power
+ 'obo': 'Sun', # Oliver Bolte
+ 'obr': 'Sun', # Oliver Braun
+ 'od': 'Sun', # Oliver Dusterhoff
+ 'oj': 'Sun', # Ocke Janssen
+ 'OPENSTEP': 'unaffiliated', # Edward Peterlin
+ 'os': 'Sun', # Oliver Specht
+ 'pagalmes': 'StarXpert', # Pierre-Andre Galmes
+ 'pb': 'Sun', # Peter Burow
+ 'pdefilippis': 'unaffiliated', # Pierre de Filippis
+ 'pereriksson': 'unaffiliated', # Per Eriksson
+ 'pflin': 'Novell', # Fong Lin
+ 'pj': 'Redflag', # Peter Junge
+ 'pjanik': 'unaffiliated', # Pavel Janik
+ 'pjunck': 'Sun', # Pascal Junck
+ 'pl': 'Sun', # Philipp Lohmann
+ 'pliao': 'unaffiliated', # Ping Liao
+ 'plipli': 'unaffiliated', # Sebastien Plisson
+ 'pluby': 'unaffiliated', # Patrick Luby
+ 'pmadhav': 'Intel', # Prasad Madhav
+ 'pmladek': 'Novell', # Petr Mladek
+ 'quch': 'Redflag', # Canghua Qu
+ 'radekdoulik': 'Novell', # Radek Doulik
+ 'rail': 'Infra-Resource', # Rail Aliev
+ 'rajeshsola': 'NOSIP', # Rajesh Sola
+ 'rene': 'Debian', # Rene Engelhard
+ 'Rescue/k0fcc': 'Canonical', # Joey Stanford
+ 'rkinsella': 'Sun', # Robert Kinsella
+ 'rodarvus': 'INdT', # Rodrigo Parra Novo
+ 'rpiterman': 'unaffiliated', # Ron Piterman
+ 'rsiddhartha': 'Novell', # Raul Siddhartha
+ 'rt': 'Sun', # Rudiger Timm
+ 'rvojta': 'unaffiliated', # Robert Vojta
+ 'sab': 'Sun', # Sascha Ballach
+ 'sb': 'Sun', # Stephan Bergmann
+ 'schmidtm': 'Sun', # Matthias Schmidt
+ 'sewardj': 'unaffiliated', # Julian Seward
+ 'sg': 'Sun', # Steffen Grund
+ 'sgauti': 'unaffiliated', # Sophie Gautier
+ 'shilei': 'Redflag', # Lei shi
+ 'shiwg': 'IBM', # Wei Guo SHI
+ 'shizhoubo': 'Redflag', # Zhoubo Shi
+ 'sj': 'Sun', # Sven Jacobi
+ 'sjanki': 'unaffiliated', # Sunil Amitkumar Janki
+ 'smmathews': 'unaffiliated', # Shane M Mathews
+ 'smsm1': 'unaffiliated', # Shaun McDonald
+ 'sparcmoz': 'clug.org.au', # Jim Watson
+ 'ssa': 'Sun', # Stephan Schaefer
+ 'ssmith': 'unaffiliated', # Sarah Smith
+ 'st': 'Sun', # Stefan Taxhet
+ 'sts': 'Sun', # Stella Schulze
+ 'sus': 'Sun', # Svante Schubert (2000-current)
+ 'svesik': 'Sun', # Sander Vesik
+ 'sw': 'unaffiliated', # Stephan Wunderlich
+ 'tbe': 'Sun', # Thomas Benisch
+ 'th': 'Sun', # Thomas Hosemann
+ 'thb': 'Novell', # Thorsten Behrens
+ 'tietjens': 'unaffiliated', # Jan Tietjens
+ 'timseves': 'SIL', # Tim Seves
+ 'tkr': 'Sun', # Tobias Krause
+ 'tl': 'Sun', # Thomas Lange
+ 'tml': 'Novell', # Tor Lillqvist
+ 'tmorgner': 'Pentaho', # Thomas Morgner (Pentaho reporting engine)
+ 'toconnor': 'unaffiliated', # Tomas O'Connor
+ 'tonn': 'unaffiliated', # Gerhard Tonn
+ 'tonygalmiche': 'unaffiliated', # Tony Galmiche
+ 'tpf': 'Sun', # Thomas Pfohe
+ 'tqfa': 'Redflag', # Quanfa Tang
+ 'tra': 'Sun', # Tino Rachui
+ 'tv': 'Sun', # Tom Verbeek
+ 'ufi': 'Sun', # Uwe Fischer
+ 'us': 'Sun', # Ulf Stroehler
+ 'va': 'Sun', # Volker Ahrendt
+ 'vg': 'Sun', # Vladimir Glazounov
+ 'volody': 'unaffiliated', # Volodymyr Khrystynych
+ 'vq': 'Gravity Waves', # Volker Quetschke
+ 'wangyumin_ccoss': 'CCOSS',
+ 'waratah': 'slug.org.au', # Ken Foskey
+ 'weiz': 'Redflag', # Zhao Wei
+ 'willem.vandorp': 'unaffiliated', # Willem van Dorp
+ 'windly': 'unaffiliated', # Wind Li
+ 'wlach': 'Net Integration Technologies', # Will Lachance
+ 'wuy': 'Redflag', # Yan Wu
+ 'xudehua': 'Redflag', # Dehua Xu
+ 'xxjack12xx': 'unaffiliated', # Jackson Low
+ 'xzcheng': 'Redflag', # Xiuzhi Cheng
+ 'ydario': 'Serenity Systems intl', # Yuri Dario
+ 'zhanghuajun': 'Redflag', # Huajun Zhang
+ 'Zhangxiaofei': 'Redflag', # Xiaofei Zhang
+ 'zhaojianwei': 'Redflag', # Jianwei Zhao
+ 'zhiming': 'Intel'} # Jeremy Zheng
+
+
+def getAffiliation (name, date):
+ affil = '(unknown)'
+ if currentAffiliations.has_key(name):
+ affil = currentAffiliations[name]
+
+ # Process names whose affiliations have changed over time.
+
+ if name == 'thb':
+ # Thorsten joined Novell in Feb 2008.
+ dateJoinedNovell = datetime.datetime(2008, 2, 1)
+ if date < dateJoinedNovell:
+ affil = 'Sun'
+ else:
+ affil = 'Novell'
+
+ elif name == 'flr':
+ # Florian joined Novell in Nov 2006.
+ dateJoinedNovell = datetime.datetime(2006, 11, 1)
+ if date < dateJoinedNovell:
+ affil = 'Sun'
+ else:
+ affil = 'Novell'
+
+ elif name == 'npower':
+ # Noel joined Novell in July of 2005.
+ dateJoinedNovell = datetime.datetime(2005, 7, 1)
+ if date < dateJoinedNovell:
+ affil = 'Sun'
+ else:
+ affil = 'Novell'
+
+ elif name == 'fridrich_strba':
+ dateJoinedNovell = datetime.datetime(2007, 3, 1)
+ if date < dateJoinedNovell:
+ affil = 'unaffiliated'
+ else:
+ affil = 'Novell'
+
+ elif name == 'kohei':
+ dateJoinedNovell = datetime.datetime(2007, 3, 1)
+ if date < dateJoinedNovell:
+ affil = 'unaffiliated'
+ else:
+ affil = 'Novell'
+
+ elif name == 'cmc':
+ # Caolan moved from Sun to RedHat about March of 2004.
+ dateJoinedRH = datetime.datetime(2004, 3, 1)
+ if date < dateJoinedRH:
+ affil = 'Sun'
+ else:
+ affil = 'RedHat'
+
+ return affil
+
+
+
+
+class RCSFile(globals.Debuggable):
+
+ # alpha numeric letter
+ alphnum = '([a-z]|[A-Z]|[0-9])'
+
+ # regex pattern for category match
+ reCategory = '^' + alphnum + '(' + alphnum + '|\ )*\:'
+
+ # regex pattern for revision separator
+ reRevSeparator = '^\-{28}$'
+
+
+ def __init__ (self, lines, ext, filepath):
+ globals.Debuggable.__init__(self)
+
+ self.lines = lines
+ self.lineCount = len(self.lines)
+ self.ext = ext
+ self.filepath = filepath;
+ self.reset()
+
+
+ def reset (self):
+ self.headers = {}
+ self.revTree = revision.RevisionTree()
+ self.commitLogs = []
+ self.descError = False
+ self.symbolicNamesError = False
+ self.miscError = False
+
+ def parse (self):
+ self.reset()
+
+ rePattern = re.compile(RCSFile.reCategory)
+ i = 0
+ while i < self.lineCount:
+ line = self.lines[i].rstrip()
+ res = rePattern.search(line)
+ if res == None:
+ # no regex match found
+ i += 1
+ continue
+
+ category = res.group(0)[:-1]
+ if category == 'symbolic names':
+ i = self.__parseSymbolicNames(i+1)
+ continue
+
+ if category == 'description':
+ i = self.__parseDescription(i+1)
+ break
+
+ self.headers[category] = line[res.end(0):].strip()
+ i += 1
+
+
+ def outputRevTree (self):
+ self.revTree.output()
+
+ def getBranchName (self, revision):
+ return self.revTree.getBranchName(revision)
+
+ def output (self):
+ for key in self.headers.keys():
+ print key + " -> '" + self.headers[key] + "'"
+
+ for commitLog in self.commitLogs:
+ print ('-'*45)
+ keys = commitLog.keys()
+ keys.sort()
+ for key in keys:
+ print (key, "->", commitLog[key])
+
+
+ def isError (self):
+ return self.descError or self.symbolicNamesError or self.miscError
+
+
+ def __parseSymbolicNames (self, i):
+
+ # [tab]symbol name: branch number
+
+ while i < self.lineCount:
+ line = self.__getLine(i)
+ if len(line) == 0:
+ break
+
+ if ord(line[0]) != 0x09:
+ # First character is not a tab. End of symbolic names.
+ return i
+
+ name, number = line.split(':')
+ name = name.strip()
+ number = number.strip()
+
+ self.revTree.addSymbol(name, number)
+ i += 1
+
+ self.symbolicNamesError = True
+ self.debugPrint("error parsing symbolic names", True)
+ return i
+
+
+ def __getLine (self, i):
+ return self.lines[i].rstrip()
+
+
+ def __isRevSeparator (self, i):
+ line = self.__getLine(i)
+ reobj = re.compile(RCSFile.reRevSeparator)
+ res = reobj.match(line)
+ return res != None
+
+
+ def __isEndLogSeparator (self, i):
+ line = self.__getLine(i)
+ return line == '='*77
+
+
+ def __parseDescription (self, i):
+ """ Parse commit records.
+
+A typical comment record would look like this:
+
+ ----------------------------
+ revision 1.43.38.1
+ date: 2005/10/25 12:31:22; author: jodygoldberg; state: Exp; lines: +8 -4
+ Issue number: 20857
+
+ Trying to get this patch out of my tree into a CWS.
+ The full commit failed, let's try smaller chunks.
+ ----------------------------
+
+The first two lines contain auxiliary information about the commit, while the
+rest of the lines contain commit message.
+"""
+ if self.__isEndLogSeparator(i):
+ # The description block is empty. This happens when the file is
+ # committed initially without any subsequent commits.
+ return i
+
+ if not self.__isRevSeparator(i):
+ self.descError = True
+ self.debugPrint("revision separator expected", True)
+ return i
+
+ self.debugPrint(self.__getLine(i))
+ i += 1
+
+ while i < self.lineCount:
+ self.debugPrint(self.__getLine(i))
+ commitLog = {}
+
+ # revision 1.43.38.1
+ line = self.__getLine(i)
+ if line.find('revision') != 0:
+ self.descError = True
+ self.debugPrint("revision number not found: '" + line + "'", True)
+ return i
+
+ revnum = line.split()[1].strip()
+ commitLog['revision'] = revnum
+ try:
+ branch = self.revTree.getBranchName(revnum)
+ commitLog['branch'] = branch
+ except revision.RevisionError:
+ pass
+
+ i += 1
+ self.debugPrint(self.__getLine(i))
+
+ line = self.__getLine(i)
+ if not self.__parseDescData(line, commitLog):
+ self.descError = True
+ self.debugPrint("error parsing description data", True)
+ return i
+
+ i += 1
+
+ # the rest is a commit message.
+ msg = []
+ while i < self.lineCount:
+ self.debugPrint(self.__getLine(i))
+ if self.__isRevSeparator(i):
+ break
+ elif self.__isEndLogSeparator(i):
+ return i
+ line = self.__getLine(i)
+ msg.append(line)
+ i += 1
+
+ commitLog['message'] = msg
+ self.commitLogs.append(commitLog)
+
+ i += 1
+
+ return i
+
+
+ def __parseDescData (self, line, commitLog):
+
+ # date: 2005/10/25 12:31:22; author: jodygoldberg; state: Exp; lines: +8 -4
+
+ rePattern = re.compile(RCSFile.reCategory)
+ for segment in line.split(';'):
+ segment = segment.strip()
+ if len(segment) == 0:
+ continue
+
+ res = rePattern.search(segment)
+ if res == None:
+ self.debugPrint("category name not found: '" + segment + "'")
+ return False
+
+ category = res.group(0)[:-1]
+ value = segment[res.end(0):].strip()
+ if category == 'date':
+ # parse & transform a string date value into a datetime object.
+ try:
+ timeValue = time.strptime(value, "%Y/%m/%d %H:%M:%S")
+ dtobj = datetime.datetime(timeValue[0], timeValue[1], timeValue[2],
+ timeValue[3], timeValue[4], timeValue[5])
+ commitLog[category] = dtobj
+ except ValueError:
+ self.debugPrint("failed to parse a date value: '" + value + "'")
+ return False
+
+ elif category == 'lines':
+ # number of lines added
+ reNum = re.compile('\+[0-9]*')
+ res = reNum.search(value)
+ if res == None:
+ self.debugPrint("number of added lines not found")
+ return False
+
+ added = int(res.group(0))
+
+ # number of lines removed
+ reNum = re.compile('\-[0-9]*')
+ res = reNum.search(value)
+ if res == None:
+ self.debugPrint("number of removed lines not found")
+ return False
+
+ removed = abs(int(res.group(0)))
+
+ # correct for separate $Revision and $Date changes in every commit
+ if added > 2:
+ added -= 2
+ else:
+ added = 0
+ if removed > 2:
+ removed -= 2
+ else:
+ removed = 0
+
+ commitLog['added'] = added
+ commitLog['removed'] = removed
+
+ else:
+ commitLog[category] = value
+
+ return True
+
+
+ def __isResyncCommit (self, msglines):
+ reResync = re.compile('^RESYNC:.*;')
+ for msgline in msglines:
+ res = reResync.search(msgline)
+ if res != None:
+ return True
+ return False
+
+ def __isCwsIntegrationCommit (self, msglines):
+ reCwsIntegration = re.compile('^INTEGRATION:\ CWS')
+ for msgline in msglines:
+ res = reCwsIntegration.search(msgline)
+ if res != None:
+ return True
+ return False
+
+ def writeCommitStats (self, statObj, filePath):
+ """Write commit statistics to the passed CommitStats instance.
+
+Each commit log may have the following data:
+
+ * added - number of lines added (integer).
+ * removed - number of lines removed (integer).
+ * date - commit date and time (datetime object).
+ * author - who made the commit (string).
+ * revision - revision number (string)
+ * branch - name of the branch to which the commit was made (string).
+ * state - state of the file ??? (string)
+ * message - commit message (string list).
+
+Each commit log is supposed to have at least the author, revision and the date
+records, while some logs may not have the added/removed line information (such
+as initial commits, branch nodes etc.
+
+Also, disregard commits whose message contains RESYNC or INTEGRATION: CWS.
+"""
+
+ issueNum = 'i[1-9][0-9]+'
+ reIssueNumbers = []
+# reIssueNumbers.append(re.compile('^#' + issueNum + '#'))
+# reIssueNumbers.append(re.compile('^Issue number:\ *' + issueNum))
+ reIssueNumbers.append(re.compile(issueNum))
+
+ for log in self.commitLogs:
+
+ statObj.totalCommitCount += 1
+
+ if log.has_key('message'):
+
+ # Check the message and disregard RESYNC commits.
+ if self.__isResyncCommit(log['message']):
+ statObj.resyncCommitCount += 1
+ continue
+
+ # Skip if this is a CWS integration commit.
+ if self.__isCwsIntegrationCommit(log['message']):
+ statObj.integrationCommitCount += 1
+ continue
+
+ # Check the message to see if this is a patch submission.
+ isIssueNumber = False
+ for msgline in log['message']:
+ for reIssueNumber in reIssueNumbers:
+ res = reIssueNumber.search(msgline)
+ if res != None:
+ txt = msgline[res.start(0):res.end(0)]
+ isIssueNumber = True
+ break
+
+ if isIssueNumber:
+ break
+
+ if isIssueNumber:
+ statObj.patchCommitCount += 1
+
+ if log.has_key('branch'):
+ branch = log['branch']
+ else:
+ branch = ''
+
+ # author
+ if not log.has_key('author'):
+ self.debugPrint("author record is absent")
+ return False
+ author = log['author']
+
+ # date
+ if not log.has_key('date'):
+ self.debugPrint("date record is absent")
+ return False
+ date = log['date']
+
+ # added
+ added = 0
+ if log.has_key('added'):
+ added = log['added']
+
+ # removed
+ removed = 0
+ if log.has_key('removed'):
+ removed = log['removed']
+
+ if added or removed:
+ statObj.add(author, date, self.ext, added, removed, branch, self.filepath)
+ self.debugPrint ("commit %s counted +%d -%d\n"%(log['revision'], added, removed));
+
+ return True
+
+
+class CommitStats(object):
+
+ class Author(object):
+ def __init__ (self):
+ self.years = {}
+
+ class Year(object):
+ def __init__ (self):
+ self.months = {}
+
+ class Month(object):
+ def __init__ (self):
+ self.affiliation = '(unknown)'
+ self.commitCounts = 0
+ self.linesAdded = 0
+ self.linesRemoved = 0
+ self.warned = 0;
+
+ def __init__ (self):
+ self.authors = {}
+ self.totalFileCount = 0
+ self.totalCommitCount = 0
+ self.resyncCommitCount = 0
+ self.integrationCommitCount = 0
+ self.ignoredByBranchCount = 0
+ self.ignoredByAuthorCount = 0
+ self.patchCommitCount = 0
+
+ def add (self, author, date, ext, added, removed, branch, filePath):
+
+ # author node
+ if not self.authors.has_key(author):
+ self.authors[author] = CommitStats.Author()
+ authorObj = self.authors[author]
+
+ # year node
+ if not authorObj.years.has_key(date.year):
+ authorObj.years[date.year] = CommitStats.Year()
+ yearObj = authorObj.years[date.year]
+
+ # month node
+ if not yearObj.months.has_key(date.month):
+ yearObj.months[date.month] = CommitStats.Month()
+ monthObj = yearObj.months[date.month]
+ extObj = monthObj
+
+ extObj.affiliation = getAffiliation(author, date)
+ extObj.commitCounts += 1
+ extObj.linesAdded += added
+ extObj.linesRemoved += removed
+
+
+class Main(object):
+
+ def __init__ (self):
+ self.stats = CommitStats()
+ self.debug = False
+ self.verbose = False
+
+ self.isError = False
+
+ def main (self):
+
+ optparser = optparse.OptionParser()
+ optparser.usage += " file1, file2, ..."
+
+ helptext = """specify a file that contains a list of directories to walk.
+Each line in the file must correspond to each directory path. If a directory
+path is relative, it is relative to the current directory."""
+ optparser.add_option('', '--dir-list',
+ action="store", type="string", dest='dirlist',
+ help=helptext, metavar='FILE')
+
+ helptext = """output debug messages to stderr."""
+ optparser.add_option('-d', '--debug',
+ action="store_true", dest="debug",
+ help=helptext)
+
+ helptext = """set verbose mode."""
+ optparser.add_option('-v', '--verbose',
+ action="store_true", dest="verbose",
+ help=helptext)
+
+ helptext = """specify output file to write result to."""
+ optparser.add_option('-o', '--output-file',
+ action='store', type='string', dest='outputfile',
+ help=helptext, metavar='FILE')
+
+ options, args = optparser.parse_args()
+
+ self.debug = options.debug
+ self.verbose = options.verbose
+
+ outfile = options.outputfile
+
+ # Check to make sure I have rlog.
+ r, w, e = popen2.popen3("/usr/bin/which rlog")
+ if len(r.read()) == 0:
+ sys.stderr.write("rlog command not available. You need to install rcs.")
+ sys.exit(1)
+
+ r.close()
+ w.close()
+ e.close()
+
+ if options.dirlist != None:
+ # directory list exists.
+ self.__useDirectoryList(options.dirlist)
+
+ filepaths = args
+
+ for filepath in filepaths:
+ if os.path.isfile(filepath):
+ r = self.__openRCSFile(filepath)
+ if not r:
+ sys.stderr.write("failed to parse %s\n"%filepath)
+ sys.exit(1)
+ elif os.path.isdir(filepath):
+ self.__parseDir(filepath)
+
+ fd = sys.stdout
+ if outfile != None and not os.path.isdir(outfile):
+ fd = open(outfile, 'w')
+
+ self.__outputReport(fd)
+
+
+ def __useDirectoryList (self, filepath):
+ if len(filepath) > 0 and filepath[0] == '~':
+ filepath = os.environ['HOME'] + filepath[1:]
+
+ filepath = os.path.abspath(filepath)
+ if not os.path.isfile(filepath):
+ sys.stderr.write("%s is not a file\n"%filepath)
+ sys.exit(1)
+
+ for dirpath in open(filepath).readlines():
+ dirpath = dirpath.strip()
+ if len(dirpath) == 0:
+ continue
+ dirpath = os.path.abspath(dirpath)
+ if not os.path.isdir(dirpath):
+ continue
+ self.__parseDir(dirpath)
+
+
+ def __parseDir (self, dirpath):
+ if self.verbose:
+ print("parsing directory %s"%dirpath)
+
+ for root, dirs, files in os.walk(dirpath):
+ for filename in files:
+ fullpath = root + '/' + filename
+ r = self.__openRCSFile(fullpath)
+ if not r:
+ sys.stderr.write("failed to parse %s\n"%fullpath)
+ sys.exit(1)
+
+
+ def __getExtension (self, filepath):
+ if filepath[-2:] != ',v':
+ # this isn't a right RCS file name.
+ sys.stderr.write("This is not an RCS file: %s\n"%filepath)
+ sys.exit(1)
+ filepath = filepath[:-2]
+ ext = os.path.splitext(filepath)[1]
+ return ext
+
+
+ def __openRCSFile (self, filepath):
+
+ if filepath[-2:] != ',v':
+ # this isn't a right RCS file name. Skip it.
+ if self.verbose:
+ sys.stdout.write("Skipping a non-RCS file: %s\n"%filepath)
+ return True
+
+ no_attic_path = re.subn ("/Attic/", "/", filepath)[0]
+
+ extn = self.__getExtension(filepath)
+ if not sourceExtension.has_key(extn):
+ if self.verbose:
+ sys.stdout.write("Skipping a non-source file: %s\n"%filepath)
+ return True
+
+ cmd = "rlog " + filepath
+ r, w, e = popen2.popen3(cmd)
+ lines = r.readlines()
+ r.close()
+ w.close()
+ e.close()
+
+ obj = RCSFile(lines, extn, filepath);
+ obj.debug = self.debug
+ obj.parse()
+ if obj.isError():
+ sys.stderr.write("error parsing " + filepath + "\n")
+ self.isError = True
+
+# obj.outputRevTree()
+# obj.output()
+
+ if not obj.writeCommitStats(self.stats, filepath):
+ sys.stderr.write("failed to write commit stats\n")
+ sys.exit(1)
+
+
+ self.stats.totalFileCount += 1
+
+ return not obj.isError()
+
+
+ def __outputReport (self, fd):
+ authorNames = self.stats.authors.keys()
+ authorNames.sort()
+ fd.write("author\tyear\tmonth\taffiliation\tcommit count\tlines added\tlines removed\tdate\n")
+ for authorName in authorNames:
+ authorObj = self.stats.authors[authorName]
+ years = authorObj.years.keys()
+ years.sort()
+ for year in years:
+ yearObj = authorObj.years[year]
+ months = yearObj.months.keys()
+ months.sort()
+ for month in months:
+ monthObj = yearObj.months[month]
+ extObj = monthObj
+ fd.write("%s\t%d\t%d\t%s\t%d\t%d\t%d\t%d-%d-1\n"%(
+ authorName, year, month,
+ extObj.affiliation,
+ extObj.commitCounts,
+ extObj.linesAdded,
+ extObj.linesRemoved,
+ year, month))
+
+ fd.write("\n")
+ fd.write("total file count\t%d\n"%self.stats.totalFileCount)
+ fd.write("total commit count\t%d\n"%self.stats.totalCommitCount)
+ fd.write("cws integration commits ignored\t%d\n"%self.stats.integrationCommitCount)
+ fd.write("resync commits ignored\t%d\n"%self.stats.resyncCommitCount)
+ fd.write("commits ignored by branch name\t%d\n"%self.stats.ignoredByBranchCount)
+ fd.write("commits ignored by author name\t%d\n"%self.stats.ignoredByAuthorCount)
+ fd.write("issue numbers found\t%d\n"%self.stats.patchCommitCount)
+
+
+
+if __name__ == '__main__':
+ mainObj = Main()
+ mainObj.main()
Modified: trunk/scratch/rcsutil/parse_rcs.py
==============================================================================
--- trunk/scratch/rcsutil/parse_rcs.py (original)
+++ trunk/scratch/rcsutil/parse_rcs.py Tue Aug 12 16:01:21 2008
@@ -26,6 +26,7 @@
'cws_src680_basmgr02' : [ 'framework/binfilter/' ],
'cws_src680_hr38' : [ 'framework/binfilter/' ],
'cws_src680_bff2' : [ 'framework/binfilter/' ],
+ 'cws_src680_picom' : [ 'graphics/slideshow/' ],
}
# all commmits done by the following authors are ignored
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]