50
48
create_signatures - this option controls whether bzr will always create
51
49
gpg signatures, never create them, or create them if the
52
50
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
51
NB: This option is planned, but not implemented yet.
68
from bzrlib.lazy_import import lazy_import
69
lazy_import(globals(), """
71
57
from fnmatch import fnmatch
73
from cStringIO import StringIO
87
from bzrlib.util.configobj import configobj
61
import bzrlib.errors as errors
62
import bzrlib.util.configobj.configobj as configobj
63
from StringIO import StringIO
91
65
CHECK_IF_POSSIBLE=0
103
POLICY_APPENDPATH = 2
107
POLICY_NORECURSE: 'norecurse',
108
POLICY_APPENDPATH: 'appendpath',
113
'norecurse': POLICY_NORECURSE,
114
'appendpath': POLICY_APPENDPATH,
118
STORE_LOCATION = POLICY_NONE
119
STORE_LOCATION_NORECURSE = POLICY_NORECURSE
120
STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
125
def ConfigObj(*args, **kwargs):
127
if _ConfigObj is None:
128
class ConfigObj(configobj.ConfigObj):
130
def get_bool(self, section, key):
131
return self[section].as_bool(key)
133
def get_value(self, section, name):
134
# Try [] for the old DEFAULT section.
135
if section == "DEFAULT":
140
return self[section][name]
141
_ConfigObj = ConfigObj
142
return _ConfigObj(*args, **kwargs)
70
class ConfigObj(configobj.ConfigObj):
72
def get_bool(self, section, key):
73
val = self[section][key].lower()
74
if val in ('1', 'yes', 'true', 'on'):
76
elif val in ('0', 'no', 'false', 'off'):
79
raise ValueError("Value %r is not boolean" % val)
81
def get_value(self, section, name):
82
# Try [] for the old DEFAULT section.
83
if section == "DEFAULT":
88
return self[section][name]
145
91
class Config(object):
309
self._parser = ConfigObj(input, encoding='utf-8')
195
self._parser = ConfigObj(input)
310
196
except configobj.ConfigObjError, e:
311
197
raise errors.ParseConfigError(e.errors, e.config.filename)
312
198
return self._parser
314
def _get_matching_sections(self):
315
"""Return an ordered list of (section_name, extra_path) pairs.
317
If the section contains inherited configuration, extra_path is
318
a string containing the additional path components.
320
section = self._get_section()
321
if section is not None:
322
return [(section, '')]
326
200
def _get_section(self):
327
201
"""Override this to define the section used by the config."""
330
def _get_option_policy(self, section, option_name):
331
"""Return the policy for the given (section, option_name) pair."""
334
204
def _get_signature_checking(self):
335
205
"""See Config._get_signature_checking."""
336
206
policy = self._get_user_option('check_signatures')
338
208
return self._string_to_signature_policy(policy)
340
def _get_signing_policy(self):
341
"""See Config._get_signing_policy"""
342
policy = self._get_user_option('create_signatures')
344
return self._string_to_signing_policy(policy)
346
210
def _get_user_id(self):
347
211
"""Get the user id from the 'email' key in the current section."""
348
212
return self._get_user_option('email')
350
214
def _get_user_option(self, option_name):
351
215
"""See Config._get_user_option."""
352
for (section, extra_path) in self._get_matching_sections():
354
value = self._get_parser().get_value(section, option_name)
357
policy = self._get_option_policy(section, option_name)
358
if policy == POLICY_NONE:
360
elif policy == POLICY_NORECURSE:
361
# norecurse items only apply to the exact path
366
elif policy == POLICY_APPENDPATH:
368
value = urlutils.join(value, extra_path)
371
raise AssertionError('Unexpected config policy %r' % policy)
217
return self._get_parser().get_value(self._get_section(),
375
222
def _gpg_signing_command(self):
376
223
"""See Config.gpg_signing_command."""
377
224
return self._get_user_option('gpg_signing_command')
379
def _log_format(self):
380
"""See Config.log_format."""
381
return self._get_user_option('log_format')
383
226
def __init__(self, get_filename):
384
227
super(IniBasedConfig, self).__init__()
385
228
self._get_filename = get_filename
431
253
def __init__(self):
432
254
super(GlobalConfig, self).__init__(config_filename)
434
def set_user_option(self, option, value):
435
"""Save option and its value in the configuration."""
436
self._set_option(option, value, 'DEFAULT')
438
def get_aliases(self):
439
"""Return the aliases section."""
440
if 'ALIASES' in self._get_parser():
441
return self._get_parser()['ALIASES']
445
def set_alias(self, alias_name, alias_command):
446
"""Save the alias in the configuration."""
447
self._set_option(alias_name, alias_command, 'ALIASES')
449
def unset_alias(self, alias_name):
450
"""Unset an existing alias."""
451
aliases = self._get_parser().get('ALIASES')
452
if not aliases or alias_name not in aliases:
453
raise errors.NoSuchAlias(alias_name)
454
del aliases[alias_name]
455
self._write_config_file()
457
def _set_option(self, option, value, section):
458
# FIXME: RBC 20051029 This should refresh the parser and also take a
459
# file lock on bazaar.conf.
460
conf_dir = os.path.dirname(self._get_filename())
461
ensure_config_dir_exists(conf_dir)
462
self._get_parser().setdefault(section, {})[option] = value
463
self._write_config_file()
465
def _write_config_file(self):
466
f = open(self._get_filename(), 'wb')
467
self._get_parser().write(f)
471
257
class LocationConfig(IniBasedConfig):
472
258
"""A configuration object that gives the policy for a location."""
474
260
def __init__(self, location):
475
name_generator = locations_config_filename
476
if (not os.path.exists(name_generator()) and
477
os.path.exists(branches_config_filename())):
478
if sys.platform == 'win32':
479
trace.warning('Please rename %s to %s'
480
% (branches_config_filename(),
481
locations_config_filename()))
483
trace.warning('Please rename ~/.bazaar/branches.conf'
484
' to ~/.bazaar/locations.conf')
485
name_generator = branches_config_filename
486
super(LocationConfig, self).__init__(name_generator)
487
# local file locations are looked up by local path, rather than
488
# by file url. This is because the config file is a user
489
# file, and we would rather not expose the user to file urls.
490
if location.startswith('file://'):
491
location = urlutils.local_path_from_url(location)
261
super(LocationConfig, self).__init__(branches_config_filename)
262
self._global_config = None
492
263
self.location = location
494
def _get_matching_sections(self):
495
"""Return an ordered list of section names matching this location."""
265
def _get_global_config(self):
266
if self._global_config is None:
267
self._global_config = GlobalConfig()
268
return self._global_config
270
def _get_section(self):
271
"""Get the section we should look in for config items.
273
Returns None if none exists.
274
TODO: perhaps return a NullSection that thunks through to the
496
277
sections = self._get_parser()
497
278
location_names = self.location.split('/')
498
279
if self.location.endswith('/'):
499
280
del location_names[-1]
501
282
for section in sections:
502
# location is a local path if possible, so we need
503
# to convert 'file://' urls to local paths if necessary.
504
# This also avoids having file:///path be a more exact
505
# match than '/path'.
506
if section.startswith('file://'):
507
section_path = urlutils.local_path_from_url(section)
509
section_path = section
510
section_names = section_path.split('/')
283
section_names = section.split('/')
511
284
if section.endswith('/'):
512
285
del section_names[-1]
513
286
names = zip(location_names, section_names)
522
295
# if section is longer, no match.
523
296
if len(section_names) > len(location_names):
525
matches.append((len(section_names), section,
526
'/'.join(location_names[len(section_names):])))
298
# if path is longer, and recurse is not true, no match
299
if len(section_names) < len(location_names):
301
if not self._get_parser().get_bool(section, 'recurse'):
305
matches.append((len(section_names), section))
527
308
matches.sort(reverse=True)
529
for (length, section, extra_path) in matches:
530
sections.append((section, extra_path))
531
# should we stop looking for parent configs here?
533
if self._get_parser()[section].as_bool('ignore_parents'):
539
def _get_option_policy(self, section, option_name):
540
"""Return the policy for the given (section, option_name) pair."""
541
# check for the old 'recurse=False' flag
543
recurse = self._get_parser()[section].as_bool('recurse')
547
return POLICY_NORECURSE
549
policy_key = option_name + ':policy'
551
policy_name = self._get_parser()[section][policy_key]
555
return _policy_value[policy_name]
557
def _set_option_policy(self, section, option_name, option_policy):
558
"""Set the policy for the given option name in the given section."""
559
# The old recurse=False option affects all options in the
560
# section. To handle multiple policies in the section, we
561
# need to convert it to a policy_norecurse key.
563
recurse = self._get_parser()[section].as_bool('recurse')
567
symbol_versioning.warn(
568
'The recurse option is deprecated as of 0.14. '
569
'The section "%s" has been converted to use policies.'
572
del self._get_parser()[section]['recurse']
574
for key in self._get_parser()[section].keys():
575
if not key.endswith(':policy'):
576
self._get_parser()[section][key +
577
':policy'] = 'norecurse'
579
policy_key = option_name + ':policy'
580
policy_name = _policy_name[option_policy]
581
if policy_name is not None:
582
self._get_parser()[section][policy_key] = policy_name
584
if policy_key in self._get_parser()[section]:
585
del self._get_parser()[section][policy_key]
587
def set_user_option(self, option, value, store=STORE_LOCATION):
311
def _gpg_signing_command(self):
312
"""See Config.gpg_signing_command."""
313
command = super(LocationConfig, self)._gpg_signing_command()
314
if command is not None:
316
return self._get_global_config()._gpg_signing_command()
318
def _get_user_id(self):
319
user_id = super(LocationConfig, self)._get_user_id()
320
if user_id is not None:
322
return self._get_global_config()._get_user_id()
324
def _get_user_option(self, option_name):
325
"""See Config._get_user_option."""
326
option_value = super(LocationConfig,
327
self)._get_user_option(option_name)
328
if option_value is not None:
330
return self._get_global_config()._get_user_option(option_name)
332
def _get_signature_checking(self):
333
"""See Config._get_signature_checking."""
334
check = super(LocationConfig, self)._get_signature_checking()
335
if check is not None:
337
return self._get_global_config()._get_signature_checking()
339
def _post_commit(self):
340
"""See Config.post_commit."""
341
hook = self._get_user_option('post_commit')
344
return self._get_global_config()._post_commit()
346
def set_user_option(self, option, value):
588
347
"""Save option and its value in the configuration."""
589
if store not in [STORE_LOCATION,
590
STORE_LOCATION_NORECURSE,
591
STORE_LOCATION_APPENDPATH]:
592
raise ValueError('bad storage policy %r for %r' %
594
348
# FIXME: RBC 20051029 This should refresh the parser and also take a
595
# file lock on locations.conf.
596
conf_dir = os.path.dirname(self._get_filename())
597
ensure_config_dir_exists(conf_dir)
349
# file lock on branches.conf.
350
if not os.path.isdir(os.path.dirname(self._get_filename())):
351
os.mkdir(os.path.dirname(self._get_filename()))
598
352
location = self.location
599
353
if location.endswith('/'):
600
354
location = location[:-1]
604
358
elif location + '/' in self._get_parser():
605
359
location = location + '/'
606
360
self._get_parser()[location][option]=value
607
# the allowed values of store match the config policies
608
self._set_option_policy(location, option, store)
609
self._get_parser().write(file(self._get_filename(), 'wb'))
361
self._get_parser().write()
612
364
class BranchConfig(Config):
613
365
"""A configuration object giving the policy for a branch."""
615
def _get_branch_data_config(self):
616
if self._branch_data_config is None:
617
self._branch_data_config = TreeConfig(self.branch)
618
return self._branch_data_config
620
367
def _get_location_config(self):
621
368
if self._location_config is None:
622
369
self._location_config = LocationConfig(self.branch.base)
623
370
return self._location_config
625
def _get_global_config(self):
626
if self._global_config is None:
627
self._global_config = GlobalConfig()
628
return self._global_config
630
def _get_best_value(self, option_name):
631
"""This returns a user option from local, tree or global config.
633
They are tried in that order. Use get_safe_value if trusted values
636
for source in self.option_sources:
637
value = getattr(source(), option_name)()
638
if value is not None:
642
def _get_safe_value(self, option_name):
643
"""This variant of get_best_value never returns untrusted values.
645
It does not return values from the branch data, because the branch may
646
not be controlled by the user.
648
We may wish to allow locations.conf to control whether branches are
649
trusted in the future.
651
for source in (self._get_location_config, self._get_global_config):
652
value = getattr(source(), option_name)()
653
if value is not None:
657
372
def _get_user_id(self):
658
373
"""Return the full user id for the branch.
660
e.g. "John Hacker <jhacker@example.com>"
375
e.g. "John Hacker <jhacker@foo.org>"
661
376
This is looked up in the email controlfile for the branch.
664
return (self.branch._transport.get_bytes("email")
665
.decode(osutils.get_user_encoding())
379
return (self.branch.controlfile("email", "r")
381
.decode(bzrlib.user_encoding)
667
383
except errors.NoSuchFile, e:
670
return self._get_best_value('_get_user_id')
386
return self._get_location_config()._get_user_id()
672
388
def _get_signature_checking(self):
673
389
"""See Config._get_signature_checking."""
674
return self._get_best_value('_get_signature_checking')
676
def _get_signing_policy(self):
677
"""See Config._get_signing_policy."""
678
return self._get_best_value('_get_signing_policy')
390
return self._get_location_config()._get_signature_checking()
680
392
def _get_user_option(self, option_name):
681
393
"""See Config._get_user_option."""
682
for source in self.option_sources:
683
value = source()._get_user_option(option_name)
684
if value is not None:
688
def set_user_option(self, name, value, store=STORE_BRANCH,
690
if store == STORE_BRANCH:
691
self._get_branch_data_config().set_option(value, name)
692
elif store == STORE_GLOBAL:
693
self._get_global_config().set_user_option(name, value)
695
self._get_location_config().set_user_option(name, value, store)
698
if store in (STORE_GLOBAL, STORE_BRANCH):
699
mask_value = self._get_location_config().get_user_option(name)
700
if mask_value is not None:
701
trace.warning('Value "%s" is masked by "%s" from'
702
' locations.conf', value, mask_value)
704
if store == STORE_GLOBAL:
705
branch_config = self._get_branch_data_config()
706
mask_value = branch_config.get_user_option(name)
707
if mask_value is not None:
708
trace.warning('Value "%s" is masked by "%s" from'
709
' branch.conf', value, mask_value)
394
return self._get_location_config()._get_user_option(option_name)
712
396
def _gpg_signing_command(self):
713
397
"""See Config.gpg_signing_command."""
714
return self._get_safe_value('_gpg_signing_command')
398
return self._get_location_config()._gpg_signing_command()
716
400
def __init__(self, branch):
717
401
super(BranchConfig, self).__init__()
718
402
self._location_config = None
719
self._branch_data_config = None
720
self._global_config = None
721
403
self.branch = branch
722
self.option_sources = (self._get_location_config,
723
self._get_branch_data_config,
724
self._get_global_config)
726
405
def _post_commit(self):
727
406
"""See Config.post_commit."""
728
return self._get_safe_value('_post_commit')
730
def _get_nickname(self):
731
value = self._get_explicit_nickname()
732
if value is not None:
734
return urlutils.unescape(self.branch.base.split('/')[-2])
736
def has_explicit_nickname(self):
737
"""Return true if a nickname has been explicitly assigned."""
738
return self._get_explicit_nickname() is not None
740
def _get_explicit_nickname(self):
741
return self._get_best_value('_get_nickname')
743
def _log_format(self):
744
"""See Config.log_format."""
745
return self._get_best_value('_log_format')
748
def ensure_config_dir_exists(path=None):
749
"""Make sure a configuration directory exists.
750
This makes sure that the directory exists.
751
On windows, since configuration directories are 2 levels deep,
752
it makes sure both the directory and the parent directory exists.
756
if not os.path.isdir(path):
757
if sys.platform == 'win32':
758
parent_dir = os.path.dirname(path)
759
if not os.path.isdir(parent_dir):
760
trace.mutter('creating config parent directory: %r', parent_dir)
762
trace.mutter('creating config directory: %r', path)
407
return self._get_location_config()._post_commit()
766
410
def config_dir():
872
459
except ImportError:
875
user_encoding = osutils.get_user_encoding()
876
realname = username = getpass.getuser().decode(user_encoding)
877
except UnicodeDecodeError:
878
raise errors.BzrError("Can't decode username as %s." % \
461
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
881
463
return realname, (username + '@' + socket.gethostname())
884
def parse_username(username):
885
"""Parse e-mail username and return a (name, address) tuple."""
886
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
888
return (username, '')
890
return (match.group(1), match.group(2))
893
466
def extract_email_address(e):
894
467
"""Return just the address part of an email string.
896
469
That is just the user@domain part, nothing else.
897
470
This part is required to contain only ascii characters.
898
471
If it can't be extracted, raises an error.
900
473
>>> extract_email_address('Jane Tester <jane@test.com>')
903
name, email = parse_username(e)
905
raise errors.NoEmailInUsername(e)
909
class TreeConfig(IniBasedConfig):
476
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
478
raise errors.BzrError("%r doesn't seem to contain "
479
"a reasonable email address" % e)
482
class TreeConfig(object):
910
483
"""Branch configuration data associated with its contents, not location"""
912
# XXX: Really needs a better name, as this is not part of the tree! -- mbp 20080507
914
484
def __init__(self, branch):
915
# XXX: Really this should be asking the branch for its configuration
916
# data, rather than relying on a Transport, so that it can work
917
# more cleanly with a RemoteBranch that has no transport.
918
self._config = TransportConfig(branch._transport, 'branch.conf')
919
485
self.branch = branch
921
def _get_parser(self, file=None):
923
return IniBasedConfig._get_parser(file)
924
return self._config._get_configobj()
487
def _get_config(self):
489
obj = ConfigObj(self.branch.controlfile('branch.conf',
492
except errors.NoSuchFile:
926
496
def get_option(self, name, section=None, default=None):
927
497
self.branch.lock_read()
929
return self._config.get_option(name, section, default)
499
obj = self._get_config()
501
if section is not None:
931
507
self.branch.unlock()
935
511
"""Set a per-branch configuration option"""
936
512
self.branch.lock_write()
938
self._config.set_option(value, name, section)
514
cfg_obj = self._get_config()
519
obj = cfg_obj[section]
521
cfg_obj[section] = {}
522
obj = cfg_obj[section]
524
cfg_obj.encode('UTF-8')
525
out_file = StringIO(''.join([l+'\n' for l in cfg_obj.write()]))
527
self.branch.put_controlfile('branch.conf', out_file, encode=False)
940
529
self.branch.unlock()
943
class AuthenticationConfig(object):
944
"""The authentication configuration file based on a ini file.
946
Implements the authentication.conf file described in
947
doc/developers/authentication-ring.txt.
950
def __init__(self, _file=None):
951
self._config = None # The ConfigObj
953
self._filename = authentication_config_filename()
954
self._input = self._filename = authentication_config_filename()
956
# Tests can provide a string as _file
957
self._filename = None
960
def _get_config(self):
961
if self._config is not None:
964
# FIXME: Should we validate something here ? Includes: empty
965
# sections are useless, at least one of
966
# user/password/password_encoding should be defined, etc.
968
# Note: the encoding below declares that the file itself is utf-8
969
# encoded, but the values in the ConfigObj are always Unicode.
970
self._config = ConfigObj(self._input, encoding='utf-8')
971
except configobj.ConfigObjError, e:
972
raise errors.ParseConfigError(e.errors, e.config.filename)
976
"""Save the config file, only tests should use it for now."""
977
conf_dir = os.path.dirname(self._filename)
978
ensure_config_dir_exists(conf_dir)
979
self._get_config().write(file(self._filename, 'wb'))
981
def _set_option(self, section_name, option_name, value):
982
"""Set an authentication configuration option"""
983
conf = self._get_config()
984
section = conf.get(section_name)
987
section = conf[section]
988
section[option_name] = value
991
def get_credentials(self, scheme, host, port=None, user=None, path=None):
992
"""Returns the matching credentials from authentication.conf file.
994
:param scheme: protocol
996
:param host: the server address
998
:param port: the associated port (optional)
1000
:param user: login (optional)
1002
:param path: the absolute path on the server (optional)
1004
:return: A dict containing the matching credentials or None.
1006
- name: the section name of the credentials in the
1007
authentication.conf file,
1008
- user: can't de different from the provided user if any,
1009
- password: the decoded password, could be None if the credential
1010
defines only the user
1011
- verify_certificates: https specific, True if the server
1012
certificate should be verified, False otherwise.
1015
for auth_def_name, auth_def in self._get_config().items():
1016
if type(auth_def) is not configobj.Section:
1017
raise ValueError("%s defined outside a section" % auth_def_name)
1019
a_scheme, a_host, a_user, a_path = map(
1020
auth_def.get, ['scheme', 'host', 'user', 'path'])
1023
a_port = auth_def.as_int('port')
1027
raise ValueError("'port' not numeric in %s" % auth_def_name)
1029
a_verify_certificates = auth_def.as_bool('verify_certificates')
1031
a_verify_certificates = True
1034
"'verify_certificates' not boolean in %s" % auth_def_name)
1037
if a_scheme is not None and scheme != a_scheme:
1039
if a_host is not None:
1040
if not (host == a_host
1041
or (a_host.startswith('.') and host.endswith(a_host))):
1043
if a_port is not None and port != a_port:
1045
if (a_path is not None and path is not None
1046
and not path.startswith(a_path)):
1048
if (a_user is not None and user is not None
1049
and a_user != user):
1050
# Never contradict the caller about the user to be used
1055
credentials = dict(name=auth_def_name,
1057
password=auth_def.get('password', None),
1058
verify_certificates=a_verify_certificates)
1059
self.decode_password(credentials,
1060
auth_def.get('password_encoding', None))
1061
if 'auth' in debug.debug_flags:
1062
trace.mutter("Using authentication section: %r", auth_def_name)
1067
def set_credentials(self, name, host, user, scheme=None, password=None,
1068
port=None, path=None, verify_certificates=None):
1069
"""Set authentication credentials for a host.
1071
Any existing credentials with matching scheme, host, port and path
1072
will be deleted, regardless of name.
1074
:param name: An arbitrary name to describe this set of credentials.
1075
:param host: Name of the host that accepts these credentials.
1076
:param user: The username portion of these credentials.
1077
:param scheme: The URL scheme (e.g. ssh, http) the credentials apply
1079
:param password: Password portion of these credentials.
1080
:param port: The IP port on the host that these credentials apply to.
1081
:param path: A filesystem path on the host that these credentials
1083
:param verify_certificates: On https, verify server certificates if
1086
values = {'host': host, 'user': user}
1087
if password is not None:
1088
values['password'] = password
1089
if scheme is not None:
1090
values['scheme'] = scheme
1091
if port is not None:
1092
values['port'] = '%d' % port
1093
if path is not None:
1094
values['path'] = path
1095
if verify_certificates is not None:
1096
values['verify_certificates'] = str(verify_certificates)
1097
config = self._get_config()
1099
for section, existing_values in config.items():
1100
for key in ('scheme', 'host', 'port', 'path'):
1101
if existing_values.get(key) != values.get(key):
1105
config.update({name: values})
1108
def get_user(self, scheme, host, port=None,
1109
realm=None, path=None, prompt=None):
1110
"""Get a user from authentication file.
1112
:param scheme: protocol
1114
:param host: the server address
1116
:param port: the associated port (optional)
1118
:param realm: the realm sent by the server (optional)
1120
:param path: the absolute path on the server (optional)
1122
:return: The found user.
1124
credentials = self.get_credentials(scheme, host, port, user=None,
1126
if credentials is not None:
1127
user = credentials['user']
1132
def get_password(self, scheme, host, user, port=None,
1133
realm=None, path=None, prompt=None):
1134
"""Get a password from authentication file or prompt the user for one.
1136
:param scheme: protocol
1138
:param host: the server address
1140
:param port: the associated port (optional)
1144
:param realm: the realm sent by the server (optional)
1146
:param path: the absolute path on the server (optional)
1148
:return: The found password or the one entered by the user.
1150
credentials = self.get_credentials(scheme, host, port, user, path)
1151
if credentials is not None:
1152
password = credentials['password']
1153
if password is not None and scheme is 'ssh':
1154
trace.warning('password ignored in section [%s],'
1155
' use an ssh agent instead'
1156
% credentials['name'])
1160
# Prompt user only if we could't find a password
1161
if password is None:
1163
# Create a default prompt suitable for most cases
1164
prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
1165
# Special handling for optional fields in the prompt
1166
if port is not None:
1167
prompt_host = '%s:%d' % (host, port)
1170
password = ui.ui_factory.get_password(prompt,
1171
host=prompt_host, user=user)
1174
def decode_password(self, credentials, encoding):
1178
class BzrDirConfig(object):
1180
def __init__(self, transport):
1181
self._config = TransportConfig(transport, 'control.conf')
1183
def set_default_stack_on(self, value):
1184
"""Set the default stacking location.
1186
It may be set to a location, or None.
1188
This policy affects all branches contained by this bzrdir, except for
1189
those under repositories.
1192
self._config.set_option('', 'default_stack_on')
1194
self._config.set_option(value, 'default_stack_on')
1196
def get_default_stack_on(self):
1197
"""Return the default stacking location.
1199
This will either be a location, or None.
1201
This policy affects all branches contained by this bzrdir, except for
1202
those under repositories.
1204
value = self._config.get_option('default_stack_on')
1210
class TransportConfig(object):
1211
"""A Config that reads/writes a config file on a Transport.
1213
It is a low-level object that considers config data to be name/value pairs
1214
that may be associated with a section. Assigning meaning to the these
1215
values is done at higher levels like TreeConfig.
1218
def __init__(self, transport, filename):
1219
self._transport = transport
1220
self._filename = filename
1222
def get_option(self, name, section=None, default=None):
1223
"""Return the value associated with a named option.
1225
:param name: The name of the value
1226
:param section: The section the option is in (if any)
1227
:param default: The value to return if the value is not set
1228
:return: The value or default value
1230
configobj = self._get_configobj()
1232
section_obj = configobj
1235
section_obj = configobj[section]
1238
return section_obj.get(name, default)
1240
def set_option(self, value, name, section=None):
1241
"""Set the value associated with a named option.
1243
:param value: The value to set
1244
:param name: The name of the value to set
1245
:param section: The section the option is in (if any)
1247
configobj = self._get_configobj()
1249
configobj[name] = value
1251
configobj.setdefault(section, {})[name] = value
1252
self._set_configobj(configobj)
1254
def _get_configobj(self):
1256
return ConfigObj(self._transport.get(self._filename),
1258
except errors.NoSuchFile:
1259
return ConfigObj(encoding='utf-8')
1261
def _set_configobj(self, configobj):
1262
out_file = StringIO()
1263
configobj.write(out_file)
1265
self._transport.put_file(self._filename, out_file)