Last active
December 14, 2015 08:28
-
-
Save ganadist/5057717 to your computer and use it in GitHub Desktop.
get commit count from AOSP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding : utf-8 -*- | |
import sys, os | |
import subprocess | |
import xml.dom.minidom | |
BOTS = ('[email protected]', | |
'[email protected]', | |
'[email protected]', | |
'[email protected]', | |
'[email protected]', | |
'[email protected]', | |
) | |
NOBODY = ('', '[email protected]') | |
def isBot(email): | |
if email in BOTS: return True | |
return email.startswith('android-build') | |
def isGoogler(email): | |
if email.endswith('google.com'): | |
return True | |
if email.endswith('android.com'): | |
return True | |
return email == '' | |
def getManifest(path): | |
return os.path.join(path, '.repo', 'manifest.xml') | |
def getTop(): | |
def isTopDir(path): | |
return os.access(getManifest(path), os.F_OK) | |
def getParents(): | |
for env in ('TOP', 'ANDROID_BUILD_TOP'): | |
wd = os.getenv(env) | |
if wd: yield wd | |
wd = os.path.abspath(os.getcwd()) | |
while wd != os.path.sep: | |
yield wd | |
wd = os.path.dirname(wd) | |
for path in getParents(): | |
if isTopDir(path): | |
return path | |
assert False, "can not find android source directory." | |
def getPaths(path): | |
manifest = getManifest(path) | |
root = xml.dom.minidom.parse(manifest) | |
for node in root.childNodes[0].childNodes: | |
if node.nodeName != 'project': | |
continue | |
yield node.getAttribute('path') | |
def getAuthors(path): | |
gitdir = os.path.join(path, '.git') | |
cmd = ('git', 'log', '--no-merges', '--pretty=%ae %an') | |
p = subprocess.Popen(cmd, stdout = subprocess.PIPE, | |
env = {'GIT_DIR': gitdir}) | |
for line in p.stdout: | |
line = line.strip() | |
if '@' in line: | |
if ' ' in line: | |
email, name = line.split(' ', 1) | |
else: | |
email, name = line, '' | |
else: | |
email, name = '', line | |
yield email, name | |
class AuthorCount(object): | |
def __init__(self, email): | |
object.__init__(self) | |
self.email = email | |
self.names = [] | |
self.count = 0 | |
def getName(self): | |
return self.names and self.names[0] or '' | |
def getCount(self): | |
return self.count | |
def getEmail(self): | |
return self.email | |
def incCount(self, name): | |
if not name in self.names: | |
def nameSort(a, b): | |
if a.islower(): return 1 | |
if b.islower(): return -1 | |
return cmp(b, a) | |
self.names.append(name) | |
self.names.sort(nameSort) | |
self.count += 1 | |
def __str__(self): | |
if self.email: | |
mail = self.email.replace('@', ' at ').replace('.', ' dot ') | |
else: | |
mail = 'UNKNOWN_AT_GOOGLE_DOT_COM' | |
return '%s <%s>\t %d'%(self.getName(), mail, self.count) | |
if __name__ == '__main__': | |
d = {} | |
top = getTop() | |
platformPrefix = ('frameworks', | |
'bionic', | |
'system', | |
'hardware', | |
'build', | |
'dalvik', | |
'libcore', | |
) | |
platformOnly = '-p' in sys.argv | |
commitCountLimit = platformOnly and 500 or 1000 | |
def isPlatform(path): | |
for prefix in platformPrefix: | |
if path.startswith(prefix): | |
return True | |
for path in getPaths(top): | |
if platformOnly and not isPlatform(path): | |
continue | |
for author in getAuthors(path): | |
email, name = author | |
if isBot(email): | |
continue | |
if not isGoogler(email): | |
continue | |
if email in NOBODY: | |
key = 'NOBODY', name | |
email = '' | |
else: | |
if email.endswith('corp.google.com'): | |
email = email.split('@', 1)[0] + '@google.com' | |
key = email, '' | |
d.setdefault(key, AuthorCount(email)).incCount(name) | |
names = {} | |
for item in d.iteritems(): | |
k, v = item | |
name = v.getName() | |
names.setdefault(name, set()).add(item) | |
# get delegate account in duplicated | |
def getDelegates(items): | |
google_account = set() | |
android_account = set() | |
for key, value in items: | |
email = value.getEmail() | |
if email.endswith('google.com'): | |
google_account.add((key, value)) | |
elif email.endswith('android.com'): | |
android_account.add((key, value)) | |
return google_account and google_account or android_account | |
# merge duplicated account | |
for items in names.itervalues(): | |
if len(items) == 1: continue | |
delegates = getDelegates(items) | |
if len(delegates) != 1: continue | |
delegate = tuple(delegates)[0][1] | |
for k, v in items - delegates: | |
del d[k] | |
delegate.count += v.count | |
countKey = lambda x:x.getCount() | |
nameKey = lambda x:x.getName() | |
emailKey = lambda x:x.getEmail() | |
count = 0 | |
for item in sorted(d.itervalues(), key = countKey): | |
#if d[item].count < commitCountLimit: continue | |
sys.stdout.write('%s\n'%(str(item))) | |
count += item.getCount() | |
print 'total commit count:', count |
Author
ganadist
commented
Feb 28, 2013
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment