Preliminary tool to troll through the CVS logs and LaTeX sources for
the names of people that should be in the ACKS file. This relies on some personal code that is not yet available, but should be by the time we release 2.0c1.
This commit is contained in:
parent
5b4c22806f
commit
1654b43ef7
|
@ -0,0 +1,162 @@
|
|||
#!/usr/bin/env python
|
||||
"""Script to locate email addresses in the CVS logs."""
|
||||
__version__ = '$Revision$'
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import UserDict
|
||||
|
||||
import fdrake.cvstools.info
|
||||
cvstools = fdrake.cvstools
|
||||
|
||||
|
||||
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):
|
||||
repolist = cvstools.info.get_repository_list(args or [""])
|
||||
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()
|
Loading…
Reference in New Issue