50
49
create_signatures - this option controls whether bzr will always create
51
50
gpg signatures, never create them, or create them if the
52
51
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
52
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
68
from bzrlib.lazy_import import lazy_import
69
lazy_import(globals(), """
71
61
from fnmatch import fnmatch
73
from cStringIO import StringIO
87
from bzrlib.util.configobj import configobj
65
import bzrlib.errors as errors
66
from bzrlib.osutils import pathjoin
67
from bzrlib.trace import mutter
68
import bzrlib.util.configobj.configobj as configobj
69
from StringIO import StringIO
91
71
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)
76
class ConfigObj(configobj.ConfigObj):
78
def get_bool(self, section, key):
79
return self[section].as_bool(key)
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')
206
self._parser = ConfigObj(input)
310
207
except configobj.ConfigObjError, e:
311
208
raise errors.ParseConfigError(e.errors, e.config.filename)
312
209
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
211
def _get_section(self):
327
212
"""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
215
def _get_signature_checking(self):
335
216
"""See Config._get_signature_checking."""
336
217
policy = self._get_user_option('check_signatures')
338
219
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
221
def _get_user_id(self):
347
222
"""Get the user id from the 'email' key in the current section."""
348
223
return self._get_user_option('email')
350
225
def _get_user_option(self, option_name):
351
226
"""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)
228
return self._get_parser().get_value(self._get_section(),
375
233
def _gpg_signing_command(self):
376
234
"""See Config.gpg_signing_command."""
431
268
def __init__(self):
432
269
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
272
class LocationConfig(IniBasedConfig):
472
273
"""A configuration object that gives the policy for a location."""
474
275
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)
276
super(LocationConfig, self).__init__(branches_config_filename)
277
self._global_config = None
492
278
self.location = location
494
def _get_matching_sections(self):
495
"""Return an ordered list of section names matching this location."""
280
def _get_global_config(self):
281
if self._global_config is None:
282
self._global_config = GlobalConfig()
283
return self._global_config
285
def _get_section(self):
286
"""Get the section we should look in for config items.
288
Returns None if none exists.
289
TODO: perhaps return a NullSection that thunks through to the
496
292
sections = self._get_parser()
497
293
location_names = self.location.split('/')
498
294
if self.location.endswith('/'):
499
295
del location_names[-1]
501
297
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('/')
298
section_names = section.split('/')
511
299
if section.endswith('/'):
512
300
del section_names[-1]
513
301
names = zip(location_names, section_names)
522
310
# if section is longer, no match.
523
311
if len(section_names) > len(location_names):
525
matches.append((len(section_names), section,
526
'/'.join(location_names[len(section_names):])))
313
# if path is longer, and recurse is not true, no match
314
if len(section_names) < len(location_names):
316
if not self._get_parser().get_bool(section, 'recurse'):
320
matches.append((len(section_names), section))
527
323
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):
326
def _gpg_signing_command(self):
327
"""See Config.gpg_signing_command."""
328
command = super(LocationConfig, self)._gpg_signing_command()
329
if command is not None:
331
return self._get_global_config()._gpg_signing_command()
333
def _log_format(self):
334
"""See Config.log_format."""
335
command = super(LocationConfig, self)._log_format()
336
if command is not None:
338
return self._get_global_config()._log_format()
340
def _get_user_id(self):
341
user_id = super(LocationConfig, self)._get_user_id()
342
if user_id is not None:
344
return self._get_global_config()._get_user_id()
346
def _get_user_option(self, option_name):
347
"""See Config._get_user_option."""
348
option_value = super(LocationConfig,
349
self)._get_user_option(option_name)
350
if option_value is not None:
352
return self._get_global_config()._get_user_option(option_name)
354
def _get_signature_checking(self):
355
"""See Config._get_signature_checking."""
356
check = super(LocationConfig, self)._get_signature_checking()
357
if check is not None:
359
return self._get_global_config()._get_signature_checking()
361
def _post_commit(self):
362
"""See Config.post_commit."""
363
hook = self._get_user_option('post_commit')
366
return self._get_global_config()._post_commit()
368
def set_user_option(self, option, value):
588
369
"""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
370
# FIXME: RBC 20051029 This should refresh the parser and also take a
595
# file lock on locations.conf.
371
# file lock on branches.conf.
596
372
conf_dir = os.path.dirname(self._get_filename())
597
373
ensure_config_dir_exists(conf_dir)
598
374
location = self.location
604
380
elif location + '/' in self._get_parser():
605
381
location = location + '/'
606
382
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'))
383
self._get_parser().write()
612
386
class BranchConfig(Config):
613
387
"""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
389
def _get_location_config(self):
621
390
if self._location_config is None:
622
391
self._location_config = LocationConfig(self.branch.base)
623
392
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
394
def _get_user_id(self):
658
395
"""Return the full user id for the branch.
660
e.g. "John Hacker <jhacker@example.com>"
397
e.g. "John Hacker <jhacker@foo.org>"
661
398
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())
401
return (self.branch.control_files.get_utf8("email")
403
.decode(bzrlib.user_encoding)
667
405
except errors.NoSuchFile, e:
670
return self._get_best_value('_get_user_id')
408
return self._get_location_config()._get_user_id()
672
410
def _get_signature_checking(self):
673
411
"""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')
412
return self._get_location_config()._get_signature_checking()
680
414
def _get_user_option(self, option_name):
681
415
"""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)
416
return self._get_location_config()._get_user_option(option_name)
712
418
def _gpg_signing_command(self):
713
419
"""See Config.gpg_signing_command."""
714
return self._get_safe_value('_gpg_signing_command')
420
return self._get_location_config()._gpg_signing_command()
716
422
def __init__(self, branch):
717
423
super(BranchConfig, self).__init__()
718
424
self._location_config = None
719
self._branch_data_config = None
720
self._global_config = None
721
425
self.branch = branch
722
self.option_sources = (self._get_location_config,
723
self._get_branch_data_config,
724
self._get_global_config)
726
427
def _post_commit(self):
727
428
"""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')
429
return self._get_location_config()._post_commit()
743
431
def _log_format(self):
744
432
"""See Config.log_format."""
745
return self._get_best_value('_log_format')
433
return self._get_location_config()._log_format()
748
435
def ensure_config_dir_exists(path=None):
749
436
"""Make sure a configuration directory exists.
773
460
base = os.environ.get('BZR_HOME', None)
774
461
if sys.platform == 'win32':
776
base = win32utils.get_appdata_location_unicode()
463
base = os.environ.get('APPDATA', None)
778
465
base = os.environ.get('HOME', None)
780
raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
782
return osutils.pathjoin(base, 'bazaar', '2.0')
467
raise BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
468
return pathjoin(base, 'bazaar', '2.0')
784
470
# cygwin, linux, and darwin all have a $HOME directory
786
472
base = os.path.expanduser("~")
787
return osutils.pathjoin(base, ".bazaar")
473
return pathjoin(base, ".bazaar")
790
476
def config_filename():
791
477
"""Return per-user configuration ini file filename."""
792
return osutils.pathjoin(config_dir(), 'bazaar.conf')
478
return pathjoin(config_dir(), 'bazaar.conf')
795
481
def branches_config_filename():
796
482
"""Return per-user configuration ini file filename."""
797
return osutils.pathjoin(config_dir(), 'branches.conf')
800
def locations_config_filename():
801
"""Return per-user configuration ini file filename."""
802
return osutils.pathjoin(config_dir(), 'locations.conf')
805
def authentication_config_filename():
806
"""Return per-user authentication ini file filename."""
807
return osutils.pathjoin(config_dir(), 'authentication.conf')
810
def user_ignore_config_filename():
811
"""Return the user default ignore filename"""
812
return osutils.pathjoin(config_dir(), 'ignore')
483
return pathjoin(config_dir(), 'branches.conf')
815
486
def _auto_user_id():
872
515
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." % \
517
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
881
519
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
522
def extract_email_address(e):
894
523
"""Return just the address part of an email string.
896
525
That is just the user@domain part, nothing else.
897
526
This part is required to contain only ascii characters.
898
527
If it can't be extracted, raises an error.
900
529
>>> extract_email_address('Jane Tester <jane@test.com>')
903
name, email = parse_username(e)
905
raise errors.NoEmailInUsername(e)
909
class TreeConfig(IniBasedConfig):
532
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
534
raise errors.BzrError("%r doesn't seem to contain "
535
"a reasonable email address" % e)
538
class TreeConfig(object):
910
539
"""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
540
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
541
self.branch = branch
921
def _get_parser(self, file=None):
923
return IniBasedConfig._get_parser(file)
924
return self._config._get_configobj()
543
def _get_config(self):
545
obj = ConfigObj(self.branch.control_files.get('branch.conf'),
547
except errors.NoSuchFile:
548
obj = ConfigObj(encoding='utf=8')
926
551
def get_option(self, name, section=None, default=None):
927
552
self.branch.lock_read()
929
return self._config.get_option(name, section, default)
554
obj = self._get_config()
556
if section is not None:
931
562
self.branch.unlock()
935
566
"""Set a per-branch configuration option"""
936
567
self.branch.lock_write()
938
self._config.set_option(value, name, section)
569
cfg_obj = self._get_config()
574
obj = cfg_obj[section]
576
cfg_obj[section] = {}
577
obj = cfg_obj[section]
579
out_file = StringIO()
580
cfg_obj.write(out_file)
582
self.branch.control_files.put('branch.conf', out_file)
940
584
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 get_user(self, scheme, host, port=None,
1068
realm=None, path=None, prompt=None):
1069
"""Get a user from authentication file.
1071
:param scheme: protocol
1073
:param host: the server address
1075
:param port: the associated port (optional)
1077
:param realm: the realm sent by the server (optional)
1079
:param path: the absolute path on the server (optional)
1081
:return: The found user.
1083
credentials = self.get_credentials(scheme, host, port, user=None,
1085
if credentials is not None:
1086
user = credentials['user']
1091
def get_password(self, scheme, host, user, port=None,
1092
realm=None, path=None, prompt=None):
1093
"""Get a password from authentication file or prompt the user for one.
1095
:param scheme: protocol
1097
:param host: the server address
1099
:param port: the associated port (optional)
1103
:param realm: the realm sent by the server (optional)
1105
:param path: the absolute path on the server (optional)
1107
:return: The found password or the one entered by the user.
1109
credentials = self.get_credentials(scheme, host, port, user, path)
1110
if credentials is not None:
1111
password = credentials['password']
1112
if password is not None and scheme is 'ssh':
1113
trace.warning('password ignored in section [%s],'
1114
' use an ssh agent instead'
1115
% credentials['name'])
1119
# Prompt user only if we could't find a password
1120
if password is None:
1122
# Create a default prompt suitable for most cases
1123
prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
1124
# Special handling for optional fields in the prompt
1125
if port is not None:
1126
prompt_host = '%s:%d' % (host, port)
1129
password = ui.ui_factory.get_password(prompt,
1130
host=prompt_host, user=user)
1133
def decode_password(self, credentials, encoding):
1137
class BzrDirConfig(object):
1139
def __init__(self, transport):
1140
self._config = TransportConfig(transport, 'control.conf')
1142
def set_default_stack_on(self, value):
1143
"""Set the default stacking location.
1145
It may be set to a location, or None.
1147
This policy affects all branches contained by this bzrdir, except for
1148
those under repositories.
1151
self._config.set_option('', 'default_stack_on')
1153
self._config.set_option(value, 'default_stack_on')
1155
def get_default_stack_on(self):
1156
"""Return the default stacking location.
1158
This will either be a location, or None.
1160
This policy affects all branches contained by this bzrdir, except for
1161
those under repositories.
1163
value = self._config.get_option('default_stack_on')
1169
class TransportConfig(object):
1170
"""A Config that reads/writes a config file on a Transport.
1172
It is a low-level object that considers config data to be name/value pairs
1173
that may be associated with a section. Assigning meaning to the these
1174
values is done at higher levels like TreeConfig.
1177
def __init__(self, transport, filename):
1178
self._transport = transport
1179
self._filename = filename
1181
def get_option(self, name, section=None, default=None):
1182
"""Return the value associated with a named option.
1184
:param name: The name of the value
1185
:param section: The section the option is in (if any)
1186
:param default: The value to return if the value is not set
1187
:return: The value or default value
1189
configobj = self._get_configobj()
1191
section_obj = configobj
1194
section_obj = configobj[section]
1197
return section_obj.get(name, default)
1199
def set_option(self, value, name, section=None):
1200
"""Set the value associated with a named option.
1202
:param value: The value to set
1203
:param name: The name of the value to set
1204
:param section: The section the option is in (if any)
1206
configobj = self._get_configobj()
1208
configobj[name] = value
1210
configobj.setdefault(section, {})[name] = value
1211
self._set_configobj(configobj)
1213
def _get_configobj(self):
1215
return ConfigObj(self._transport.get(self._filename),
1217
except errors.NoSuchFile:
1218
return ConfigObj(encoding='utf-8')
1220
def _set_configobj(self, configobj):
1221
out_file = StringIO()
1222
configobj.write(out_file)
1224
self._transport.put_file(self._filename, out_file)