181
194
"""Get a generic option as a boolean - no special process, no default.
183
196
:return None if the option doesn't exist or its value can't be
184
interpreted as a boolean. Returns True or False ortherwise.
197
interpreted as a boolean. Returns True or False otherwise.
186
199
s = self._get_user_option(option_name)
187
return ui.bool_from_string(s)
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 ','
189
222
def gpg_signing_command(self):
190
223
"""What program should be used to sign signatures?"""
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:
308
355
class IniBasedConfig(Config):
309
356
"""A configuration policy that draws from ini files."""
311
def __init__(self, get_filename):
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.
312
364
super(IniBasedConfig, self).__init__()
313
self._get_filename = get_filename
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
314
377
self._parser = None
316
def _get_parser(self, file=None):
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):
317
402
if self._parser is not None:
318
403
return self._parser
320
input = self._get_filename()
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
324
self._parser = ConfigObj(input, encoding='utf-8')
417
self._parser = ConfigObj(co_input, encoding='utf-8')
325
418
except configobj.ConfigObjError, e:
326
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
327
422
return self._parser
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()
329
431
def _get_matching_sections(self):
330
432
"""Return an ordered list of (section_name, extra_path) pairs.
431
536
def _get_nickname(self):
432
537
return self.get_user_option('nickname')
435
class GlobalConfig(IniBasedConfig):
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):
436
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)
438
634
def get_editor(self):
439
635
return self._get_user_option('editor')
442
super(GlobalConfig, self).__init__(config_filename)
444
638
def set_user_option(self, option, value):
445
639
"""Save option and its value in the configuration."""
446
640
self._set_option(option, value, 'DEFAULT')
465
662
self._write_config_file()
467
664
def _set_option(self, option, value, section):
468
# FIXME: RBC 20051029 This should refresh the parser and also take a
469
# file lock on bazaar.conf.
470
conf_dir = os.path.dirname(self._get_filename())
471
ensure_config_dir_exists(conf_dir)
472
666
self._get_parser().setdefault(section, {})[option] = value
473
667
self._write_config_file()
475
def _write_config_file(self):
476
f = open(self._get_filename(), 'wb')
477
self._get_parser().write(f)
481
class LocationConfig(IniBasedConfig):
670
class LocationConfig(LockableConfig):
482
671
"""A configuration object that gives the policy for a location."""
484
673
def __init__(self, location):
485
name_generator = locations_config_filename
486
if (not os.path.exists(name_generator()) and
487
os.path.exists(branches_config_filename())):
488
if sys.platform == 'win32':
489
trace.warning('Please rename %s to %s'
490
% (branches_config_filename(),
491
locations_config_filename()))
493
trace.warning('Please rename ~/.bazaar/branches.conf'
494
' to ~/.bazaar/locations.conf')
495
name_generator = branches_config_filename
496
super(LocationConfig, self).__init__(name_generator)
674
super(LocationConfig, self).__init__(
675
file_name=locations_config_filename())
497
676
# local file locations are looked up by local path, rather than
498
677
# by file url. This is because the config file is a user
499
678
# file, and we would rather not expose the user to file urls.
501
680
location = urlutils.local_path_from_url(location)
502
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)
504
698
def _get_matching_sections(self):
505
699
"""Return an ordered list of section names matching this location."""
506
700
sections = self._get_parser()
601
796
STORE_LOCATION_APPENDPATH]:
602
797
raise ValueError('bad storage policy %r for %r' %
604
# FIXME: RBC 20051029 This should refresh the parser and also take a
605
# file lock on locations.conf.
606
conf_dir = os.path.dirname(self._get_filename())
607
ensure_config_dir_exists(conf_dir)
608
800
location = self.location
609
801
if location.endswith('/'):
610
802
location = location[:-1]
611
if (not location in self._get_parser() and
612
not location + '/' in self._get_parser()):
613
self._get_parser()[location]={}
614
elif location + '/' in self._get_parser():
803
parser = self._get_parser()
804
if not location in parser and not location + '/' in parser:
805
parser[location] = {}
806
elif location + '/' in parser:
615
807
location = location + '/'
616
self._get_parser()[location][option]=value
808
parser[location][option]=value
617
809
# the allowed values of store match the config policies
618
810
self._set_option_policy(location, option, store)
619
self._get_parser().write(file(self._get_filename(), 'wb'))
811
self._write_config_file()
622
814
class BranchConfig(Config):
623
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)
625
827
def _get_branch_data_config(self):
626
828
if self._branch_data_config is None:
627
829
self._branch_data_config = TreeConfig(self.branch)
722
927
"""See Config.gpg_signing_command."""
723
928
return self._get_safe_value('_gpg_signing_command')
725
def __init__(self, branch):
726
super(BranchConfig, self).__init__()
727
self._location_config = None
728
self._branch_data_config = None
729
self._global_config = None
731
self.option_sources = (self._get_location_config,
732
self._get_branch_data_config,
733
self._get_global_config)
735
930
def _post_commit(self):
736
931
"""See Config.post_commit."""
737
932
return self._get_safe_value('_post_commit')
821
1011
return osutils.pathjoin(config_dir(), 'ignore')
825
"""Calculate automatic user identification.
827
Returns (realname, email).
829
Only used when none is set in the environment or the id file.
831
This previously used the FQDN as the default domain, but that can
832
be very slow on machines where DNS is broken. So now we simply
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
837
1023
if sys.platform == 'win32':
838
name = win32utils.get_user_name_unicode()
840
raise errors.BzrError("Cannot autodetect user name.\n"
841
"Please, set your name with command like:\n"
842
'bzr whoami "Your Name <name@domain.com>"')
843
host = win32utils.get_host_name_unicode()
845
host = socket.gethostname()
846
return name, (name + '@' + host)
852
w = pwd.getpwuid(uid)
854
raise errors.BzrCommandError('Unable to determine your name. '
855
'Please use "bzr whoami" to set it.')
857
# we try utf-8 first, because on many variants (like Linux),
858
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
859
# false positives. (many users will have their user encoding set to
860
# latin-1, which cannot raise UnicodeError.)
862
gecos = w.pw_gecos.decode('utf-8')
866
encoding = osutils.get_user_encoding()
867
gecos = w.pw_gecos.decode(encoding)
869
raise errors.BzrCommandError('Unable to determine your name. '
870
'Use "bzr whoami" to set it.')
872
username = w.pw_name.decode(encoding)
874
raise errors.BzrCommandError('Unable to determine your name. '
875
'Use "bzr whoami" to set it.')
877
comma = gecos.find(',')
881
realname = gecos[:comma]
888
user_encoding = osutils.get_user_encoding()
889
realname = username = getpass.getuser().decode(user_encoding)
890
except UnicodeDecodeError:
891
raise errors.BzrError("Can't decode username as %s." % \
894
return realname, (username + '@' + socket.gethostname())
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')
897
1041
def parse_username(username):