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):
141
input = self._get_filename()
144
if self._parser is None:
146
self._parser = ConfigObj(input)
147
except ConfigObjError, e:
148
raise errors.ParseConfigError(e.errors, e.config.filename)
151
def _get_section(self):
152
"""Override this to define the section used by the config."""
155
def _config_val(self, name, section=None):
157
section = self._get_section()
160
# Throw KeyError if name or section not present
161
if section == "DEFAULT":
163
return self._get_parser()[name]
166
return self._get_parser()[section][name]
168
def _config_bool(self, name, section=None):
169
val = self._config_val(name, section).lower()
170
if val in ('1', 'yes', 'true', 'on'):
172
elif val in ('0', 'no', 'false', 'off'):
175
raise ValueError("Value %r is not boolean" % val)
179
def _get_signature_checking(self):
180
"""See Config._get_signature_checking."""
182
policy = self._config_val('check_signatures')
185
return self._string_to_signature_policy(policy)
187
def _get_user_id(self):
188
"""Get the user id from the 'email' key in the current section."""
190
return self._config_val('email')
194
def __init__(self, get_filename):
195
super(IniBasedConfig, self).__init__()
196
self._get_filename = get_filename
199
def _string_to_signature_policy(self, signature_string):
200
"""Convert a string to a signing policy."""
201
if signature_string.lower() == 'check-available':
202
return CHECK_IF_POSSIBLE
203
if signature_string.lower() == 'ignore':
205
if signature_string.lower() == 'require':
207
raise errors.BzrError("Invalid signatures policy '%s'"
211
class GlobalConfig(IniBasedConfig):
212
"""The configuration that should be used for a specific location."""
214
def get_editor(self):
216
return self._config_val('editor')
221
super(GlobalConfig, self).__init__(config_filename)
224
class LocationConfig(IniBasedConfig):
225
"""A configuration object that gives the policy for a location."""
227
def __init__(self, location):
228
super(LocationConfig, self).__init__(branches_config_filename)
229
self._global_config = None
230
self.location = location
232
def _get_global_config(self):
233
if self._global_config is None:
234
self._global_config = GlobalConfig()
235
return self._global_config
237
def _get_section(self):
238
"""Get the section we should look in for config items.
240
Returns None if none exists.
241
TODO: perhaps return a NullSection that thunks through to the
244
sections = self._get_parser()
245
location_names = self.location.split('/')
246
if self.location.endswith('/'):
247
del location_names[-1]
249
for section in sections:
250
section_names = section.split('/')
251
if section.endswith('/'):
252
del section_names[-1]
253
names = zip(location_names, section_names)
256
if not fnmatch(name[0], name[1]):
261
# so, for the common prefix they matched.
262
# if section is longer, no match.
263
if len(section_names) > len(location_names):
265
# if path is longer, and recurse is not true, no match
266
if len(section_names) < len(location_names):
268
if not self._config_bool('recurse', section=section):
272
matches.append((len(section_names), section))
275
matches.sort(reverse=True)
278
def _get_user_id(self):
279
user_id = super(LocationConfig, self)._get_user_id()
280
if user_id is not None:
282
return self._get_global_config()._get_user_id()
284
def _get_signature_checking(self):
285
"""See Config._get_signature_checking."""
286
check = super(LocationConfig, self)._get_signature_checking()
287
if check is not None:
289
return self._get_global_config()._get_signature_checking()
292
class BranchConfig(Config):
293
"""A configuration object giving the policy for a branch."""
295
def _get_location_config(self):
296
if self._location_config is None:
297
self._location_config = LocationConfig(self.branch.base)
298
return self._location_config
300
def _get_user_id(self):
301
"""Return the full user id for the branch.
303
e.g. "John Hacker <jhacker@foo.org>"
304
This is looked up in the email controlfile for the branch.
307
return (self.branch.controlfile("email", "r")
309
.decode(bzrlib.user_encoding)
311
except errors.NoSuchFile, e:
314
return self._get_location_config()._get_user_id()
316
def _get_signature_checking(self):
317
"""See Config._get_signature_checking."""
318
return self._get_location_config()._get_signature_checking()
320
def __init__(self, branch):
321
super(BranchConfig, self).__init__()
322
self._location_config = None
327
"""Return per-user configuration directory.
329
By default this is ~/.bazaar/
331
TODO: Global option --config-dir to override this.
333
return os.path.join(os.path.expanduser("~"), ".bazaar")
336
def config_filename():
337
"""Return per-user configuration ini file filename."""
338
return os.path.join(config_dir(), 'bazaar.conf')
341
def branches_config_filename():
342
"""Return per-user configuration ini file filename."""
343
return os.path.join(config_dir(), 'branches.conf')
347
"""Calculate automatic user identification.
349
Returns (realname, email).
351
Only used when none is set in the environment or the id file.
353
This previously used the FQDN as the default domain, but that can
354
be very slow on machines where DNS is broken. So now we simply
359
# XXX: Any good way to get real user name on win32?
364
w = pwd.getpwuid(uid)
365
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
366
username = w.pw_name.decode(bzrlib.user_encoding)
367
comma = gecos.find(',')
371
realname = gecos[:comma]
377
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
379
return realname, (username + '@' + socket.gethostname())
382
def extract_email_address(e):
383
"""Return just the address part of an email string.
385
That is just the user@domain part, nothing else.
386
This part is required to contain only ascii characters.
387
If it can't be extracted, raises an error.
389
>>> extract_email_address('Jane Tester <jane@test.com>')
392
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
394
raise BzrError("%r doesn't seem to contain "
395
"a reasonable email address" % e)