Updated for 2.1a3
[python/dscho.git] / Doc / tools / findacks
blobb54ea609bda53f83a8726bc325ad0c8f9a90a44b
1 #!/usr/bin/env python
2 """Script to locate email addresses in the CVS logs."""
3 __version__ = '$Revision$'
5 import os
6 import re
7 import sys
8 import UserDict
10 import cvsinfo
13 class Acknowledgements(UserDict.UserDict):
14 def add(self, email, name, path):
15 d = self.data
16 d.setdefault(email, {})[path] = name
19 def open_cvs_log(info, paths=None):
20 cvsroot = info.get_cvsroot()
21 cmd = "cvs -q -d%s log " % cvsroot
22 if paths:
23 cmd += " ".join(paths)
24 return os.popen(cmd, "r")
27 email_rx = re.compile("<([a-z][-a-z0-9._]*@[-a-z0-9.]+)>", re.IGNORECASE)
29 def find_acks(f, acks):
30 prev = ''
31 filename = None
32 MAGIC_WORDS = ('van', 'von')
33 while 1:
34 line = f.readline()
35 if not line:
36 break
37 if line.startswith("Working file: "):
38 filename = line.split(None, 2)[2].strip()
39 prev = line
40 continue
41 m = email_rx.search(line)
42 if m:
43 words = prev.split() + line[:m.start()].split()
44 L = []
45 while words \
46 and (words[-1][0].isupper() or words[-1] in MAGIC_WORDS):
47 L.insert(0, words.pop())
48 name = " ".join(L)
49 email = m.group(1).lower()
50 acks.add(email, name, filename)
51 prev = line
54 def load_cvs_log_acks(acks, args):
55 repolist = cvsinfo.get_repository_list(args or [""])
56 for info, paths in repolist:
57 print >>sys.stderr, "Repository:", info.get_cvsroot()
58 f = open_cvs_log(info, paths)
59 find_acks(f, acks)
60 f.close()
63 def load_tex_source_acks(acks, args):
64 for path in args:
65 path = path or os.curdir
66 if os.path.isfile(path):
67 read_acks_from_tex_file(acks, path)
68 else:
69 read_acks_from_tex_dir(acks, path)
72 def read_acks_from_tex_file(acks, path):
73 f = open(path)
74 while 1:
75 line = f.readline()
76 if not line:
77 break
78 if line.startswith(r"\sectionauthor{"):
79 line = line[len(r"\sectionauthor"):]
80 name, line = extract_tex_group(line)
81 email, line = extract_tex_group(line)
82 acks.add(email, name, path)
85 def read_acks_from_tex_dir(acks, path):
86 stack = [path]
87 while stack:
88 p = stack.pop()
89 for n in os.listdir(p):
90 n = os.path.join(p, n)
91 if os.path.isdir(n):
92 stack.insert(0, n)
93 elif os.path.normpath(n).endswith(".tex"):
94 read_acks_from_tex_file(acks, n)
97 def extract_tex_group(s):
98 c = 0
99 for i in range(len(s)):
100 if s[i] == '{':
101 c += 1
102 elif s[i] == '}':
103 c -= 1
104 if c == 0:
105 return s[1:i], s[i+1:]
108 def print_acks(acks):
109 first = 1
110 for email, D in acks.items():
111 if first:
112 first = 0
113 else:
114 print
115 L = D.items()
116 L.sort()
117 prefname = L[0][1]
118 for file, name in L[1:]:
119 if name != prefname:
120 prefname = ""
121 break
122 if prefname:
123 print prefname, "<%s>:" % email
124 else:
125 print email + ":"
126 for file, name in L:
127 if name == prefname:
128 print " " + file
129 else:
130 print " %s (as %s)" % (file, name)
133 def print_ack_names(acks):
134 names = []
135 for email, D in acks.items():
136 L = D.items()
137 L.sort()
138 prefname = L[0][1]
139 for file, name in L[1:]:
140 prefname = prefname or name
141 names.append(prefname or email)
142 def f(s1, s2):
143 s1 = s1.lower()
144 s2 = s2.lower()
145 return cmp((s1.split()[-1], s1),
146 (s2.split()[-1], s2))
147 names.sort(f)
148 for name in names:
149 print name
152 def main():
153 args = sys.argv[1:]
154 acks = Acknowledgements()
155 load_cvs_log_acks(acks, args)
156 load_tex_source_acks(acks, args)
157 print_ack_names(acks)
160 if __name__ == "__main__":
161 main()