1
# Copyright (C) 2005-2010 Canonical Ltd
2
# Authors: Robert Collins <robert.collins@canonical.com>
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
"""Configuration that affects the behaviour of Bazaar.
21
Currently this configuration resides in ~/.bazaar/bazaar.conf
22
and ~/.bazaar/locations.conf, which is written to by bzr.
24
In bazaar.conf the following options may be set:
26
editor=name-of-program
27
email=Your Name <your@email.address>
28
check_signatures=require|ignore|check-available(default)
29
create_signatures=always|never|when-required(default)
30
gpg_signing_command=name-of-program
31
log_format=name-of-format
33
in locations.conf, you specify the url of a branch and options for it.
34
Wildcards may be used - * and ? as normal in shell completion. Options
35
set in both bazaar.conf and locations.conf are overridden by the locations.conf
37
[/home/robertc/source]
38
recurse=False|True(default)
40
check_signatures= as above
41
create_signatures= as above.
43
explanation of options
44
----------------------
45
editor - this option sets the pop up editor to use during commits.
46
email - this option sets the user id bzr will use when committing.
47
check_signatures - this option controls whether bzr will require good gpg
48
signatures, ignore them, or check them if they are
50
create_signatures - this option controls whether bzr will always create
51
gpg signatures, never create them, or create them if the
52
branch is configured to require them.
53
log_format - this option sets the default log format. Possible values are
54
long, 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
68
from bzrlib.decorators import needs_write_lock
69
from bzrlib.lazy_import import lazy_import
70
lazy_import(globals(), """
72
from fnmatch import fnmatch
74
from cStringIO import StringIO
92
from bzrlib.util.configobj import configobj
108
POLICY_APPENDPATH = 2
112
POLICY_NORECURSE: 'norecurse',
113
POLICY_APPENDPATH: 'appendpath',
118
'norecurse': POLICY_NORECURSE,
119
'appendpath': POLICY_APPENDPATH,
123
STORE_LOCATION = POLICY_NONE
124
STORE_LOCATION_NORECURSE = POLICY_NORECURSE
125
STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
130
def ConfigObj(*args, **kwargs):
132
if _ConfigObj is None:
133
class ConfigObj(configobj.ConfigObj):
135
def get_bool(self, section, key):
136
return self[section].as_bool(key)
138
def get_value(self, section, name):
139
# Try [] for the old DEFAULT section.
140
if section == "DEFAULT":
145
return self[section][name]
146
_ConfigObj = ConfigObj
147
return _ConfigObj(*args, **kwargs)
150
class Config(object):
151
"""A configuration policy - what username, editor, gpg needs etc."""
154
super(Config, self).__init__()
156
def get_editor(self):
157
"""Get the users pop up editor."""
158
raise NotImplementedError
160
def get_change_editor(self, old_tree, new_tree):
161
from bzrlib import diff
162
cmd = self._get_change_editor()
165
return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
169
def get_mail_client(self):
170
"""Get a mail client to use"""
171
selected_client = self.get_user_option('mail_client')
172
_registry = mail_client.mail_client_registry
174
mail_client_class = _registry.get(selected_client)
176
raise errors.UnknownMailClient(selected_client)
177
return mail_client_class(self)
179
def _get_signature_checking(self):
180
"""Template method to override signature checking policy."""
182
def _get_signing_policy(self):
183
"""Template method to override signature creation policy."""
185
def _get_user_option(self, option_name):
186
"""Template method to provide a user option."""
189
def get_user_option(self, option_name):
190
"""Get a generic option - no special process, no default."""
191
return self._get_user_option(option_name)
193
def get_user_option_as_bool(self, option_name):
194
"""Get a generic option as a boolean - no special process, no default.
196
:return None if the option doesn't exist or its value can't be
197
interpreted as a boolean. Returns True or False otherwise.
199
s = self._get_user_option(option_name)
201
# The option doesn't exist
203
val = ui.bool_from_string(s)
205
# The value can't be interpreted as a boolean
206
trace.warning('Value "%s" is not a boolean for "%s"',
210
def get_user_option_as_list(self, option_name):
211
"""Get a generic option as a list - no special process, no default.
213
:return None if the option doesn't exist. Returns the value as a list
216
l = self._get_user_option(option_name)
217
if isinstance(l, (str, unicode)):
218
# A single value, most probably the user forgot the final ','
222
def gpg_signing_command(self):
223
"""What program should be used to sign signatures?"""
224
result = self._gpg_signing_command()
229
def _gpg_signing_command(self):
230
"""See gpg_signing_command()."""
233
def log_format(self):
234
"""What log format should be used"""
235
result = self._log_format()
240
def _log_format(self):
241
"""See log_format()."""
244
def post_commit(self):
245
"""An ordered list of python functions to call.
247
Each function takes branch, rev_id as parameters.
249
return self._post_commit()
251
def _post_commit(self):
252
"""See Config.post_commit."""
255
def user_email(self):
256
"""Return just the email component of a username."""
257
return extract_email_address(self.username())
260
"""Return email-style username.
262
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
264
$BZR_EMAIL can be set to override this, then
265
the concrete policy type is checked, and finally
267
If no username can be found, errors.NoWhoami exception is raised.
269
TODO: Check it's reasonably well-formed.
271
v = os.environ.get('BZR_EMAIL')
273
return v.decode(osutils.get_user_encoding())
275
v = self._get_user_id()
279
v = os.environ.get('EMAIL')
281
return v.decode(osutils.get_user_encoding())
283
raise errors.NoWhoami()
285
def ensure_username(self):
286
"""Raise errors.NoWhoami if username is not set.
288
This method relies on the username() function raising the error.
292
def signature_checking(self):
293
"""What is the current policy for signature checking?."""
294
policy = self._get_signature_checking()
295
if policy is not None:
297
return CHECK_IF_POSSIBLE
299
def signing_policy(self):
300
"""What is the current policy for signature checking?."""
301
policy = self._get_signing_policy()
302
if policy is not None:
304
return SIGN_WHEN_REQUIRED
306
def signature_needed(self):
307
"""Is a signature needed when committing ?."""
308
policy = self._get_signing_policy()
310
policy = self._get_signature_checking()
311
if policy is not None:
312
trace.warning("Please use create_signatures,"
313
" not check_signatures to set signing policy.")
314
if policy == CHECK_ALWAYS:
316
elif policy == SIGN_ALWAYS:
320
def get_alias(self, value):
321
return self._get_alias(value)
323
def _get_alias(self, value):
326
def get_nickname(self):
327
return self._get_nickname()
329
def _get_nickname(self):
332
def get_bzr_remote_path(self):
334
return os.environ['BZR_REMOTE_PATH']
336
path = self.get_user_option("bzr_remote_path")
341
def suppress_warning(self, warning):
342
"""Should the warning be suppressed or emitted.
344
:param warning: The name of the warning being tested.
346
:returns: True if the warning should be suppressed, False otherwise.
348
warnings = self.get_user_option_as_list('suppress_warnings')
349
if warnings is None or warning not in warnings:
355
class IniBasedConfig(Config):
356
"""A configuration policy that draws from ini files."""
358
def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
360
"""Base class for configuration files using an ini-like syntax.
362
:param file_name: The configuration file path.
364
super(IniBasedConfig, self).__init__()
365
self.file_name = file_name
366
if symbol_versioning.deprecated_passed(get_filename):
367
symbol_versioning.warn(
368
'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
369
' Use file_name instead.',
372
if get_filename is not None:
373
self.file_name = get_filename()
375
self.file_name = file_name
380
def from_string(cls, str_or_unicode, file_name=None, save=False):
381
"""Create a config object from a string.
383
:param str_or_unicode: A string representing the file content. This will
386
:param file_name: The configuration file path.
388
:param _save: Whether the file should be saved upon creation.
390
conf = cls(file_name=file_name)
391
conf._create_from_string(str_or_unicode, save)
394
def _create_from_string(self, str_or_unicode, save):
395
self._content = StringIO(str_or_unicode.encode('utf-8'))
396
# Some tests use in-memory configs, some other always need the config
397
# file to exist on disk.
399
self._write_config_file()
401
def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
402
if self._parser is not None:
404
if symbol_versioning.deprecated_passed(file):
405
symbol_versioning.warn(
406
'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
407
' Use IniBasedConfig(_content=xxx) instead.',
410
if self._content is not None:
411
co_input = self._content
412
elif self.file_name is None:
413
raise AssertionError('We have no content to create the config')
415
co_input = self.file_name
417
self._parser = ConfigObj(co_input, encoding='utf-8')
418
except configobj.ConfigObjError, e:
419
raise errors.ParseConfigError(e.errors, e.config.filename)
420
# Make sure self.reload() will use the right file name
421
self._parser.filename = self.file_name
425
"""Reload the config file from disk."""
426
if self.file_name is None:
427
raise AssertionError('We need a file name to reload the config')
428
if self._parser is not None:
429
self._parser.reload()
431
def _get_matching_sections(self):
432
"""Return an ordered list of (section_name, extra_path) pairs.
434
If the section contains inherited configuration, extra_path is
435
a string containing the additional path components.
437
section = self._get_section()
438
if section is not None:
439
return [(section, '')]
443
def _get_section(self):
444
"""Override this to define the section used by the config."""
447
def _get_option_policy(self, section, option_name):
448
"""Return the policy for the given (section, option_name) pair."""
451
def _get_change_editor(self):
452
return self.get_user_option('change_editor')
454
def _get_signature_checking(self):
455
"""See Config._get_signature_checking."""
456
policy = self._get_user_option('check_signatures')
458
return self._string_to_signature_policy(policy)
460
def _get_signing_policy(self):
461
"""See Config._get_signing_policy"""
462
policy = self._get_user_option('create_signatures')
464
return self._string_to_signing_policy(policy)
466
def _get_user_id(self):
467
"""Get the user id from the 'email' key in the current section."""
468
return self._get_user_option('email')
470
def _get_user_option(self, option_name):
471
"""See Config._get_user_option."""
472
for (section, extra_path) in self._get_matching_sections():
474
value = self._get_parser().get_value(section, option_name)
477
policy = self._get_option_policy(section, option_name)
478
if policy == POLICY_NONE:
480
elif policy == POLICY_NORECURSE:
481
# norecurse items only apply to the exact path
486
elif policy == POLICY_APPENDPATH:
488
value = urlutils.join(value, extra_path)
491
raise AssertionError('Unexpected config policy %r' % policy)
495
def _gpg_signing_command(self):
496
"""See Config.gpg_signing_command."""
497
return self._get_user_option('gpg_signing_command')
499
def _log_format(self):
500
"""See Config.log_format."""
501
return self._get_user_option('log_format')
503
def _post_commit(self):
504
"""See Config.post_commit."""
505
return self._get_user_option('post_commit')
507
def _string_to_signature_policy(self, signature_string):
508
"""Convert a string to a signing policy."""
509
if signature_string.lower() == 'check-available':
510
return CHECK_IF_POSSIBLE
511
if signature_string.lower() == 'ignore':
513
if signature_string.lower() == 'require':
515
raise errors.BzrError("Invalid signatures policy '%s'"
518
def _string_to_signing_policy(self, signature_string):
519
"""Convert a string to a signing policy."""
520
if signature_string.lower() == 'when-required':
521
return SIGN_WHEN_REQUIRED
522
if signature_string.lower() == 'never':
524
if signature_string.lower() == 'always':
526
raise errors.BzrError("Invalid signing policy '%s'"
529
def _get_alias(self, value):
531
return self._get_parser().get_value("ALIASES",
536
def _get_nickname(self):
537
return self.get_user_option('nickname')
539
def _write_config_file(self):
540
if self.file_name is None:
541
raise AssertionError('We cannot save, self.file_name is None')
542
conf_dir = os.path.dirname(self.file_name)
543
ensure_config_dir_exists(conf_dir)
544
atomic_file = atomicfile.AtomicFile(self.file_name)
545
self._get_parser().write(atomic_file)
548
osutils.copy_ownership_from_path(self.file_name)
551
class LockableConfig(IniBasedConfig):
552
"""A configuration needing explicit locking for access.
554
If several processes try to write the config file, the accesses need to be
557
Daughter classes should decorate all methods that update a config with the
558
``@needs_write_lock`` decorator (they call, directly or indirectly, the
559
``_write_config_file()`` method. These methods (typically ``set_option()``
560
and variants must reload the config file from disk before calling
561
``_write_config_file()``), this can be achieved by calling the
562
``self.reload()`` method. Note that the lock scope should cover both the
563
reading and the writing of the config file which is why the decorator can't
564
be applied to ``_write_config_file()`` only.
566
This should be enough to implement the following logic:
567
- lock for exclusive write access,
568
- reload the config file from disk,
572
This logic guarantees that a writer can update a value without erasing an
573
update made by another writer.
578
def __init__(self, file_name):
579
super(LockableConfig, self).__init__(file_name=file_name)
580
self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
581
self.transport = transport.get_transport(self.dir)
582
self._lock = lockdir.LockDir(self.transport, 'lock')
584
def _create_from_string(self, unicode_bytes, save):
585
super(LockableConfig, self)._create_from_string(unicode_bytes, False)
587
# We need to handle the saving here (as opposed to IniBasedConfig)
590
self._write_config_file()
593
def lock_write(self, token=None):
594
"""Takes a write lock in the directory containing the config file.
596
If the directory doesn't exist it is created.
598
ensure_config_dir_exists(self.dir)
599
return self._lock.lock_write(token)
604
def break_lock(self):
605
self._lock.break_lock()
607
def _write_config_file(self):
608
if self._lock is None or not self._lock.is_held:
609
# NB: if the following exception is raised it probably means a
610
# missing @needs_write_lock decorator on one of the callers.
611
raise errors.ObjectNotLocked(self)
612
super(LockableConfig, self)._write_config_file()
615
class GlobalConfig(LockableConfig):
616
"""The configuration that should be used for a specific location."""
619
super(GlobalConfig, self).__init__(file_name=config_filename())
622
def from_string(cls, str_or_unicode, save=False):
623
"""Create a config object from a string.
625
:param str_or_unicode: A string representing the file content. This
626
will be utf-8 encoded.
628
:param save: Whether the file should be saved upon creation.
631
conf._create_from_string(str_or_unicode, save)
634
def get_editor(self):
635
return self._get_user_option('editor')
638
def set_user_option(self, option, value):
639
"""Save option and its value in the configuration."""
640
self._set_option(option, value, 'DEFAULT')
642
def get_aliases(self):
643
"""Return the aliases section."""
644
if 'ALIASES' in self._get_parser():
645
return self._get_parser()['ALIASES']
650
def set_alias(self, alias_name, alias_command):
651
"""Save the alias in the configuration."""
652
self._set_option(alias_name, alias_command, 'ALIASES')
655
def unset_alias(self, alias_name):
656
"""Unset an existing alias."""
658
aliases = self._get_parser().get('ALIASES')
659
if not aliases or alias_name not in aliases:
660
raise errors.NoSuchAlias(alias_name)
661
del aliases[alias_name]
662
self._write_config_file()
664
def _set_option(self, option, value, section):
666
self._get_parser().setdefault(section, {})[option] = value
667
self._write_config_file()
670
class LocationConfig(LockableConfig):
671
"""A configuration object that gives the policy for a location."""
673
def __init__(self, location):
674
super(LocationConfig, self).__init__(
675
file_name=locations_config_filename())
676
# local file locations are looked up by local path, rather than
677
# by file url. This is because the config file is a user
678
# file, and we would rather not expose the user to file urls.
679
if location.startswith('file://'):
680
location = urlutils.local_path_from_url(location)
681
self.location = location
684
def from_string(cls, str_or_unicode, location, save=False):
685
"""Create a config object from a string.
687
:param str_or_unicode: A string representing the file content. This will
690
:param location: The location url to filter the configuration.
692
:param save: Whether the file should be saved upon creation.
695
conf._create_from_string(str_or_unicode, save)
698
def _get_matching_sections(self):
699
"""Return an ordered list of section names matching this location."""
700
sections = self._get_parser()
701
location_names = self.location.split('/')
702
if self.location.endswith('/'):
703
del location_names[-1]
705
for section in sections:
706
# location is a local path if possible, so we need
707
# to convert 'file://' urls to local paths if necessary.
708
# This also avoids having file:///path be a more exact
709
# match than '/path'.
710
if section.startswith('file://'):
711
section_path = urlutils.local_path_from_url(section)
713
section_path = section
714
section_names = section_path.split('/')
715
if section.endswith('/'):
716
del section_names[-1]
717
names = zip(location_names, section_names)
720
if not fnmatch(name[0], name[1]):
725
# so, for the common prefix they matched.
726
# if section is longer, no match.
727
if len(section_names) > len(location_names):
729
matches.append((len(section_names), section,
730
'/'.join(location_names[len(section_names):])))
731
matches.sort(reverse=True)
733
for (length, section, extra_path) in matches:
734
sections.append((section, extra_path))
735
# should we stop looking for parent configs here?
737
if self._get_parser()[section].as_bool('ignore_parents'):
743
def _get_option_policy(self, section, option_name):
744
"""Return the policy for the given (section, option_name) pair."""
745
# check for the old 'recurse=False' flag
747
recurse = self._get_parser()[section].as_bool('recurse')
751
return POLICY_NORECURSE
753
policy_key = option_name + ':policy'
755
policy_name = self._get_parser()[section][policy_key]
759
return _policy_value[policy_name]
761
def _set_option_policy(self, section, option_name, option_policy):
762
"""Set the policy for the given option name in the given section."""
763
# The old recurse=False option affects all options in the
764
# section. To handle multiple policies in the section, we
765
# need to convert it to a policy_norecurse key.
767
recurse = self._get_parser()[section].as_bool('recurse')
771
symbol_versioning.warn(
772
'The recurse option is deprecated as of 0.14. '
773
'The section "%s" has been converted to use policies.'
776
del self._get_parser()[section]['recurse']
778
for key in self._get_parser()[section].keys():
779
if not key.endswith(':policy'):
780
self._get_parser()[section][key +
781
':policy'] = 'norecurse'
783
policy_key = option_name + ':policy'
784
policy_name = _policy_name[option_policy]
785
if policy_name is not None:
786
self._get_parser()[section][policy_key] = policy_name
788
if policy_key in self._get_parser()[section]:
789
del self._get_parser()[section][policy_key]
792
def set_user_option(self, option, value, store=STORE_LOCATION):
793
"""Save option and its value in the configuration."""
794
if store not in [STORE_LOCATION,
795
STORE_LOCATION_NORECURSE,
796
STORE_LOCATION_APPENDPATH]:
797
raise ValueError('bad storage policy %r for %r' %
800
location = self.location
801
if location.endswith('/'):
802
location = location[:-1]
803
parser = self._get_parser()
804
if not location in parser and not location + '/' in parser:
805
parser[location] = {}
806
elif location + '/' in parser:
807
location = location + '/'
808
parser[location][option]=value
809
# the allowed values of store match the config policies
810
self._set_option_policy(location, option, store)
811
self._write_config_file()
814
class BranchConfig(Config):
815
"""A configuration object giving the policy for a branch."""
817
def __init__(self, branch):
818
super(BranchConfig, self).__init__()
819
self._location_config = None
820
self._branch_data_config = None
821
self._global_config = None
823
self.option_sources = (self._get_location_config,
824
self._get_branch_data_config,
825
self._get_global_config)
827
def _get_branch_data_config(self):
828
if self._branch_data_config is None:
829
self._branch_data_config = TreeConfig(self.branch)
830
return self._branch_data_config
832
def _get_location_config(self):
833
if self._location_config is None:
834
self._location_config = LocationConfig(self.branch.base)
835
return self._location_config
837
def _get_global_config(self):
838
if self._global_config is None:
839
self._global_config = GlobalConfig()
840
return self._global_config
842
def _get_best_value(self, option_name):
843
"""This returns a user option from local, tree or global config.
845
They are tried in that order. Use get_safe_value if trusted values
848
for source in self.option_sources:
849
value = getattr(source(), option_name)()
850
if value is not None:
854
def _get_safe_value(self, option_name):
855
"""This variant of get_best_value never returns untrusted values.
857
It does not return values from the branch data, because the branch may
858
not be controlled by the user.
860
We may wish to allow locations.conf to control whether branches are
861
trusted in the future.
863
for source in (self._get_location_config, self._get_global_config):
864
value = getattr(source(), option_name)()
865
if value is not None:
869
def _get_user_id(self):
870
"""Return the full user id for the branch.
872
e.g. "John Hacker <jhacker@example.com>"
873
This is looked up in the email controlfile for the branch.
876
return (self.branch._transport.get_bytes("email")
877
.decode(osutils.get_user_encoding())
879
except errors.NoSuchFile, e:
882
return self._get_best_value('_get_user_id')
884
def _get_change_editor(self):
885
return self._get_best_value('_get_change_editor')
887
def _get_signature_checking(self):
888
"""See Config._get_signature_checking."""
889
return self._get_best_value('_get_signature_checking')
891
def _get_signing_policy(self):
892
"""See Config._get_signing_policy."""
893
return self._get_best_value('_get_signing_policy')
895
def _get_user_option(self, option_name):
896
"""See Config._get_user_option."""
897
for source in self.option_sources:
898
value = source()._get_user_option(option_name)
899
if value is not None:
903
def set_user_option(self, name, value, store=STORE_BRANCH,
905
if store == STORE_BRANCH:
906
self._get_branch_data_config().set_option(value, name)
907
elif store == STORE_GLOBAL:
908
self._get_global_config().set_user_option(name, value)
910
self._get_location_config().set_user_option(name, value, store)
913
if store in (STORE_GLOBAL, STORE_BRANCH):
914
mask_value = self._get_location_config().get_user_option(name)
915
if mask_value is not None:
916
trace.warning('Value "%s" is masked by "%s" from'
917
' locations.conf', value, mask_value)
919
if store == STORE_GLOBAL:
920
branch_config = self._get_branch_data_config()
921
mask_value = branch_config.get_user_option(name)
922
if mask_value is not None:
923
trace.warning('Value "%s" is masked by "%s" from'
924
' branch.conf', value, mask_value)
926
def _gpg_signing_command(self):
927
"""See Config.gpg_signing_command."""
928
return self._get_safe_value('_gpg_signing_command')
930
def _post_commit(self):
931
"""See Config.post_commit."""
932
return self._get_safe_value('_post_commit')
934
def _get_nickname(self):
935
value = self._get_explicit_nickname()
936
if value is not None:
938
return urlutils.unescape(self.branch.base.split('/')[-2])
940
def has_explicit_nickname(self):
941
"""Return true if a nickname has been explicitly assigned."""
942
return self._get_explicit_nickname() is not None
944
def _get_explicit_nickname(self):
945
return self._get_best_value('_get_nickname')
947
def _log_format(self):
948
"""See Config.log_format."""
949
return self._get_best_value('_log_format')
952
def ensure_config_dir_exists(path=None):
953
"""Make sure a configuration directory exists.
954
This makes sure that the directory exists.
955
On windows, since configuration directories are 2 levels deep,
956
it makes sure both the directory and the parent directory exists.
960
if not os.path.isdir(path):
961
if sys.platform == 'win32':
962
parent_dir = os.path.dirname(path)
963
if not os.path.isdir(parent_dir):
964
trace.mutter('creating config parent directory: %r', parent_dir)
966
trace.mutter('creating config directory: %r', path)
968
osutils.copy_ownership_from_path(path)
972
"""Return per-user configuration directory.
974
By default this is ~/.bazaar/
976
TODO: Global option --config-dir to override this.
978
base = os.environ.get('BZR_HOME', None)
979
if sys.platform == 'win32':
981
base = win32utils.get_appdata_location_unicode()
983
base = os.environ.get('HOME', None)
985
raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
987
return osutils.pathjoin(base, 'bazaar', '2.0')
990
base = os.path.expanduser("~")
991
return osutils.pathjoin(base, ".bazaar")
994
def config_filename():
995
"""Return per-user configuration ini file filename."""
996
return osutils.pathjoin(config_dir(), 'bazaar.conf')
999
def locations_config_filename():
1000
"""Return per-user configuration ini file filename."""
1001
return osutils.pathjoin(config_dir(), 'locations.conf')
1004
def authentication_config_filename():
1005
"""Return per-user authentication ini file filename."""
1006
return osutils.pathjoin(config_dir(), 'authentication.conf')
1009
def user_ignore_config_filename():
1010
"""Return the user default ignore filename"""
1011
return osutils.pathjoin(config_dir(), 'ignore')
1015
"""Return the directory name to store crash files.
1017
This doesn't implicitly create it.
1019
On Windows it's in the config directory; elsewhere it's /var/crash
1020
which may be monitored by apport. It can be overridden by
1023
if sys.platform == 'win32':
1024
return osutils.pathjoin(config_dir(), 'Crash')
1026
# XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
1028
return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
1031
def xdg_cache_dir():
1032
# See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1033
# Possibly this should be different on Windows?
1034
e = os.environ.get('XDG_CACHE_DIR', None)
1038
return os.path.expanduser('~/.cache')
1041
def parse_username(username):
1042
"""Parse e-mail username and return a (name, address) tuple."""
1043
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1045
return (username, '')
1047
return (match.group(1), match.group(2))
1050
def extract_email_address(e):
1051
"""Return just the address part of an email string.
1053
That is just the user@domain part, nothing else.
1054
This part is required to contain only ascii characters.
1055
If it can't be extracted, raises an error.
1057
>>> extract_email_address('Jane Tester <jane@test.com>')
1060
name, email = parse_username(e)
1062
raise errors.NoEmailInUsername(e)
1066
class TreeConfig(IniBasedConfig):
1067
"""Branch configuration data associated with its contents, not location"""
1069
# XXX: Really needs a better name, as this is not part of the tree! -- mbp 20080507
1071
def __init__(self, branch):
1072
self._config = branch._get_config()
1073
self.branch = branch
1075
def _get_parser(self, file=None):
1076
if file is not None:
1077
return IniBasedConfig._get_parser(file)
1078
return self._config._get_configobj()
1080
def get_option(self, name, section=None, default=None):
1081
self.branch.lock_read()
1083
return self._config.get_option(name, section, default)
1085
self.branch.unlock()
1087
def set_option(self, value, name, section=None):
1088
"""Set a per-branch configuration option"""
1089
self.branch.lock_write()
1091
self._config.set_option(value, name, section)
1093
self.branch.unlock()
1096
class AuthenticationConfig(object):
1097
"""The authentication configuration file based on a ini file.
1099
Implements the authentication.conf file described in
1100
doc/developers/authentication-ring.txt.
1103
def __init__(self, _file=None):
1104
self._config = None # The ConfigObj
1106
self._filename = authentication_config_filename()
1107
self._input = self._filename = authentication_config_filename()
1109
# Tests can provide a string as _file
1110
self._filename = None
1113
def _get_config(self):
1114
if self._config is not None:
1117
# FIXME: Should we validate something here ? Includes: empty
1118
# sections are useless, at least one of
1119
# user/password/password_encoding should be defined, etc.
1121
# Note: the encoding below declares that the file itself is utf-8
1122
# encoded, but the values in the ConfigObj are always Unicode.
1123
self._config = ConfigObj(self._input, encoding='utf-8')
1124
except configobj.ConfigObjError, e:
1125
raise errors.ParseConfigError(e.errors, e.config.filename)
1129
"""Save the config file, only tests should use it for now."""
1130
conf_dir = os.path.dirname(self._filename)
1131
ensure_config_dir_exists(conf_dir)
1132
f = file(self._filename, 'wb')
1134
self._get_config().write(f)
1138
def _set_option(self, section_name, option_name, value):
1139
"""Set an authentication configuration option"""
1140
conf = self._get_config()
1141
section = conf.get(section_name)
1144
section = conf[section]
1145
section[option_name] = value
1148
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1150
"""Returns the matching credentials from authentication.conf file.
1152
:param scheme: protocol
1154
:param host: the server address
1156
:param port: the associated port (optional)
1158
:param user: login (optional)
1160
:param path: the absolute path on the server (optional)
1162
:param realm: the http authentication realm (optional)
1164
:return: A dict containing the matching credentials or None.
1166
- name: the section name of the credentials in the
1167
authentication.conf file,
1168
- user: can't be different from the provided user if any,
1169
- scheme: the server protocol,
1170
- host: the server address,
1171
- port: the server port (can be None),
1172
- path: the absolute server path (can be None),
1173
- realm: the http specific authentication realm (can be None),
1174
- password: the decoded password, could be None if the credential
1175
defines only the user
1176
- verify_certificates: https specific, True if the server
1177
certificate should be verified, False otherwise.
1180
for auth_def_name, auth_def in self._get_config().items():
1181
if type(auth_def) is not configobj.Section:
1182
raise ValueError("%s defined outside a section" % auth_def_name)
1184
a_scheme, a_host, a_user, a_path = map(
1185
auth_def.get, ['scheme', 'host', 'user', 'path'])
1188
a_port = auth_def.as_int('port')
1192
raise ValueError("'port' not numeric in %s" % auth_def_name)
1194
a_verify_certificates = auth_def.as_bool('verify_certificates')
1196
a_verify_certificates = True
1199
"'verify_certificates' not boolean in %s" % auth_def_name)
1202
if a_scheme is not None and scheme != a_scheme:
1204
if a_host is not None:
1205
if not (host == a_host
1206
or (a_host.startswith('.') and host.endswith(a_host))):
1208
if a_port is not None and port != a_port:
1210
if (a_path is not None and path is not None
1211
and not path.startswith(a_path)):
1213
if (a_user is not None and user is not None
1214
and a_user != user):
1215
# Never contradict the caller about the user to be used
1220
# Prepare a credentials dictionary with additional keys
1221
# for the credential providers
1222
credentials = dict(name=auth_def_name,
1229
password=auth_def.get('password', None),
1230
verify_certificates=a_verify_certificates)
1231
# Decode the password in the credentials (or get one)
1232
self.decode_password(credentials,
1233
auth_def.get('password_encoding', None))
1234
if 'auth' in debug.debug_flags:
1235
trace.mutter("Using authentication section: %r", auth_def_name)
1238
if credentials is None:
1239
# No credentials were found in authentication.conf, try the fallback
1240
# credentials stores.
1241
credentials = credential_store_registry.get_fallback_credentials(
1242
scheme, host, port, user, path, realm)
1246
def set_credentials(self, name, host, user, scheme=None, password=None,
1247
port=None, path=None, verify_certificates=None,
1249
"""Set authentication credentials for a host.
1251
Any existing credentials with matching scheme, host, port and path
1252
will be deleted, regardless of name.
1254
:param name: An arbitrary name to describe this set of credentials.
1255
:param host: Name of the host that accepts these credentials.
1256
:param user: The username portion of these credentials.
1257
:param scheme: The URL scheme (e.g. ssh, http) the credentials apply
1259
:param password: Password portion of these credentials.
1260
:param port: The IP port on the host that these credentials apply to.
1261
:param path: A filesystem path on the host that these credentials
1263
:param verify_certificates: On https, verify server certificates if
1265
:param realm: The http authentication realm (optional).
1267
values = {'host': host, 'user': user}
1268
if password is not None:
1269
values['password'] = password
1270
if scheme is not None:
1271
values['scheme'] = scheme
1272
if port is not None:
1273
values['port'] = '%d' % port
1274
if path is not None:
1275
values['path'] = path
1276
if verify_certificates is not None:
1277
values['verify_certificates'] = str(verify_certificates)
1278
if realm is not None:
1279
values['realm'] = realm
1280
config = self._get_config()
1282
for section, existing_values in config.items():
1283
for key in ('scheme', 'host', 'port', 'path', 'realm'):
1284
if existing_values.get(key) != values.get(key):
1288
config.update({name: values})
1291
def get_user(self, scheme, host, port=None, realm=None, path=None,
1292
prompt=None, ask=False, default=None):
1293
"""Get a user from authentication file.
1295
:param scheme: protocol
1297
:param host: the server address
1299
:param port: the associated port (optional)
1301
:param realm: the realm sent by the server (optional)
1303
:param path: the absolute path on the server (optional)
1305
:param ask: Ask the user if there is no explicitly configured username
1308
:param default: The username returned if none is defined (optional).
1310
:return: The found user.
1312
credentials = self.get_credentials(scheme, host, port, user=None,
1313
path=path, realm=realm)
1314
if credentials is not None:
1315
user = credentials['user']
1321
# Create a default prompt suitable for most cases
1322
prompt = scheme.upper() + ' %(host)s username'
1323
# Special handling for optional fields in the prompt
1324
if port is not None:
1325
prompt_host = '%s:%d' % (host, port)
1328
user = ui.ui_factory.get_username(prompt, host=prompt_host)
1333
def get_password(self, scheme, host, user, port=None,
1334
realm=None, path=None, prompt=None):
1335
"""Get a password from authentication file or prompt the user for one.
1337
:param scheme: protocol
1339
:param host: the server address
1341
:param port: the associated port (optional)
1345
:param realm: the realm sent by the server (optional)
1347
:param path: the absolute path on the server (optional)
1349
:return: The found password or the one entered by the user.
1351
credentials = self.get_credentials(scheme, host, port, user, path,
1353
if credentials is not None:
1354
password = credentials['password']
1355
if password is not None and scheme is 'ssh':
1356
trace.warning('password ignored in section [%s],'
1357
' use an ssh agent instead'
1358
% credentials['name'])
1362
# Prompt user only if we could't find a password
1363
if password is None:
1365
# Create a default prompt suitable for most cases
1366
prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
1367
# Special handling for optional fields in the prompt
1368
if port is not None:
1369
prompt_host = '%s:%d' % (host, port)
1372
password = ui.ui_factory.get_password(prompt,
1373
host=prompt_host, user=user)
1376
def decode_password(self, credentials, encoding):
1378
cs = credential_store_registry.get_credential_store(encoding)
1380
raise ValueError('%r is not a known password_encoding' % encoding)
1381
credentials['password'] = cs.decode_password(credentials)
1385
class CredentialStoreRegistry(registry.Registry):
1386
"""A class that registers credential stores.
1388
A credential store provides access to credentials via the password_encoding
1389
field in authentication.conf sections.
1391
Except for stores provided by bzr itself, most stores are expected to be
1392
provided by plugins that will therefore use
1393
register_lazy(password_encoding, module_name, member_name, help=help,
1394
fallback=fallback) to install themselves.
1396
A fallback credential store is one that is queried if no credentials can be
1397
found via authentication.conf.
1400
def get_credential_store(self, encoding=None):
1401
cs = self.get(encoding)
1406
def is_fallback(self, name):
1407
"""Check if the named credentials store should be used as fallback."""
1408
return self.get_info(name)
1410
def get_fallback_credentials(self, scheme, host, port=None, user=None,
1411
path=None, realm=None):
1412
"""Request credentials from all fallback credentials stores.
1414
The first credentials store that can provide credentials wins.
1417
for name in self.keys():
1418
if not self.is_fallback(name):
1420
cs = self.get_credential_store(name)
1421
credentials = cs.get_credentials(scheme, host, port, user,
1423
if credentials is not None:
1424
# We found some credentials
1428
def register(self, key, obj, help=None, override_existing=False,
1430
"""Register a new object to a name.
1432
:param key: This is the key to use to request the object later.
1433
:param obj: The object to register.
1434
:param help: Help text for this entry. This may be a string or
1435
a callable. If it is a callable, it should take two
1436
parameters (registry, key): this registry and the key that
1437
the help was registered under.
1438
:param override_existing: Raise KeyErorr if False and something has
1439
already been registered for that key. If True, ignore if there
1440
is an existing key (always register the new value).
1441
:param fallback: Whether this credential store should be
1444
return super(CredentialStoreRegistry,
1445
self).register(key, obj, help, info=fallback,
1446
override_existing=override_existing)
1448
def register_lazy(self, key, module_name, member_name,
1449
help=None, override_existing=False,
1451
"""Register a new credential store to be loaded on request.
1453
:param module_name: The python path to the module. Such as 'os.path'.
1454
:param member_name: The member of the module to return. If empty or
1455
None, get() will return the module itself.
1456
:param help: Help text for this entry. This may be a string or
1458
:param override_existing: If True, replace the existing object
1459
with the new one. If False, if there is already something
1460
registered with the same key, raise a KeyError
1461
:param fallback: Whether this credential store should be
1464
return super(CredentialStoreRegistry, self).register_lazy(
1465
key, module_name, member_name, help,
1466
info=fallback, override_existing=override_existing)
1469
credential_store_registry = CredentialStoreRegistry()
1472
class CredentialStore(object):
1473
"""An abstract class to implement storage for credentials"""
1475
def decode_password(self, credentials):
1476
"""Returns a clear text password for the provided credentials."""
1477
raise NotImplementedError(self.decode_password)
1479
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1481
"""Return the matching credentials from this credential store.
1483
This method is only called on fallback credential stores.
1485
raise NotImplementedError(self.get_credentials)
1489
class PlainTextCredentialStore(CredentialStore):
1490
__doc__ = """Plain text credential store for the authentication.conf file"""
1492
def decode_password(self, credentials):
1493
"""See CredentialStore.decode_password."""
1494
return credentials['password']
1497
credential_store_registry.register('plain', PlainTextCredentialStore,
1498
help=PlainTextCredentialStore.__doc__)
1499
credential_store_registry.default_key = 'plain'
1502
class BzrDirConfig(object):
1504
def __init__(self, bzrdir):
1505
self._bzrdir = bzrdir
1506
self._config = bzrdir._get_config()
1508
def set_default_stack_on(self, value):
1509
"""Set the default stacking location.
1511
It may be set to a location, or None.
1513
This policy affects all branches contained by this bzrdir, except for
1514
those under repositories.
1516
if self._config is None:
1517
raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
1519
self._config.set_option('', 'default_stack_on')
1521
self._config.set_option(value, 'default_stack_on')
1523
def get_default_stack_on(self):
1524
"""Return the default stacking location.
1526
This will either be a location, or None.
1528
This policy affects all branches contained by this bzrdir, except for
1529
those under repositories.
1531
if self._config is None:
1533
value = self._config.get_option('default_stack_on')
1539
class TransportConfig(object):
1540
"""A Config that reads/writes a config file on a Transport.
1542
It is a low-level object that considers config data to be name/value pairs
1543
that may be associated with a section. Assigning meaning to the these
1544
values is done at higher levels like TreeConfig.
1547
def __init__(self, transport, filename):
1548
self._transport = transport
1549
self._filename = filename
1551
def get_option(self, name, section=None, default=None):
1552
"""Return the value associated with a named option.
1554
:param name: The name of the value
1555
:param section: The section the option is in (if any)
1556
:param default: The value to return if the value is not set
1557
:return: The value or default value
1559
configobj = self._get_configobj()
1561
section_obj = configobj
1564
section_obj = configobj[section]
1567
return section_obj.get(name, default)
1569
def set_option(self, value, name, section=None):
1570
"""Set the value associated with a named option.
1572
:param value: The value to set
1573
:param name: The name of the value to set
1574
:param section: The section the option is in (if any)
1576
configobj = self._get_configobj()
1578
configobj[name] = value
1580
configobj.setdefault(section, {})[name] = value
1581
self._set_configobj(configobj)
1583
def _get_config_file(self):
1585
return StringIO(self._transport.get_bytes(self._filename))
1586
except errors.NoSuchFile:
1589
def _get_configobj(self):
1590
f = self._get_config_file()
1592
return ConfigObj(f, encoding='utf-8')
1596
def _set_configobj(self, configobj):
1597
out_file = StringIO()
1598
configobj.write(out_file)
1600
self._transport.put_file(self._filename, out_file)