diff options
Diffstat (limited to 'Doc/tools')
-rwxr-xr-x | Doc/tools/findacks | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/Doc/tools/findacks b/Doc/tools/findacks new file mode 100755 index 0000000..d35859b --- /dev/null +++ b/Doc/tools/findacks @@ -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() |