summaryrefslogtreecommitdiff
path: root/scratch/rcsutil/contributors.py
diff options
context:
space:
mode:
Diffstat (limited to 'scratch/rcsutil/contributors.py')
-rwxr-xr-xscratch/rcsutil/contributors.py979
1 files changed, 0 insertions, 979 deletions
diff --git a/scratch/rcsutil/contributors.py b/scratch/rcsutil/contributors.py
deleted file mode 100755
index 8bf6f464d..000000000
--- a/scratch/rcsutil/contributors.py
+++ /dev/null
@@ -1,979 +0,0 @@
-#!/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()