2000-10-03 22:10:25 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
"""Script to locate email addresses in the CVS logs."""
|
|
|
|
__version__ = '$Revision$'
|
|
|
|
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
import UserDict
|
|
|
|
|
2000-10-06 16:37:47 +00:00
|
|
|
import cvsinfo
|
2000-10-03 22:10:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Acknowledgements(UserDict.UserDict):
|
|
|
|
def add(self, email, name, path):
|
|
|
|
d = self.data
|
|
|
|
d.setdefault(email, {})[path] = name
|
|
|
|
|
|
|
|
|
|
|
|
def open_cvs_log(info, paths=None):
|
|
|
|
cvsroot = info.get_cvsroot()
|
|
|
|
cmd = "cvs -q -d%s log " % cvsroot
|
|
|
|
if paths:
|
|
|
|
cmd += " ".join(paths)
|
|
|
|
return os.popen(cmd, "r")
|
|
|
|
|
|
|
|
|
|
|
|
email_rx = re.compile("<([a-z][-a-z0-9._]*@[-a-z0-9.]+)>", re.IGNORECASE)
|
|
|
|
|
|
|
|
def find_acks(f, acks):
|
|
|
|
prev = ''
|
|
|
|
filename = None
|
|
|
|
MAGIC_WORDS = ('van', 'von')
|
|
|
|
while 1:
|
|
|
|
line = f.readline()
|
|
|
|
if not line:
|
|
|
|
break
|
|
|
|
if line.startswith("Working file: "):
|
|
|
|
filename = line.split(None, 2)[2].strip()
|
|
|
|
prev = line
|
|
|
|
continue
|
|
|
|
m = email_rx.search(line)
|
|
|
|
if m:
|
|
|
|
words = prev.split() + line[:m.start()].split()
|
|
|
|
L = []
|
|
|
|
while words \
|
|
|
|
and (words[-1][0].isupper() or words[-1] in MAGIC_WORDS):
|
|
|
|
L.insert(0, words.pop())
|
|
|
|
name = " ".join(L)
|
|
|
|
email = m.group(1).lower()
|
|
|
|
acks.add(email, name, filename)
|
|
|
|
prev = line
|
|
|
|
|
|
|
|
|
|
|
|
def load_cvs_log_acks(acks, args):
|
2000-10-06 16:37:47 +00:00
|
|
|
repolist = cvsinfo.get_repository_list(args or [""])
|
2000-10-03 22:10:25 +00:00
|
|
|
for info, paths in repolist:
|
|
|
|
print >>sys.stderr, "Repository:", info.get_cvsroot()
|
|
|
|
f = open_cvs_log(info, paths)
|
|
|
|
find_acks(f, acks)
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
|
|
|
def load_tex_source_acks(acks, args):
|
|
|
|
for path in args:
|
|
|
|
path = path or os.curdir
|
|
|
|
if os.path.isfile(path):
|
|
|
|
read_acks_from_tex_file(acks, path)
|
|
|
|
else:
|
|
|
|
read_acks_from_tex_dir(acks, path)
|
|
|
|
|
|
|
|
|
|
|
|
def read_acks_from_tex_file(acks, path):
|
|
|
|
f = open(path)
|
|
|
|
while 1:
|
|
|
|
line = f.readline()
|
|
|
|
if not line:
|
|
|
|
break
|
|
|
|
if line.startswith(r"\sectionauthor{"):
|
|
|
|
line = line[len(r"\sectionauthor"):]
|
|
|
|
name, line = extract_tex_group(line)
|
|
|
|
email, line = extract_tex_group(line)
|
|
|
|
acks.add(email, name, path)
|
|
|
|
|
|
|
|
|
|
|
|
def read_acks_from_tex_dir(acks, path):
|
|
|
|
stack = [path]
|
|
|
|
while stack:
|
|
|
|
p = stack.pop()
|
|
|
|
for n in os.listdir(p):
|
|
|
|
n = os.path.join(p, n)
|
|
|
|
if os.path.isdir(n):
|
|
|
|
stack.insert(0, n)
|
|
|
|
elif os.path.normpath(n).endswith(".tex"):
|
|
|
|
read_acks_from_tex_file(acks, n)
|
|
|
|
|
|
|
|
|
|
|
|
def extract_tex_group(s):
|
|
|
|
c = 0
|
|
|
|
for i in range(len(s)):
|
|
|
|
if s[i] == '{':
|
|
|
|
c += 1
|
|
|
|
elif s[i] == '}':
|
|
|
|
c -= 1
|
|
|
|
if c == 0:
|
|
|
|
return s[1:i], s[i+1:]
|
|
|
|
|
|
|
|
|
|
|
|
def print_acks(acks):
|
|
|
|
first = 1
|
|
|
|
for email, D in acks.items():
|
|
|
|
if first:
|
|
|
|
first = 0
|
|
|
|
else:
|
|
|
|
print
|
|
|
|
L = D.items()
|
|
|
|
L.sort()
|
|
|
|
prefname = L[0][1]
|
|
|
|
for file, name in L[1:]:
|
|
|
|
if name != prefname:
|
|
|
|
prefname = ""
|
|
|
|
break
|
|
|
|
if prefname:
|
|
|
|
print prefname, "<%s>:" % email
|
|
|
|
else:
|
|
|
|
print email + ":"
|
|
|
|
for file, name in L:
|
|
|
|
if name == prefname:
|
|
|
|
print " " + file
|
|
|
|
else:
|
|
|
|
print " %s (as %s)" % (file, name)
|
|
|
|
|
|
|
|
|
|
|
|
def print_ack_names(acks):
|
|
|
|
names = []
|
|
|
|
for email, D in acks.items():
|
|
|
|
L = D.items()
|
|
|
|
L.sort()
|
|
|
|
prefname = L[0][1]
|
|
|
|
for file, name in L[1:]:
|
|
|
|
prefname = prefname or name
|
|
|
|
names.append(prefname or email)
|
|
|
|
def f(s1, s2):
|
|
|
|
s1 = s1.lower()
|
|
|
|
s2 = s2.lower()
|
|
|
|
return cmp((s1.split()[-1], s1),
|
|
|
|
(s2.split()[-1], s2))
|
|
|
|
names.sort(f)
|
|
|
|
for name in names:
|
|
|
|
print name
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
args = sys.argv[1:]
|
|
|
|
acks = Acknowledgements()
|
|
|
|
load_cvs_log_acks(acks, args)
|
|
|
|
load_tex_source_acks(acks, args)
|
|
|
|
print_ack_names(acks)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|