1
# Copyright (C) 2005 by Canonical Ltd
2
# Authors: Robert Collins <robert.collins@canonical.com>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""Configuration that affects the behaviour of Bazaar.
20
Currently this configuration resides in ~/.bazaar/bazaar.conf
21
and ~/.bazaar/branches.conf, which is written to by bzr.
23
In bazaar.config the following options may be set:
25
editor=name-of-program
26
email=Your Name <your@email.address>
27
check_signatures=require|ignore|check-available(default)
28
create_signatures=always|never|when-required(default)
30
in branches.conf, you specify the url of a branch and options for it.
31
Wildcards may be used - * and ? as normal in shell completion. Options
32
set in both bazaar.conf and branches.conf are overriden by the branches.conf
34
[/home/robertc/source]
35
recurse=False|True(default)
37
check_signatures= as abive
38
create_signatures= as above.
40
explanation of options
41
----------------------
42
editor - this option sets the pop up editor to use during commits.
43
email - this option sets the user id bzr will use when committing.
44
check_signatures - this option controls whether bzr will require good gpg
45
signatures, ignore them, or check them if they are
47
create_signatures - this option controls whether bzr will always create
48
gpg signatures, never create them, or create them if the
49
branch is configured to require them.
50
NB: This option is planned, but not implemented yet.
53
from util.configobj.configobj import ConfigObj, ConfigObjError
55
from fnmatch import fnmatch
60
import bzrlib.errors as errors
69
"""A configuration policy - what username, editor, gpg needs etc."""
72
"""Get the users pop up editor."""
73
raise NotImplementedError
75
def _get_signature_checking(self):
76
"""Template method to override signature checking policy."""
79
super(Config, self).__init__()
82
"""Return just the email component of a username."""
84
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
86
raise BzrError("%r doesn't seem to contain "
87
"a reasonable email address" % e)
91
"""Return email-style username.
93
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
95
$BZREMAIL can be set to override this, then
96
the concrete policy type is checked, and finally
98
but if none is found, a reasonable default is (hopefully)
101
TODO: Check it's reasonably well-formed.
103
v = os.environ.get('BZREMAIL')
105
return v.decode(bzrlib.user_encoding)
107
v = self._get_user_id()
111
v = os.environ.get('EMAIL')
113
return v.decode(bzrlib.user_encoding)
115
name, email = _auto_user_id()
117
return '%s <%s>' % (name, email)
121
def signature_checking(self):
122
"""What is the current policy for signature checking?."""
123
policy = self._get_signature_checking()
124
if policy is not None:
126
return CHECK_IF_POSSIBLE
128
def signature_needed(self):
129
"""Is a signature needed when committing ?."""
130
policy = self._get_signature_checking()
131
if policy == CHECK_ALWAYS:
136
class IniBasedConfig(Config):
137
"""A configuration policy that draws from ini files."""
139
def _get_parser(self, file=None):
140
if self._parser is not None:
143
input = self._get_filename()
147
self._parser = ConfigObj(input)
148
except ConfigObjError, e:
149
raise errors.ParseConfigError(e.errors, e.config.filename)
152
def _get_section(self):
153
"""Override this to define the section used by the config."""
156
def _config_val(self, name, section=None):
158
section = self._get_section()
161
# Throw KeyError if name or section not present
162
if section == "DEFAULT":
164
return self._get_parser()[name]
167
return self._get_parser()[section][name]
169
def _config_bool(self, name, section=None):
170
val = self._config_val(name, section).lower()
171
if val in ('1', 'yes', 'true', 'on'):
173
elif val in ('0', 'no', 'false', 'off'):
176
raise ValueError("Value %r is not boolean" % val)
180
def _get_signature_checking(self):
181
"""See Config._get_signature_checking."""
183
policy = self._config_val('check_signatures')
186
return self._string_to_signature_policy(policy)
188
def _get_user_id(self):
189
"""Get the user id from the 'email' key in the current section."""
191
return self._config_val('email')
195
def __init__(self, get_filename):
196
super(IniBasedConfig, self).__init__()
197
self._get_filename = get_filename
200
def _string_to_signature_policy(self, signature_string):
201
"""Convert a string to a signing policy."""
202
if signature_string.lower() == 'check-available':
203
return CHECK_IF_POSSIBLE
204
if signature_string.lower() == 'ignore':
206
if signature_string.lower() == 'require':
208
raise errors.BzrError("Invalid signatures policy '%s'"
212
class GlobalConfig(IniBasedConfig):
213
"""The configuration that should be used for a specific location."""
215
def get_editor(self):
217
return self._config_val('editor')
222
super(GlobalConfig, self).__init__(config_filename)
225
class LocationConfig(IniBasedConfig):
226
"""A configuration object that gives the policy for a location."""
228
def __init__(self, location):
229
super(LocationConfig, self).__init__(branches_config_filename)
230
self._global_config = None
231
self.location = location
233
def _get_global_config(self):
234
if self._global_config is None:
235
self._global_config = GlobalConfig()
236
return self._global_config
238
def _get_section(self):
239
"""Get the section we should look in for config items.
241
Returns None if none exists.
242
TODO: perhaps return a NullSection that thunks through to the
245
sections = self._get_parser()
246
location_names = self.location.split('/')
247
if self.location.endswith('/'):
248
del location_names[-1]
250
for section in sections:
251
section_names = section.split('/')
252
if section.endswith('/'):
253
del section_names[-1]
254
names = zip(location_names, section_names)
257
if not fnmatch(name[0], name[1]):
262
# so, for the common prefix they matched.
263
# if section is longer, no match.
264
if len(section_names) > len(location_names):
266
# if path is longer, and recurse is not true, no match
267
if len(section_names) < len(location_names):
269
if not self._config_bool('recurse', section=section):
273
matches.append((len(section_names), section))
276
matches.sort(reverse=True)
279
def _get_user_id(self):
280
user_id = super(LocationConfig, self)._get_user_id()
281
if user_id is not None:
283
return self._get_global_config()._get_user_id()
285
def _get_signature_checking(self):
286
"""See Config._get_signature_checking."""
287
check = super(LocationConfig, self)._get_signature_checking()
288
if check is not None:
290
return self._get_global_config()._get_signature_checking()
293
class BranchConfig(Config):
294
"""A configuration object giving the policy for a branch."""
296
def _get_location_config(self):
297
if self._location_config is None:
298
self._location_config = LocationConfig(self.branch.base)
299
return self._location_config
301
def _get_user_id(self):
302
"""Return the full user id for the branch.
304
e.g. "John Hacker <jhacker@foo.org>"
305
This is looked up in the email controlfile for the branch.
308
return (self.branch.controlfile("email", "r")
310
.decode(bzrlib.user_encoding)
312
except errors.NoSuchFile, e:
315
return self._get_location_config()._get_user_id()
317
def _get_signature_checking(self):
318
"""See Config._get_signature_checking."""
319
return self._get_location_config()._get_signature_checking()
321
def __init__(self, branch):
322
super(BranchConfig, self).__init__()
323
self._location_config = None
328
"""Return per-user configuration directory.
330
By default this is ~/.bazaar/
332
TODO: Global option --config-dir to override this.
334
return os.path.join(os.path.expanduser("~"), ".bazaar")
337
def config_filename():
338
"""Return per-user configuration ini file filename."""
339
return os.path.join(config_dir(), 'bazaar.conf')
342
def branches_config_filename():
343
"""Return per-user configuration ini file filename."""
344
return os.path.join(config_dir(), 'branches.conf')
348
"""Calculate automatic user identification.
350
Returns (realname, email).
352
Only used when none is set in the environment or the id file.
354
This previously used the FQDN as the default domain, but that can
355
be very slow on machines where DNS is broken. So now we simply
360
# XXX: Any good way to get real user name on win32?
365
w = pwd.getpwuid(uid)
366
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
367
username = w.pw_name.decode(bzrlib.user_encoding)
368
comma = gecos.find(',')
372
realname = gecos[:comma]
378
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
380
return realname, (username + '@' + socket.gethostname())
383
def extract_email_address(e):
384
"""Return just the address part of an email string.
386
That is just the user@domain part, nothing else.
387
This part is required to contain only ascii characters.
388
If it can't be extracted, raises an error.
390
>>> extract_email_address('Jane Tester <jane@test.com>')
393
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
395
raise BzrError("%r doesn't seem to contain "
396
"a reasonable email address" % e)