]> Git Repo - u-boot.git/blame - tools/patman/settings.py
Merge tag 'video-for-2020.01-rc1' of https://gitlab.denx.de/u-boot/custodians/u-boot...
[u-boot.git] / tools / patman / settings.py
CommitLineData
83d290c5 1# SPDX-License-Identifier: GPL-2.0+
0d24de9d
SG
2# Copyright (c) 2011 The Chromium OS Authors.
3#
0d24de9d 4
a920a17b
PB
5from __future__ import print_function
6
2ce7b21e
PB
7try:
8 import configparser as ConfigParser
9except:
10 import ConfigParser
11
0d24de9d
SG
12import os
13import re
14
15import command
87d65558 16import gitutil
513eace4 17import tools
0d24de9d 18
a1dcee84
DA
19"""Default settings per-project.
20
21These are used by _ProjectConfigParser. Settings names should match
22the "dest" of the option parser from patman.py.
23"""
24_default_settings = {
25 "u-boot": {},
26 "linux": {
27 "process_tags": "False",
28 }
29}
30
31class _ProjectConfigParser(ConfigParser.SafeConfigParser):
32 """ConfigParser that handles projects.
33
34 There are two main goals of this class:
35 - Load project-specific default settings.
36 - Merge general default settings/aliases with project-specific ones.
37
38 # Sample config used for tests below...
f5d44b9b
PB
39 >>> try:
40 ... from StringIO import StringIO
41 ... except ImportError:
42 ... from io import StringIO
a1dcee84
DA
43 >>> sample_config = '''
44 ... [alias]
45 ... me: Peter P. <[email protected]>
46 ... enemies: Evil <[email protected]>
47 ...
48 ... [sm_alias]
49 ... enemies: Green G. <[email protected]>
50 ...
51 ... [sm2_alias]
52 ... enemies: Doc O. <[email protected]>
53 ...
54 ... [settings]
55 ... am_hero: True
56 ... '''
57
58 # Check to make sure that bogus project gets general alias.
59 >>> config = _ProjectConfigParser("zzz")
f5d44b9b 60 >>> config.readfp(StringIO(sample_config))
7ebb45c7
SG
61 >>> str(config.get("alias", "enemies"))
62 'Evil <[email protected]>'
a1dcee84
DA
63
64 # Check to make sure that alias gets overridden by project.
65 >>> config = _ProjectConfigParser("sm")
f5d44b9b 66 >>> config.readfp(StringIO(sample_config))
7ebb45c7
SG
67 >>> str(config.get("alias", "enemies"))
68 'Green G. <[email protected]>'
a1dcee84
DA
69
70 # Check to make sure that settings get merged with project.
71 >>> config = _ProjectConfigParser("linux")
f5d44b9b 72 >>> config.readfp(StringIO(sample_config))
7ebb45c7
SG
73 >>> sorted((str(a), str(b)) for (a, b) in config.items("settings"))
74 [('am_hero', 'True'), ('process_tags', 'False')]
a1dcee84
DA
75
76 # Check to make sure that settings works with unknown project.
77 >>> config = _ProjectConfigParser("unknown")
f5d44b9b 78 >>> config.readfp(StringIO(sample_config))
7ebb45c7
SG
79 >>> sorted((str(a), str(b)) for (a, b) in config.items("settings"))
80 [('am_hero', 'True')]
a1dcee84
DA
81 """
82 def __init__(self, project_name):
83 """Construct _ProjectConfigParser.
84
85 In addition to standard SafeConfigParser initialization, this also loads
86 project defaults.
87
88 Args:
89 project_name: The name of the project.
90 """
91 self._project_name = project_name
92 ConfigParser.SafeConfigParser.__init__(self)
93
94 # Update the project settings in the config based on
95 # the _default_settings global.
96 project_settings = "%s_settings" % project_name
97 if not self.has_section(project_settings):
98 self.add_section(project_settings)
99 project_defaults = _default_settings.get(project_name, {})
c9eac38a 100 for setting_name, setting_value in project_defaults.items():
a1dcee84
DA
101 self.set(project_settings, setting_name, setting_value)
102
103 def get(self, section, option, *args, **kwargs):
104 """Extend SafeConfigParser to try project_section before section.
105
106 Args:
107 See SafeConfigParser.
108 Returns:
109 See SafeConfigParser.
110 """
111 try:
ec9e0f47 112 val = ConfigParser.SafeConfigParser.get(
a1dcee84
DA
113 self, "%s_%s" % (self._project_name, section), option,
114 *args, **kwargs
115 )
116 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
ec9e0f47 117 val = ConfigParser.SafeConfigParser.get(
a1dcee84
DA
118 self, section, option, *args, **kwargs
119 )
513eace4 120 return tools.ToUnicode(val)
a1dcee84
DA
121
122 def items(self, section, *args, **kwargs):
123 """Extend SafeConfigParser to add project_section to section.
124
125 Args:
126 See SafeConfigParser.
127 Returns:
128 See SafeConfigParser.
129 """
130 project_items = []
131 has_project_section = False
132 top_items = []
133
134 # Get items from the project section
135 try:
136 project_items = ConfigParser.SafeConfigParser.items(
137 self, "%s_%s" % (self._project_name, section), *args, **kwargs
138 )
139 has_project_section = True
140 except ConfigParser.NoSectionError:
141 pass
142
143 # Get top-level items
144 try:
145 top_items = ConfigParser.SafeConfigParser.items(
146 self, section, *args, **kwargs
147 )
148 except ConfigParser.NoSectionError:
149 # If neither section exists raise the error on...
150 if not has_project_section:
151 raise
152
153 item_dict = dict(top_items)
154 item_dict.update(project_items)
513eace4 155 return {(tools.ToUnicode(item), tools.ToUnicode(val))
4a4c5dd4 156 for item, val in item_dict.items()}
a1dcee84 157
0d24de9d
SG
158def ReadGitAliases(fname):
159 """Read a git alias file. This is in the form used by git:
160
161 alias uboot [email protected]
162 alias wd Wolfgang Denk <[email protected]>
163
164 Args:
165 fname: Filename to read
166 """
167 try:
168 fd = open(fname, 'r')
169 except IOError:
a920a17b 170 print("Warning: Cannot find alias file '%s'" % fname)
0d24de9d
SG
171 return
172
173 re_line = re.compile('alias\s+(\S+)\s+(.*)')
174 for line in fd.readlines():
175 line = line.strip()
176 if not line or line[0] == '#':
177 continue
178
179 m = re_line.match(line)
180 if not m:
a920a17b 181 print("Warning: Alias file line '%s' not understood" % line)
0d24de9d
SG
182 continue
183
184 list = alias.get(m.group(1), [])
185 for item in m.group(2).split(','):
186 item = item.strip()
187 if item:
188 list.append(item)
189 alias[m.group(1)] = list
190
191 fd.close()
192
87d65558
VN
193def CreatePatmanConfigFile(config_fname):
194 """Creates a config file under $(HOME)/.patman if it can't find one.
195
196 Args:
197 config_fname: Default config filename i.e., $(HOME)/.patman
198
199 Returns:
200 None
201 """
202 name = gitutil.GetDefaultUserName()
203 if name == None:
204 name = raw_input("Enter name: ")
205
206 email = gitutil.GetDefaultUserEmail()
207
208 if email == None:
209 email = raw_input("Enter email: ")
210
211 try:
212 f = open(config_fname, 'w')
213 except IOError:
a920a17b 214 print("Couldn't create patman config file\n")
87d65558
VN
215 raise
216
ad893140
SG
217 print('''[alias]
218me: %s <%s>
219
220[bounces]
221nxp = Zhikang Zhang <[email protected]>
222''' % (name, email), file=f)
87d65558
VN
223 f.close();
224
8568baed
DA
225def _UpdateDefaults(parser, config):
226 """Update the given OptionParser defaults based on config.
227
228 We'll walk through all of the settings from the parser
229 For each setting we'll look for a default in the option parser.
230 If it's found we'll update the option parser default.
231
232 The idea here is that the .patman file should be able to update
233 defaults but that command line flags should still have the final
234 say.
235
236 Args:
237 parser: An instance of an OptionParser whose defaults will be
238 updated.
a1dcee84 239 config: An instance of _ProjectConfigParser that we will query
8568baed
DA
240 for settings.
241 """
242 defaults = parser.get_default_values()
243 for name, val in config.items('settings'):
244 if hasattr(defaults, name):
245 default_val = getattr(defaults, name)
246 if isinstance(default_val, bool):
247 val = config.getboolean('settings', name)
248 elif isinstance(default_val, int):
249 val = config.getint('settings', name)
250 parser.set_default(name, val)
251 else:
a920a17b 252 print("WARNING: Unknown setting %s" % name)
8568baed 253
8895b3e1
SG
254def _ReadAliasFile(fname):
255 """Read in the U-Boot git alias file if it exists.
256
257 Args:
258 fname: Filename to read.
259 """
260 if os.path.exists(fname):
261 bad_line = None
262 with open(fname) as fd:
263 linenum = 0
264 for line in fd:
265 linenum += 1
266 line = line.strip()
267 if not line or line.startswith('#'):
268 continue
b8a48fbc 269 words = line.split(None, 2)
8895b3e1
SG
270 if len(words) < 3 or words[0] != 'alias':
271 if not bad_line:
272 bad_line = "%s:%d:Invalid line '%s'" % (fname, linenum,
273 line)
274 continue
275 alias[words[1]] = [s.strip() for s in words[2].split(',')]
276 if bad_line:
a920a17b 277 print(bad_line)
8895b3e1 278
e11aa602
CP
279def _ReadBouncesFile(fname):
280 """Read in the bounces file if it exists
281
282 Args:
283 fname: Filename to read.
284 """
285 if os.path.exists(fname):
286 with open(fname) as fd:
287 for line in fd:
288 if line.startswith('#'):
289 continue
290 bounces.add(line.strip())
291
ad893140
SG
292def GetItems(config, section):
293 """Get the items from a section of the config.
294
295 Args:
296 config: _ProjectConfigParser object containing settings
297 section: name of section to retrieve
298
299 Returns:
300 List of (name, value) tuples for the section
301 """
302 try:
303 return config.items(section)
304 except ConfigParser.NoSectionError as e:
305 return []
306 except:
307 raise
308
a1dcee84 309def Setup(parser, project_name, config_fname=''):
0d24de9d
SG
310 """Set up the settings module by reading config files.
311
312 Args:
8568baed 313 parser: The parser to update
a1dcee84
DA
314 project_name: Name of project that we're working on; we'll look
315 for sections named "project_section" as well.
0d24de9d
SG
316 config_fname: Config filename to read ('' for default)
317 """
8895b3e1
SG
318 # First read the git alias file if available
319 _ReadAliasFile('doc/git-mailrc')
a1dcee84 320 config = _ProjectConfigParser(project_name)
0d24de9d 321 if config_fname == '':
2b36c75d 322 config_fname = '%s/.patman' % os.getenv('HOME')
87d65558
VN
323
324 if not os.path.exists(config_fname):
a920a17b 325 print("No config file found ~/.patman\nCreating one...\n")
87d65558
VN
326 CreatePatmanConfigFile(config_fname)
327
8568baed 328 config.read(config_fname)
0d24de9d 329
ad893140 330 for name, value in GetItems(config, 'alias'):
0d24de9d
SG
331 alias[name] = value.split(',')
332
e11aa602 333 _ReadBouncesFile('doc/bounces')
ad893140 334 for name, value in GetItems(config, 'bounces'):
e11aa602
CP
335 bounces.add(value)
336
8568baed 337 _UpdateDefaults(parser, config)
0d24de9d
SG
338
339# These are the aliases we understand, indexed by alias. Each member is a list.
340alias = {}
e11aa602 341bounces = set()
a1dcee84
DA
342
343if __name__ == "__main__":
344 import doctest
345
346 doctest.testmod()
This page took 0.295788 seconds and 4 git commands to generate.