27
27
check_signatures=require|ignore|check-available(default)
28
28
create_signatures=always|never|when-required(default)
29
29
gpg_signing_command=name-of-program
30
log_format=name-of-format
32
31
in branches.conf, you specify the url of a branch and options for it.
33
32
Wildcards may be used - * and ? as normal in shell completion. Options
50
49
gpg signatures, never create them, or create them if the
51
50
branch is configured to require them.
52
51
NB: This option is planned, but not implemented yet.
53
log_format - This options set the default log format. Options are long,
54
short, line, or a plugin can register new formats
56
In bazaar.conf you can also define aliases in the ALIASES sections, example
59
lastlog=log --line -r-10..-1
60
ll=log --line -r-10..-1
54
from ConfigParser import ConfigParser
69
56
from fnmatch import fnmatch
73
61
import bzrlib.errors as errors
74
from bzrlib.osutils import pathjoin
75
from bzrlib.trace import mutter
76
import bzrlib.util.configobj.configobj as configobj
77
from StringIO import StringIO
79
64
CHECK_IF_POSSIBLE=0
84
class ConfigObj(configobj.ConfigObj):
86
def get_bool(self, section, key):
87
return self[section].as_bool(key)
89
def get_value(self, section, name):
90
# Try [] for the old DEFAULT section.
91
if section == "DEFAULT":
96
return self[section][name]
99
69
class Config(object):
100
70
"""A configuration policy - what username, editor, gpg needs etc."""
106
76
def _get_signature_checking(self):
107
77
"""Template method to override signature checking policy."""
109
def _get_user_option(self, option_name):
110
"""Template method to provide a user option."""
113
def get_user_option(self, option_name):
114
"""Get a generic option - no special process, no default."""
115
return self._get_user_option(option_name)
117
79
def gpg_signing_command(self):
118
80
"""What program should be used to sign signatures?"""
119
81
result = self._gpg_signing_command()
125
87
"""See gpg_signing_command()."""
128
def log_format(self):
129
"""What log format should be used"""
130
result = self._log_format()
135
def _log_format(self):
136
"""See log_format()."""
139
90
def __init__(self):
140
91
super(Config, self).__init__()
142
def post_commit(self):
143
"""An ordered list of python functions to call.
145
Each function takes branch, rev_id as parameters.
147
return self._post_commit()
149
def _post_commit(self):
150
"""See Config.post_commit."""
153
93
def user_email(self):
154
94
"""Return just the email component of a username."""
155
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)
157
102
def username(self):
158
103
"""Return email-style username.
162
107
$BZREMAIL can be set to override this, then
163
108
the concrete policy type is checked, and finally
165
If none is found, a reasonable default is (hopefully)
110
but if none is found, a reasonable default is (hopefully)
168
113
TODO: Check it's reasonably well-formed.
202
def get_alias(self, value):
203
return self._get_alias(value)
205
def _get_alias(self, value):
209
148
class IniBasedConfig(Config):
210
149
"""A configuration policy that draws from ini files."""
212
151
def _get_parser(self, file=None):
213
152
if self._parser is not None:
214
153
return self._parser
216
input = self._get_filename()
154
parser = ConfigParser()
220
self._parser = ConfigObj(input, encoding='utf-8')
221
except configobj.ConfigObjError, e:
222
raise errors.ParseConfigError(e.errors, e.config.filename)
158
parser.read([self._get_filename()])
159
self._parser = parser
225
162
def _get_section(self):
226
163
"""Override this to define the section used by the config."""
229
166
def _get_signature_checking(self):
230
167
"""See Config._get_signature_checking."""
231
policy = self._get_user_option('check_signatures')
233
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'))
235
175
def _get_user_id(self):
236
176
"""Get the user id from the 'email' key in the current section."""
237
return self._get_user_option('email')
239
def _get_user_option(self, option_name):
240
"""See Config._get_user_option."""
242
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')
247
182
def _gpg_signing_command(self):
248
183
"""See Config.gpg_signing_command."""
249
return self._get_user_option('gpg_signing_command')
251
def _log_format(self):
252
"""See Config.log_format."""
253
return self._get_user_option('log_format')
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')
255
189
def __init__(self, get_filename):
256
190
super(IniBasedConfig, self).__init__()
257
191
self._get_filename = get_filename
258
192
self._parser = None
260
def _post_commit(self):
261
"""See Config.post_commit."""
262
return self._get_user_option('post_commit')
264
194
def _string_to_signature_policy(self, signature_string):
265
195
"""Convert a string to a signing policy."""
272
202
raise errors.BzrError("Invalid signatures policy '%s'"
273
203
% signature_string)
275
def _get_alias(self, value):
277
return self._get_parser().get_value("ALIASES",
283
206
class GlobalConfig(IniBasedConfig):
284
207
"""The configuration that should be used for a specific location."""
286
209
def get_editor(self):
287
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')
289
213
def __init__(self):
290
214
super(GlobalConfig, self).__init__(config_filename)
310
234
TODO: perhaps return a NullSection that thunks through to the
313
sections = self._get_parser()
237
sections = self._get_parser().sections()
314
238
location_names = self.location.split('/')
315
239
if self.location.endswith('/'):
316
240
del location_names[-1]
334
258
# if path is longer, and recurse is not true, no match
335
259
if len(section_names) < len(location_names):
337
if not self._get_parser()[section].as_bool('recurse'):
260
if (self._get_parser().has_option(section, 'recurse')
261
and not self._get_parser().getboolean(section, 'recurse')):
341
263
matches.append((len(section_names), section))
342
264
if not len(matches):
352
274
return self._get_global_config()._gpg_signing_command()
354
def _log_format(self):
355
"""See Config.log_format."""
356
command = super(LocationConfig, self)._log_format()
357
if command is not None:
359
return self._get_global_config()._log_format()
361
276
def _get_user_id(self):
362
277
user_id = super(LocationConfig, self)._get_user_id()
363
278
if user_id is not None:
365
280
return self._get_global_config()._get_user_id()
367
def _get_user_option(self, option_name):
368
"""See Config._get_user_option."""
369
option_value = super(LocationConfig,
370
self)._get_user_option(option_name)
371
if option_value is not None:
373
return self._get_global_config()._get_user_option(option_name)
375
282
def _get_signature_checking(self):
376
283
"""See Config._get_signature_checking."""
377
284
check = super(LocationConfig, self)._get_signature_checking()
380
287
return self._get_global_config()._get_signature_checking()
382
def _post_commit(self):
383
"""See Config.post_commit."""
384
hook = self._get_user_option('post_commit')
387
return self._get_global_config()._post_commit()
389
def set_user_option(self, option, value):
390
"""Save option and its value in the configuration."""
391
# FIXME: RBC 20051029 This should refresh the parser and also take a
392
# file lock on branches.conf.
393
conf_dir = os.path.dirname(self._get_filename())
394
ensure_config_dir_exists(conf_dir)
395
location = self.location
396
if location.endswith('/'):
397
location = location[:-1]
398
if (not location in self._get_parser() and
399
not location + '/' in self._get_parser()):
400
self._get_parser()[location]={}
401
elif location + '/' in self._get_parser():
402
location = location + '/'
403
self._get_parser()[location][option]=value
404
self._get_parser().write(file(self._get_filename(), 'wb'))
407
290
class BranchConfig(Config):
408
291
"""A configuration object giving the policy for a branch."""
419
302
This is looked up in the email controlfile for the branch.
422
return (self.branch.control_files.get_utf8("email")
305
return (self.branch.controlfile("email", "r")
424
307
.decode(bzrlib.user_encoding)
432
315
"""See Config._get_signature_checking."""
433
316
return self._get_location_config()._get_signature_checking()
435
def _get_user_option(self, option_name):
436
"""See Config._get_user_option."""
437
return self._get_location_config()._get_user_option(option_name)
439
318
def _gpg_signing_command(self):
440
319
"""See Config.gpg_signing_command."""
441
320
return self._get_location_config()._gpg_signing_command()
445
324
self._location_config = None
446
325
self.branch = branch
448
def _post_commit(self):
449
"""See Config.post_commit."""
450
return self._get_location_config()._post_commit()
452
def _log_format(self):
453
"""See Config.log_format."""
454
return self._get_location_config()._log_format()
457
def ensure_config_dir_exists(path=None):
458
"""Make sure a configuration directory exists.
459
This makes sure that the directory exists.
460
On windows, since configuration directories are 2 levels deep,
461
it makes sure both the directory and the parent directory exists.
465
if not os.path.isdir(path):
466
if sys.platform == 'win32':
467
parent_dir = os.path.dirname(path)
468
if not os.path.isdir(parent_dir):
469
mutter('creating config parent directory: %r', parent_dir)
471
mutter('creating config directory: %r', path)
475
328
def config_dir():
476
329
"""Return per-user configuration directory.
480
333
TODO: Global option --config-dir to override this.
482
base = os.environ.get('BZR_HOME', None)
483
if sys.platform == 'win32':
485
base = os.environ.get('APPDATA', None)
487
base = os.environ.get('HOME', None)
489
raise BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
490
return pathjoin(base, 'bazaar', '2.0')
492
# cygwin, linux, and darwin all have a $HOME directory
494
base = os.path.expanduser("~")
495
return pathjoin(base, ".bazaar")
335
return os.path.join(os.path.expanduser("~"), ".bazaar")
498
338
def config_filename():
499
339
"""Return per-user configuration ini file filename."""
500
return pathjoin(config_dir(), 'bazaar.conf')
340
return os.path.join(config_dir(), 'bazaar.conf')
503
343
def branches_config_filename():
504
344
"""Return per-user configuration ini file filename."""
505
return pathjoin(config_dir(), 'branches.conf')
345
return os.path.join(config_dir(), 'branches.conf')
508
348
def _auto_user_id():
525
365
uid = os.getuid()
526
366
w = pwd.getpwuid(uid)
529
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
530
username = w.pw_name.decode(bzrlib.user_encoding)
531
except UnicodeDecodeError:
532
# We're using pwd, therefore we're on Unix, so /etc/passwd is ok.
533
raise errors.BzrError("Can't decode username in " \
534
"/etc/passwd as %s." % bzrlib.user_encoding)
367
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
368
username = w.pw_name.decode(bzrlib.user_encoding)
536
369
comma = gecos.find(',')
544
377
except ImportError:
547
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
548
except UnicodeDecodeError:
549
raise errors.BzrError("Can't decode username as %s." % \
550
bzrlib.user_encoding)
379
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
552
381
return realname, (username + '@' + socket.gethostname())
565
394
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
567
raise errors.BzrError("%r doesn't seem to contain "
568
"a reasonable email address" % e)
396
raise BzrError("%r doesn't seem to contain "
397
"a reasonable email address" % e)
569
398
return m.group(0)
571
class TreeConfig(object):
572
"""Branch configuration data associated with its contents, not location"""
573
def __init__(self, branch):
576
def _get_config(self):
578
obj = ConfigObj(self.branch.control_files.get('branch.conf'),
580
except errors.NoSuchFile:
581
obj = ConfigObj(encoding='utf=8')
584
def get_option(self, name, section=None, default=None):
585
self.branch.lock_read()
587
obj = self._get_config()
589
if section is not None:
598
def set_option(self, value, name, section=None):
599
"""Set a per-branch configuration option"""
600
self.branch.lock_write()
602
cfg_obj = self._get_config()
607
obj = cfg_obj[section]
609
cfg_obj[section] = {}
610
obj = cfg_obj[section]
612
out_file = StringIO()
613
cfg_obj.write(out_file)
615
self.branch.control_files.put('branch.conf', out_file)