Hacky stuff for 4.0
[git-dm.git] / ConfigFile.py
blob3a1e208cd6f6b319901755f151d836be1c5274e5
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
17 # Read a line and strip out junk.
19 def ReadConfigLine (file):
20 line = file.readline ()
21 if not line:
22 return None
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)
27 return line
30 # Give up and die.
32 def croak (message):
33 sys.stderr.write (message + '\n')
34 sys.exit (1)
37 # Read a list of email aliases.
39 def ReadEmailAliases (name):
40 try:
41 file = open (name, 'r')
42 except IOError:
43 croak ('Unable to open email alias file %s' % (name))
44 line = ReadConfigLine (file)
45 while line:
46 m = re.match ('^("[^"]+"|\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)
53 file.close ()
56 # The Email/Employer map
58 EMMpat = re.compile (r'^([^\s]+)\s+([^<]+)\s*(<\s*(\d+-\d+-\d+)\s*)?$')
60 def ReadEmailEmployers (name):
61 try:
62 file = open (name, 'r')
63 except IOError:
64 croak ('Unable to open email/employer file %s' % (name))
65 line = ReadConfigLine (file)
66 while line:
67 m = EMMpat.match (line)
68 if not m:
69 croak ('Funky email/employer line "%s"' % (line))
70 email = m.group (1)
71 company = m.group (2).strip ()
72 enddate = ParseDate (m.group (4))
73 database.AddEmailEmployerMapping (email, company, enddate)
74 line = ReadConfigLine (file)
75 file.close ()
77 def ParseDate (cdate):
78 if not cdate:
79 return None
80 sdate = cdate.split ('-')
81 return datetime.date (int (sdate[0]), int (sdate[1]), int (sdate[2]))
84 def ReadGroupMap (fname, employer):
85 try:
86 file = open (fname, 'r')
87 except IOError:
88 croak ('Unable to open group map file %s' % (fname))
89 line = ReadConfigLine (file)
90 while line:
91 database.AddEmailEmployerMapping (line, employer)
92 line = ReadConfigLine (file)
93 file.close ()
96 # Read in a virtual employer description.
98 def ReadVirtual (file, name):
99 ve = database.VirtualEmployer (name)
100 line = ReadConfigLine (file)
101 while line:
102 sl = line.split (None, 1)
103 first = sl[0]
104 if first == 'end':
105 ve.store ()
106 return
108 # Zap the "%" syntactic sugar if it's there
110 if first[-1] == '%':
111 first = first[:-1]
112 try:
113 percent = int (first)
114 except ValueError:
115 croak ('Bad split value "%s" for virtual empl %s' % (first, name))
116 if not (0 < percent <= 100):
117 croak ('Bad split value "%s" for virtual empl %s' % (first, name))
118 ve.addsplit (' '.join (sl[1:]), percent/100.0)
119 line = ReadConfigLine (file)
121 # We should never get here
123 croak ('Missing "end" line for virtual employer %s' % (name))
126 # Read file type patterns for more fine graned reports
128 def ReadFileType (filename):
129 try:
130 file = open (filename, 'r')
131 except IOError:
132 croak ('Unable to open file type mapping file %s' % (filename))
133 patterns = {}
134 order = []
135 regex_order = re.compile ('^order\s+(.*)$')
136 regex_file_type = re.compile ('^filetype\s+(\S+)\s+(.+)$')
137 line = ReadConfigLine (file)
138 while line:
139 o = regex_order.match (line)
140 if o:
141 # Consider only the first definition in the config file
142 elements = o.group(1).replace (' ', '')
143 order = order or elements.split(',')
144 line = ReadConfigLine (file)
145 continue
147 m = regex_file_type.match (line)
148 if not m or len (m.groups ()) != 2:
149 ConfigFile.croak ('Funky file type line "%s"' % (line))
150 if not patterns.has_key (m.group (1)):
151 patterns[m.group (1)] = []
152 if m.group (1) not in order:
153 print '%s not found, appended to the last order' % m.group (1)
154 order.append (m.group (1))
156 patterns[m.group (1)].append (re.compile (m.group (2), re.IGNORECASE))
158 line = ReadConfigLine (file)
159 file.close ()
160 return patterns, order
163 # Read an overall config file.
166 def ConfigFile (name, confdir):
167 try:
168 file = open (name, 'r')
169 except IOError:
170 try:
171 file = open (os.path.join (confdir, name), 'r')
172 except IOError:
173 croak ('Unable to open config file %s' % (name))
174 line = ReadConfigLine (file)
175 while line:
176 sline = line.split (None, 2)
177 if len (sline) < 2:
178 croak ('Funky config line: "%s"' % (line))
179 if sline[0] == 'EmailAliases':
180 ReadEmailAliases (os.path.join (confdir, sline[1]))
181 elif sline[0] == 'EmailMap':
182 ReadEmailEmployers (os.path.join (confdir, sline[1]))
183 elif sline[0] == 'GroupMap':
184 if len (sline) != 3:
185 croak ('Funky group map line "%s"' % (line))
186 ReadGroupMap (os.path.join (confdir, sline[1]), sline[2])
187 elif sline[0] == 'VirtualEmployer':
188 ReadVirtual (file, ' '.join (sline[1:]))
189 elif sline[0] == 'FileTypeMap':
190 patterns, order = ReadFileType (os.path.join (confdir, sline[1]))
191 database.FileTypes = database.FileType (patterns, order)
192 else:
193 croak ('Unrecognized config line: "%s"' % (line))
194 line = ReadConfigLine (file)