20
20
Currently this configuration resides in ~/.bazaar/bazaar.conf
21
21
and ~/.bazaar/branches.conf, which is written to by bzr.
23
In bazaar.conf the following options may be set:
23
In bazaar.config the following options may be set:
25
25
editor=name-of-program
26
26
email=Your Name <your@email.address>
51
51
NB: This option is planned, but not implemented yet.
54
from ConfigParser import ConfigParser
58
56
from fnmatch import fnmatch
62
61
import bzrlib.errors as errors
63
import bzrlib.util.configobj.configobj as configobj
64
from StringIO import StringIO
66
64
CHECK_IF_POSSIBLE=0
71
class ConfigObj(configobj.ConfigObj):
73
def get_bool(self, section, key):
74
val = self[section][key].lower()
75
if val in ('1', 'yes', 'true', 'on'):
77
elif val in ('0', 'no', 'false', 'off'):
80
raise ValueError("Value %r is not boolean" % val)
82
def get_value(self, section, name):
83
# Try [] for the old DEFAULT section.
84
if section == "DEFAULT":
89
return self[section][name]
92
69
class Config(object):
93
70
"""A configuration policy - what username, editor, gpg needs etc."""
99
76
def _get_signature_checking(self):
100
77
"""Template method to override signature checking policy."""
102
def _get_user_option(self, option_name):
103
"""Template method to provide a user option."""
106
def get_user_option(self, option_name):
107
"""Get a generic option - no special process, no default."""
108
return self._get_user_option(option_name)
110
79
def gpg_signing_command(self):
111
80
"""What program should be used to sign signatures?"""
112
81
result = self._gpg_signing_command()
121
90
def __init__(self):
122
91
super(Config, self).__init__()
124
def post_commit(self):
125
"""An ordered list of python functions to call.
127
Each function takes branch, rev_id as parameters.
129
return self._post_commit()
131
def _post_commit(self):
132
"""See Config.post_commit."""
135
93
def user_email(self):
136
94
"""Return just the email component of a username."""
137
return extract_email_address(self.username())
96
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
98
raise BzrError("%r doesn't seem to contain "
99
"a reasonable email address" % e)
139
102
def username(self):
140
103
"""Return email-style username.
144
107
$BZREMAIL can be set to override this, then
145
108
the concrete policy type is checked, and finally
147
If none is found, a reasonable default is (hopefully)
110
but if none is found, a reasonable default is (hopefully)
150
113
TODO: Check it's reasonably well-formed.
188
151
def _get_parser(self, file=None):
189
152
if self._parser is not None:
190
153
return self._parser
192
input = self._get_filename()
154
parser = ConfigParser()
196
self._parser = ConfigObj(input)
197
except configobj.ConfigObjError, e:
198
raise errors.ParseConfigError(e.errors, e.config.filename)
158
parser.read([self._get_filename()])
159
self._parser = parser
201
162
def _get_section(self):
202
163
"""Override this to define the section used by the config."""
205
166
def _get_signature_checking(self):
206
167
"""See Config._get_signature_checking."""
207
policy = self._get_user_option('check_signatures')
209
return self._string_to_signature_policy(policy)
168
section = self._get_section()
171
if self._get_parser().has_option(section, 'check_signatures'):
172
return self._string_to_signature_policy(
173
self._get_parser().get(section, 'check_signatures'))
211
175
def _get_user_id(self):
212
176
"""Get the user id from the 'email' key in the current section."""
213
return self._get_user_option('email')
215
def _get_user_option(self, option_name):
216
"""See Config._get_user_option."""
218
return self._get_parser().get_value(self._get_section(),
177
section = self._get_section()
178
if section is not None:
179
if self._get_parser().has_option(section, 'email'):
180
return self._get_parser().get(section, 'email')
223
182
def _gpg_signing_command(self):
224
183
"""See Config.gpg_signing_command."""
225
return self._get_user_option('gpg_signing_command')
184
section = self._get_section()
185
if section is not None:
186
if self._get_parser().has_option(section, 'gpg_signing_command'):
187
return self._get_parser().get(section, 'gpg_signing_command')
227
189
def __init__(self, get_filename):
228
190
super(IniBasedConfig, self).__init__()
229
191
self._get_filename = get_filename
230
192
self._parser = None
232
def _post_commit(self):
233
"""See Config.post_commit."""
234
return self._get_user_option('post_commit')
236
194
def _string_to_signature_policy(self, signature_string):
237
195
"""Convert a string to a signing policy."""
249
207
"""The configuration that should be used for a specific location."""
251
209
def get_editor(self):
252
return self._get_user_option('editor')
210
if self._get_parser().has_option(self._get_section(), 'editor'):
211
return self._get_parser().get(self._get_section(), 'editor')
254
213
def __init__(self):
255
214
super(GlobalConfig, self).__init__(config_filename)
275
234
TODO: perhaps return a NullSection that thunks through to the
278
sections = self._get_parser()
237
sections = self._get_parser().sections()
279
238
location_names = self.location.split('/')
280
239
if self.location.endswith('/'):
281
240
del location_names[-1]
299
258
# if path is longer, and recurse is not true, no match
300
259
if len(section_names) < len(location_names):
302
if not self._get_parser().get_bool(section, 'recurse'):
260
if (self._get_parser().has_option(section, 'recurse')
261
and not self._get_parser().getboolean(section, 'recurse')):
306
263
matches.append((len(section_names), section))
307
264
if not len(matches):
323
280
return self._get_global_config()._get_user_id()
325
def _get_user_option(self, option_name):
326
"""See Config._get_user_option."""
327
option_value = super(LocationConfig,
328
self)._get_user_option(option_name)
329
if option_value is not None:
331
return self._get_global_config()._get_user_option(option_name)
333
282
def _get_signature_checking(self):
334
283
"""See Config._get_signature_checking."""
335
284
check = super(LocationConfig, self)._get_signature_checking()
338
287
return self._get_global_config()._get_signature_checking()
340
def _post_commit(self):
341
"""See Config.post_commit."""
342
hook = self._get_user_option('post_commit')
345
return self._get_global_config()._post_commit()
347
def set_user_option(self, option, value):
348
"""Save option and its value in the configuration."""
349
# FIXME: RBC 20051029 This should refresh the parser and also take a
350
# file lock on branches.conf.
351
if not os.path.isdir(os.path.dirname(self._get_filename())):
352
os.mkdir(os.path.dirname(self._get_filename()))
353
location = self.location
354
if location.endswith('/'):
355
location = location[:-1]
356
if (not location in self._get_parser() and
357
not location + '/' in self._get_parser()):
358
self._get_parser()[location]={}
359
elif location + '/' in self._get_parser():
360
location = location + '/'
361
self._get_parser()[location][option]=value
362
self._get_parser().write()
365
290
class BranchConfig(Config):
366
291
"""A configuration object giving the policy for a branch."""
390
315
"""See Config._get_signature_checking."""
391
316
return self._get_location_config()._get_signature_checking()
393
def _get_user_option(self, option_name):
394
"""See Config._get_user_option."""
395
return self._get_location_config()._get_user_option(option_name)
397
318
def _gpg_signing_command(self):
398
319
"""See Config.gpg_signing_command."""
399
320
return self._get_location_config()._gpg_signing_command()
416
333
TODO: Global option --config-dir to override this.
418
base = os.environ.get('BZR_HOME', None)
419
if sys.platform == 'win32':
421
base = os.environ.get('APPDATA', None)
423
base = os.environ.get('HOME', None)
425
raise BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
426
return os.path.join(base, 'bazaar', '2.0')
428
# cygwin, linux, and darwin all have a $HOME directory
430
base = os.path.expanduser("~")
431
return os.path.join(base, ".bazaar")
335
return os.path.join(os.path.expanduser("~"), ".bazaar")
434
338
def config_filename():
490
394
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
492
raise errors.BzrError("%r doesn't seem to contain "
493
"a reasonable email address" % e)
396
raise BzrError("%r doesn't seem to contain "
397
"a reasonable email address" % e)
494
398
return m.group(0)
496
class TreeConfig(object):
497
"""Branch configuration data associated with its contents, not location"""
498
def __init__(self, branch):
501
def _get_config(self):
503
obj = ConfigObj(self.branch.controlfile('branch.conf',
506
except errors.NoSuchFile:
510
def get_option(self, name, section=None, default=None):
511
self.branch.lock_read()
513
obj = self._get_config()
515
if section is not None:
524
def set_option(self, value, name, section=None):
525
"""Set a per-branch configuration option"""
526
self.branch.lock_write()
528
cfg_obj = self._get_config()
533
obj = cfg_obj[section]
535
cfg_obj[section] = {}
536
obj = cfg_obj[section]
538
cfg_obj.encode('UTF-8')
539
out_file = StringIO(''.join([l+'\n' for l in cfg_obj.write()]))
541
self.branch.put_controlfile('branch.conf', out_file, encode=False)