2 # Stuff for dealing with configuration files.
5 # This code is part of the LWN git data miner.
7 # Copyright 2007-11 Eklektix, Inc.
8 # Copyright 2007-11 Jonathan Corbet <corbet@lwn.net>
10 # This file may be distributed under the terms of the GNU General
11 # Public License, version 2.
13 import sys
, re
, datetime
, os
.path
14 import database
, sre_constants
17 # Read a line and strip out junk.
19 def ReadConfigLine(file):
20 line
= file.readline()
23 line
= line
.split('#')[0] # Get rid of any comments
24 line
= line
.strip() # and extra white space
25 if len(line
) == 0: # we got rid of everything
26 return ReadConfigLine(file)
33 sys
.stderr
.write(message
+ '\n')
37 # Read a list of email aliases.
39 def ReadEmailAliases(name
):
41 file = open(name
, 'r')
43 croak('Unable to open email alias file %s' % (name
))
44 line
= ReadConfigLine(file)
46 m
= re
.match(r
'^("[^"]+"|\S+)\s+(.+)$', line
)
47 if not m
or len(m
.groups()) != 2:
48 croak('Funky email alias line "%s"' % (line
))
49 if m
and m
.group(2).find('@') <= 0:
50 croak('Non-addresses in email alias "%s"' % (line
))
51 database
.AddEmailAlias(m
.group(1).replace('"', ''), m
.group(2))
52 line
= ReadConfigLine(file)
55 def ReadRegexpEmailAliases(name
):
57 file = open(name
, 'r')
59 croak('Unable to open regex email alias file %s' % (name
))
60 line
= ReadConfigLine(file)
62 m
= re
.match(r
'^("[^"]+"|\S+)\s+(.+)$', line
)
63 if not m
or len(m
.groups()) != 2:
64 croak('Funky email alias line "%s"' % (line
))
65 if m
and m
.group(2).find('@') <= 0:
66 croak('Non-addresses in email alias "%s"' % (line
))
68 regex
= re
.compile(m
.group(1).replace('"', ''))
69 except sre_constants
.error
:
70 croak('Screwy regex: %s' % (m
.group(1)))
71 database
.AddRXEmailAlias(regex
, m
.group(2))
72 line
= ReadConfigLine(file)
77 # The Email/Employer map
79 EMMpat
= re
.compile(r
'^([^\s]+)\s+([^<]+)\s*(<\s*(\d+-\d+-\d+)\s*)?$')
81 def ReadEmailEmployers(name
):
83 file = open(name
, 'r')
85 croak('Unable to open email/employer file %s' % (name
))
86 line
= ReadConfigLine(file)
88 m
= EMMpat
.match(line
)
90 croak('Funky email/employer line "%s"' % (line
))
92 company
= m
.group(2).strip()
93 enddate
= ParseDate(m
.group(4))
94 database
.AddEmailEmployerMapping(email
, company
, enddate
)
95 line
= ReadConfigLine(file)
101 sdate
= cdate
.split('-')
102 return datetime
.date(int(sdate
[0]), int(sdate
[1]), int(sdate
[2]))
105 def ReadGroupMap(fname
, employer
):
107 file = open(fname
, 'r')
109 croak('Unable to open group map file %s' % (fname
))
110 line
= ReadConfigLine(file)
112 database
.AddEmailEmployerMapping(line
, employer
)
113 line
= ReadConfigLine(file)
117 # Read in a virtual employer description.
119 def ReadVirtual(file, name
):
120 ve
= database
.VirtualEmployer(name
)
121 line
= ReadConfigLine(file)
123 sl
= line
.split(None, 1)
129 # Zap the "%" syntactic sugar if it's there
136 croak('Bad split value "%s" for virtual empl %s' % (first
, name
))
137 if not (0 < percent
<= 100):
138 croak('Bad split value "%s" for virtual empl %s' % (first
, name
))
139 ve
.addsplit(' '.join(sl
[1:]), percent
/100.0)
140 line
= ReadConfigLine(file)
142 # We should never get here
144 croak('Missing "end" line for virtual employer %s' % (name
))
147 # Read file type patterns for more fine graned reports
149 def ReadFileType(filename
):
151 file = open(filename
, 'r')
153 croak('Unable to open file type mapping file %s' % (filename
))
156 regex_order
= re
.compile(r
'^order\s+(.*)$')
157 regex_file_type
= re
.compile(r
'^filetype\s+(\S+)\s+(.+)$')
158 line
= ReadConfigLine(file)
160 o
= regex_order
.match(line
)
162 # Consider only the first definition in the config file
163 elements
= o
.group(1).replace(' ', '')
164 order
= order
or elements
.split(',')
165 line
= ReadConfigLine(file)
168 m
= regex_file_type
.match(line
)
169 if not m
or len(m
.groups()) != 2:
170 croak('Funky file type line "%s"' % (line
))
171 if m
.group(1) not in patterns
:
172 patterns
[m
.group(1)] = []
173 if m
.group(1) not in order
:
174 print('%s not found, appended to the last order' % m
.group(1))
175 order
.append(m
.group(1))
177 patterns
[m
.group(1)].append(re
.compile(m
.group(2), re
.IGNORECASE
))
179 line
= ReadConfigLine(file)
181 return patterns
, order
184 # Read an overall config file.
187 def ConfigFile(name
, confdir
):
189 file = open(name
, 'r')
192 file = open(os
.path
.join(confdir
, name
), 'r')
194 croak('Unable to open config file %s' % (name
))
195 line
= ReadConfigLine(file)
197 sline
= line
.split(None, 2)
199 croak('Funky config line: "%s"' % (line
))
200 if sline
[0] == 'EmailAliases':
201 ReadEmailAliases(os
.path
.join(confdir
, sline
[1]))
202 elif sline
[0] == 'RXEmailAliases':
203 ReadRegexpEmailAliases(os
.path
.join(confdir
, sline
[1]))
204 elif sline
[0] == 'EmailMap':
205 ReadEmailEmployers(os
.path
.join(confdir
, sline
[1]))
206 elif sline
[0] == 'GroupMap':
208 croak('Funky group map line "%s"' % (line
))
209 ReadGroupMap(os
.path
.join(confdir
, sline
[1]), sline
[2])
210 elif sline
[0] == 'VirtualEmployer':
211 ReadVirtual(file, ' '.join(sline
[1:]))
212 elif sline
[0] == 'FileTypeMap':
213 patterns
, order
= ReadFileType(os
.path
.join(confdir
, sline
[1]))
214 database
.FileTypes
= database
.FileType(patterns
, order
)
216 croak('Unrecognized config line: "%s"' % (line
))
217 line
= ReadConfigLine(file)