~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

Revert the dirstate/transform changes, so we have a pure 'lstat/fstat' change.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#            and others
4
4
#
63
63
"""
64
64
 
65
65
import os
 
66
import string
66
67
import sys
67
68
 
 
69
from bzrlib import commands
 
70
from bzrlib.decorators import needs_write_lock
68
71
from bzrlib.lazy_import import lazy_import
69
72
lazy_import(globals(), """
70
73
import errno
71
 
from fnmatch import fnmatch
 
74
import fnmatch
72
75
import re
73
76
from cStringIO import StringIO
74
77
 
75
78
import bzrlib
76
79
from bzrlib import (
 
80
    atomicfile,
 
81
    bzrdir,
77
82
    debug,
78
83
    errors,
 
84
    lockdir,
79
85
    mail_client,
 
86
    mergetools,
80
87
    osutils,
81
88
    registry,
82
89
    symbol_versioning,
83
90
    trace,
 
91
    transport,
84
92
    ui,
85
93
    urlutils,
86
94
    win32utils,
122
130
STORE_BRANCH = 3
123
131
STORE_GLOBAL = 4
124
132
 
125
 
_ConfigObj = None
126
 
def ConfigObj(*args, **kwargs):
127
 
    global _ConfigObj
128
 
    if _ConfigObj is None:
129
 
        class ConfigObj(configobj.ConfigObj):
130
 
 
131
 
            def get_bool(self, section, key):
132
 
                return self[section].as_bool(key)
133
 
 
134
 
            def get_value(self, section, name):
135
 
                # Try [] for the old DEFAULT section.
136
 
                if section == "DEFAULT":
137
 
                    try:
138
 
                        return self[name]
139
 
                    except KeyError:
140
 
                        pass
141
 
                return self[section][name]
142
 
        _ConfigObj = ConfigObj
143
 
    return _ConfigObj(*args, **kwargs)
 
133
 
 
134
class ConfigObj(configobj.ConfigObj):
 
135
 
 
136
    def __init__(self, infile=None, **kwargs):
 
137
        # We define our own interpolation mechanism calling it option expansion
 
138
        super(ConfigObj, self).__init__(infile=infile,
 
139
                                        interpolation=False,
 
140
                                        **kwargs)
 
141
 
 
142
 
 
143
    def get_bool(self, section, key):
 
144
        return self[section].as_bool(key)
 
145
 
 
146
    def get_value(self, section, name):
 
147
        # Try [] for the old DEFAULT section.
 
148
        if section == "DEFAULT":
 
149
            try:
 
150
                return self[name]
 
151
            except KeyError:
 
152
                pass
 
153
        return self[section][name]
 
154
 
 
155
 
 
156
# FIXME: Until we can guarantee that each config file is loaded once and and
 
157
# only once for a given bzrlib session, we don't want to re-read the file every
 
158
# time we query for an option so we cache the value (bad ! watch out for tests
 
159
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
 
160
# yell at mgz^W vila and the RM if this is still present at that time
 
161
# -- vila 20110219
 
162
_expand_default_value = None
 
163
def _get_expand_default_value():
 
164
    global _expand_default_value
 
165
    if _expand_default_value is not None:
 
166
        return _expand_default_value
 
167
    conf = GlobalConfig()
 
168
    # Note that we must not use None for the expand value below or we'll run
 
169
    # into infinite recursion. Using False really would be quite silly ;)
 
170
    expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
 
171
    if expand is None:
 
172
        # This is an opt-in feature, you *really* need to clearly say you want
 
173
        # to activate it !
 
174
        expand = False
 
175
    _expand_default_value = expand
 
176
    return expand
144
177
 
145
178
 
146
179
class Config(object):
149
182
    def __init__(self):
150
183
        super(Config, self).__init__()
151
184
 
 
185
    def config_id(self):
 
186
        """Returns a unique ID for the config."""
 
187
        raise NotImplementedError(self.config_id)
 
188
 
152
189
    def get_editor(self):
153
190
        """Get the users pop up editor."""
154
191
        raise NotImplementedError
178
215
    def _get_signing_policy(self):
179
216
        """Template method to override signature creation policy."""
180
217
 
 
218
    option_ref_re = None
 
219
 
 
220
    def expand_options(self, string, env=None):
 
221
        """Expand option references in the string in the configuration context.
 
222
 
 
223
        :param string: The string containing option to expand.
 
224
 
 
225
        :param env: An option dict defining additional configuration options or
 
226
            overriding existing ones.
 
227
 
 
228
        :returns: The expanded string.
 
229
        """
 
230
        return self._expand_options_in_string(string, env)
 
231
 
 
232
    def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
 
233
        """Expand options in  a list of strings in the configuration context.
 
234
 
 
235
        :param slist: A list of strings.
 
236
 
 
237
        :param env: An option dict defining additional configuration options or
 
238
            overriding existing ones.
 
239
 
 
240
        :param _ref_stack: Private list containing the options being
 
241
            expanded to detect loops.
 
242
 
 
243
        :returns: The flatten list of expanded strings.
 
244
        """
 
245
        # expand options in each value separately flattening lists
 
246
        result = []
 
247
        for s in slist:
 
248
            value = self._expand_options_in_string(s, env, _ref_stack)
 
249
            if isinstance(value, list):
 
250
                result.extend(value)
 
251
            else:
 
252
                result.append(value)
 
253
        return result
 
254
 
 
255
    def _expand_options_in_string(self, string, env=None, _ref_stack=None):
 
256
        """Expand options in the string in the configuration context.
 
257
 
 
258
        :param string: The string to be expanded.
 
259
 
 
260
        :param env: An option dict defining additional configuration options or
 
261
            overriding existing ones.
 
262
 
 
263
        :param _ref_stack: Private list containing the options being
 
264
            expanded to detect loops.
 
265
 
 
266
        :returns: The expanded string.
 
267
        """
 
268
        if string is None:
 
269
            # Not much to expand there
 
270
            return None
 
271
        if _ref_stack is None:
 
272
            # What references are currently resolved (to detect loops)
 
273
            _ref_stack = []
 
274
        if self.option_ref_re is None:
 
275
            # We want to match the most embedded reference first (i.e. for
 
276
            # '{{foo}}' we will get '{foo}',
 
277
            # for '{bar{baz}}' we will get '{baz}'
 
278
            self.option_ref_re = re.compile('({[^{}]+})')
 
279
        result = string
 
280
        # We need to iterate until no more refs appear ({{foo}} will need two
 
281
        # iterations for example).
 
282
        while True:
 
283
            raw_chunks = self.option_ref_re.split(result)
 
284
            if len(raw_chunks) == 1:
 
285
                # Shorcut the trivial case: no refs
 
286
                return result
 
287
            chunks = []
 
288
            list_value = False
 
289
            # Split will isolate refs so that every other chunk is a ref
 
290
            chunk_is_ref = False
 
291
            for chunk in raw_chunks:
 
292
                if not chunk_is_ref:
 
293
                    if chunk:
 
294
                        # Keep only non-empty strings (or we get bogus empty
 
295
                        # slots when a list value is involved).
 
296
                        chunks.append(chunk)
 
297
                    chunk_is_ref = True
 
298
                else:
 
299
                    name = chunk[1:-1]
 
300
                    if name in _ref_stack:
 
301
                        raise errors.OptionExpansionLoop(string, _ref_stack)
 
302
                    _ref_stack.append(name)
 
303
                    value = self._expand_option(name, env, _ref_stack)
 
304
                    if value is None:
 
305
                        raise errors.ExpandingUnknownOption(name, string)
 
306
                    if isinstance(value, list):
 
307
                        list_value = True
 
308
                        chunks.extend(value)
 
309
                    else:
 
310
                        chunks.append(value)
 
311
                    _ref_stack.pop()
 
312
                    chunk_is_ref = False
 
313
            if list_value:
 
314
                # Once a list appears as the result of an expansion, all
 
315
                # callers will get a list result. This allows a consistent
 
316
                # behavior even when some options in the expansion chain
 
317
                # defined as strings (no comma in their value) but their
 
318
                # expanded value is a list.
 
319
                return self._expand_options_in_list(chunks, env, _ref_stack)
 
320
            else:
 
321
                result = ''.join(chunks)
 
322
        return result
 
323
 
 
324
    def _expand_option(self, name, env, _ref_stack):
 
325
        if env is not None and name in env:
 
326
            # Special case, values provided in env takes precedence over
 
327
            # anything else
 
328
            value = env[name]
 
329
        else:
 
330
            # FIXME: This is a limited implementation, what we really need is a
 
331
            # way to query the bzr config for the value of an option,
 
332
            # respecting the scope rules (That is, once we implement fallback
 
333
            # configs, getting the option value should restart from the top
 
334
            # config, not the current one) -- vila 20101222
 
335
            value = self.get_user_option(name, expand=False)
 
336
            if isinstance(value, list):
 
337
                value = self._expand_options_in_list(value, env, _ref_stack)
 
338
            else:
 
339
                value = self._expand_options_in_string(value, env, _ref_stack)
 
340
        return value
 
341
 
181
342
    def _get_user_option(self, option_name):
182
343
        """Template method to provide a user option."""
183
344
        return None
184
345
 
185
 
    def get_user_option(self, option_name):
186
 
        """Get a generic option - no special process, no default."""
187
 
        return self._get_user_option(option_name)
188
 
 
189
 
    def get_user_option_as_bool(self, option_name):
 
346
    def get_user_option(self, option_name, expand=None):
 
347
        """Get a generic option - no special process, no default.
 
348
 
 
349
        :param option_name: The queried option.
 
350
 
 
351
        :param expand: Whether options references should be expanded.
 
352
 
 
353
        :returns: The value of the option.
 
354
        """
 
355
        if expand is None:
 
356
            expand = _get_expand_default_value()
 
357
        value = self._get_user_option(option_name)
 
358
        if expand:
 
359
            if isinstance(value, list):
 
360
                value = self._expand_options_in_list(value)
 
361
            elif isinstance(value, dict):
 
362
                trace.warning('Cannot expand "%s":'
 
363
                              ' Dicts do not support option expansion'
 
364
                              % (option_name,))
 
365
            else:
 
366
                value = self._expand_options_in_string(value)
 
367
        return value
 
368
 
 
369
    def get_user_option_as_bool(self, option_name, expand=None):
190
370
        """Get a generic option as a boolean - no special process, no default.
191
371
 
192
372
        :return None if the option doesn't exist or its value can't be
193
373
            interpreted as a boolean. Returns True or False otherwise.
194
374
        """
195
 
        s = self._get_user_option(option_name)
 
375
        s = self.get_user_option(option_name, expand=expand)
196
376
        if s is None:
197
377
            # The option doesn't exist
198
378
            return None
203
383
                          s, option_name)
204
384
        return val
205
385
 
206
 
    def get_user_option_as_list(self, option_name):
 
386
    def get_user_option_as_list(self, option_name, expand=None):
207
387
        """Get a generic option as a list - no special process, no default.
208
388
 
209
389
        :return None if the option doesn't exist. Returns the value as a list
210
390
            otherwise.
211
391
        """
212
 
        l = self._get_user_option(option_name)
 
392
        l = self.get_user_option(option_name, expand=expand)
213
393
        if isinstance(l, (str, unicode)):
214
 
            # A single value, most probably the user forgot the final ','
 
394
            # A single value, most probably the user forgot (or didn't care to
 
395
            # add) the final ','
215
396
            l = [l]
216
397
        return l
217
398
 
257
438
 
258
439
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
259
440
 
260
 
        $BZR_EMAIL can be set to override this (as well as the
261
 
        deprecated $BZREMAIL), then
 
441
        $BZR_EMAIL can be set to override this, then
262
442
        the concrete policy type is checked, and finally
263
443
        $EMAIL is examined.
264
 
        If none is found, a reasonable default is (hopefully)
265
 
        created.
266
 
 
267
 
        TODO: Check it's reasonably well-formed.
 
444
        If no username can be found, errors.NoWhoami exception is raised.
268
445
        """
269
446
        v = os.environ.get('BZR_EMAIL')
270
447
        if v:
271
448
            return v.decode(osutils.get_user_encoding())
272
 
 
273
449
        v = self._get_user_id()
274
450
        if v:
275
451
            return v
276
 
 
277
452
        v = os.environ.get('EMAIL')
278
453
        if v:
279
454
            return v.decode(osutils.get_user_encoding())
280
 
 
281
455
        name, email = _auto_user_id()
282
 
        if name:
 
456
        if name and email:
283
457
            return '%s <%s>' % (name, email)
284
 
        else:
 
458
        elif email:
285
459
            return email
 
460
        raise errors.NoWhoami()
 
461
 
 
462
    def ensure_username(self):
 
463
        """Raise errors.NoWhoami if username is not set.
 
464
 
 
465
        This method relies on the username() function raising the error.
 
466
        """
 
467
        self.username()
286
468
 
287
469
    def signature_checking(self):
288
470
        """What is the current policy for signature checking?."""
346
528
        else:
347
529
            return True
348
530
 
 
531
    def get_merge_tools(self):
 
532
        tools = {}
 
533
        for (oname, value, section, conf_id, parser) in self._get_options():
 
534
            if oname.startswith('bzr.mergetool.'):
 
535
                tool_name = oname[len('bzr.mergetool.'):]
 
536
                tools[tool_name] = value
 
537
        trace.mutter('loaded merge tools: %r' % tools)
 
538
        return tools
 
539
 
 
540
    def find_merge_tool(self, name):
 
541
        # We fake a defaults mechanism here by checking if the given name can 
 
542
        # be found in the known_merge_tools if it's not found in the config.
 
543
        # This should be done through the proposed config defaults mechanism
 
544
        # when it becomes available in the future.
 
545
        command_line = (self.get_user_option('bzr.mergetool.%s' % name,
 
546
                                             expand=False)
 
547
                        or mergetools.known_merge_tools.get(name, None))
 
548
        return command_line
 
549
 
349
550
 
350
551
class IniBasedConfig(Config):
351
552
    """A configuration policy that draws from ini files."""
352
553
 
353
 
    def __init__(self, get_filename):
 
554
    def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
 
555
                 file_name=None):
 
556
        """Base class for configuration files using an ini-like syntax.
 
557
 
 
558
        :param file_name: The configuration file path.
 
559
        """
354
560
        super(IniBasedConfig, self).__init__()
355
 
        self._get_filename = get_filename
 
561
        self.file_name = file_name
 
562
        if symbol_versioning.deprecated_passed(get_filename):
 
563
            symbol_versioning.warn(
 
564
                'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
 
565
                ' Use file_name instead.',
 
566
                DeprecationWarning,
 
567
                stacklevel=2)
 
568
            if get_filename is not None:
 
569
                self.file_name = get_filename()
 
570
        else:
 
571
            self.file_name = file_name
 
572
        self._content = None
356
573
        self._parser = None
357
574
 
358
 
    def _get_parser(self, file=None):
 
575
    @classmethod
 
576
    def from_string(cls, str_or_unicode, file_name=None, save=False):
 
577
        """Create a config object from a string.
 
578
 
 
579
        :param str_or_unicode: A string representing the file content. This will
 
580
            be utf-8 encoded.
 
581
 
 
582
        :param file_name: The configuration file path.
 
583
 
 
584
        :param _save: Whether the file should be saved upon creation.
 
585
        """
 
586
        conf = cls(file_name=file_name)
 
587
        conf._create_from_string(str_or_unicode, save)
 
588
        return conf
 
589
 
 
590
    def _create_from_string(self, str_or_unicode, save):
 
591
        self._content = StringIO(str_or_unicode.encode('utf-8'))
 
592
        # Some tests use in-memory configs, some other always need the config
 
593
        # file to exist on disk.
 
594
        if save:
 
595
            self._write_config_file()
 
596
 
 
597
    def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
359
598
        if self._parser is not None:
360
599
            return self._parser
361
 
        if file is None:
362
 
            input = self._get_filename()
 
600
        if symbol_versioning.deprecated_passed(file):
 
601
            symbol_versioning.warn(
 
602
                'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
 
603
                ' Use IniBasedConfig(_content=xxx) instead.',
 
604
                DeprecationWarning,
 
605
                stacklevel=2)
 
606
        if self._content is not None:
 
607
            co_input = self._content
 
608
        elif self.file_name is None:
 
609
            raise AssertionError('We have no content to create the config')
363
610
        else:
364
 
            input = file
 
611
            co_input = self.file_name
365
612
        try:
366
 
            self._parser = ConfigObj(input, encoding='utf-8')
 
613
            self._parser = ConfigObj(co_input, encoding='utf-8')
367
614
        except configobj.ConfigObjError, e:
368
615
            raise errors.ParseConfigError(e.errors, e.config.filename)
 
616
        # Make sure self.reload() will use the right file name
 
617
        self._parser.filename = self.file_name
369
618
        return self._parser
370
619
 
 
620
    def reload(self):
 
621
        """Reload the config file from disk."""
 
622
        if self.file_name is None:
 
623
            raise AssertionError('We need a file name to reload the config')
 
624
        if self._parser is not None:
 
625
            self._parser.reload()
 
626
 
371
627
    def _get_matching_sections(self):
372
628
        """Return an ordered list of (section_name, extra_path) pairs.
373
629
 
384
640
        """Override this to define the section used by the config."""
385
641
        return "DEFAULT"
386
642
 
 
643
    def _get_sections(self, name=None):
 
644
        """Returns an iterator of the sections specified by ``name``.
 
645
 
 
646
        :param name: The section name. If None is supplied, the default
 
647
            configurations are yielded.
 
648
 
 
649
        :return: A tuple (name, section, config_id) for all sections that will
 
650
            be walked by user_get_option() in the 'right' order. The first one
 
651
            is where set_user_option() will update the value.
 
652
        """
 
653
        parser = self._get_parser()
 
654
        if name is not None:
 
655
            yield (name, parser[name], self.config_id())
 
656
        else:
 
657
            # No section name has been given so we fallback to the configobj
 
658
            # itself which holds the variables defined outside of any section.
 
659
            yield (None, parser, self.config_id())
 
660
 
 
661
    def _get_options(self, sections=None):
 
662
        """Return an ordered list of (name, value, section, config_id) tuples.
 
663
 
 
664
        All options are returned with their associated value and the section
 
665
        they appeared in. ``config_id`` is a unique identifier for the
 
666
        configuration file the option is defined in.
 
667
 
 
668
        :param sections: Default to ``_get_matching_sections`` if not
 
669
            specified. This gives a better control to daughter classes about
 
670
            which sections should be searched. This is a list of (name,
 
671
            configobj) tuples.
 
672
        """
 
673
        opts = []
 
674
        if sections is None:
 
675
            parser = self._get_parser()
 
676
            sections = []
 
677
            for (section_name, _) in self._get_matching_sections():
 
678
                try:
 
679
                    section = parser[section_name]
 
680
                except KeyError:
 
681
                    # This could happen for an empty file for which we define a
 
682
                    # DEFAULT section. FIXME: Force callers to provide sections
 
683
                    # instead ? -- vila 20100930
 
684
                    continue
 
685
                sections.append((section_name, section))
 
686
        config_id = self.config_id()
 
687
        for (section_name, section) in sections:
 
688
            for (name, value) in section.iteritems():
 
689
                yield (name, parser._quote(value), section_name,
 
690
                       config_id, parser)
 
691
 
387
692
    def _get_option_policy(self, section, option_name):
388
693
        """Return the policy for the given (section, option_name) pair."""
389
694
        return POLICY_NONE
476
781
    def _get_nickname(self):
477
782
        return self.get_user_option('nickname')
478
783
 
479
 
 
480
 
class GlobalConfig(IniBasedConfig):
 
784
    def remove_user_option(self, option_name, section_name=None):
 
785
        """Remove a user option and save the configuration file.
 
786
 
 
787
        :param option_name: The option to be removed.
 
788
 
 
789
        :param section_name: The section the option is defined in, default to
 
790
            the default section.
 
791
        """
 
792
        self.reload()
 
793
        parser = self._get_parser()
 
794
        if section_name is None:
 
795
            section = parser
 
796
        else:
 
797
            section = parser[section_name]
 
798
        try:
 
799
            del section[option_name]
 
800
        except KeyError:
 
801
            raise errors.NoSuchConfigOption(option_name)
 
802
        self._write_config_file()
 
803
 
 
804
    def _write_config_file(self):
 
805
        if self.file_name is None:
 
806
            raise AssertionError('We cannot save, self.file_name is None')
 
807
        conf_dir = os.path.dirname(self.file_name)
 
808
        ensure_config_dir_exists(conf_dir)
 
809
        atomic_file = atomicfile.AtomicFile(self.file_name)
 
810
        self._get_parser().write(atomic_file)
 
811
        atomic_file.commit()
 
812
        atomic_file.close()
 
813
        osutils.copy_ownership_from_path(self.file_name)
 
814
 
 
815
 
 
816
class LockableConfig(IniBasedConfig):
 
817
    """A configuration needing explicit locking for access.
 
818
 
 
819
    If several processes try to write the config file, the accesses need to be
 
820
    serialized.
 
821
 
 
822
    Daughter classes should decorate all methods that update a config with the
 
823
    ``@needs_write_lock`` decorator (they call, directly or indirectly, the
 
824
    ``_write_config_file()`` method. These methods (typically ``set_option()``
 
825
    and variants must reload the config file from disk before calling
 
826
    ``_write_config_file()``), this can be achieved by calling the
 
827
    ``self.reload()`` method. Note that the lock scope should cover both the
 
828
    reading and the writing of the config file which is why the decorator can't
 
829
    be applied to ``_write_config_file()`` only.
 
830
 
 
831
    This should be enough to implement the following logic:
 
832
    - lock for exclusive write access,
 
833
    - reload the config file from disk,
 
834
    - set the new value
 
835
    - unlock
 
836
 
 
837
    This logic guarantees that a writer can update a value without erasing an
 
838
    update made by another writer.
 
839
    """
 
840
 
 
841
    lock_name = 'lock'
 
842
 
 
843
    def __init__(self, file_name):
 
844
        super(LockableConfig, self).__init__(file_name=file_name)
 
845
        self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
 
846
        # FIXME: It doesn't matter that we don't provide possible_transports
 
847
        # below since this is currently used only for local config files ;
 
848
        # local transports are not shared. But if/when we start using
 
849
        # LockableConfig for other kind of transports, we will need to reuse
 
850
        # whatever connection is already established -- vila 20100929
 
851
        self.transport = transport.get_transport(self.dir)
 
852
        self._lock = lockdir.LockDir(self.transport, 'lock')
 
853
 
 
854
    def _create_from_string(self, unicode_bytes, save):
 
855
        super(LockableConfig, self)._create_from_string(unicode_bytes, False)
 
856
        if save:
 
857
            # We need to handle the saving here (as opposed to IniBasedConfig)
 
858
            # to be able to lock
 
859
            self.lock_write()
 
860
            self._write_config_file()
 
861
            self.unlock()
 
862
 
 
863
    def lock_write(self, token=None):
 
864
        """Takes a write lock in the directory containing the config file.
 
865
 
 
866
        If the directory doesn't exist it is created.
 
867
        """
 
868
        ensure_config_dir_exists(self.dir)
 
869
        return self._lock.lock_write(token)
 
870
 
 
871
    def unlock(self):
 
872
        self._lock.unlock()
 
873
 
 
874
    def break_lock(self):
 
875
        self._lock.break_lock()
 
876
 
 
877
    @needs_write_lock
 
878
    def remove_user_option(self, option_name, section_name=None):
 
879
        super(LockableConfig, self).remove_user_option(option_name,
 
880
                                                       section_name)
 
881
 
 
882
    def _write_config_file(self):
 
883
        if self._lock is None or not self._lock.is_held:
 
884
            # NB: if the following exception is raised it probably means a
 
885
            # missing @needs_write_lock decorator on one of the callers.
 
886
            raise errors.ObjectNotLocked(self)
 
887
        super(LockableConfig, self)._write_config_file()
 
888
 
 
889
 
 
890
class GlobalConfig(LockableConfig):
481
891
    """The configuration that should be used for a specific location."""
482
892
 
 
893
    def __init__(self):
 
894
        super(GlobalConfig, self).__init__(file_name=config_filename())
 
895
 
 
896
    def config_id(self):
 
897
        return 'bazaar'
 
898
 
 
899
    @classmethod
 
900
    def from_string(cls, str_or_unicode, save=False):
 
901
        """Create a config object from a string.
 
902
 
 
903
        :param str_or_unicode: A string representing the file content. This
 
904
            will be utf-8 encoded.
 
905
 
 
906
        :param save: Whether the file should be saved upon creation.
 
907
        """
 
908
        conf = cls()
 
909
        conf._create_from_string(str_or_unicode, save)
 
910
        return conf
 
911
 
483
912
    def get_editor(self):
484
913
        return self._get_user_option('editor')
485
914
 
486
 
    def __init__(self):
487
 
        super(GlobalConfig, self).__init__(config_filename)
488
 
 
 
915
    @needs_write_lock
489
916
    def set_user_option(self, option, value):
490
917
        """Save option and its value in the configuration."""
491
918
        self._set_option(option, value, 'DEFAULT')
497
924
        else:
498
925
            return {}
499
926
 
 
927
    @needs_write_lock
500
928
    def set_alias(self, alias_name, alias_command):
501
929
        """Save the alias in the configuration."""
502
930
        self._set_option(alias_name, alias_command, 'ALIASES')
503
931
 
 
932
    @needs_write_lock
504
933
    def unset_alias(self, alias_name):
505
934
        """Unset an existing alias."""
 
935
        self.reload()
506
936
        aliases = self._get_parser().get('ALIASES')
507
937
        if not aliases or alias_name not in aliases:
508
938
            raise errors.NoSuchAlias(alias_name)
510
940
        self._write_config_file()
511
941
 
512
942
    def _set_option(self, option, value, section):
513
 
        # FIXME: RBC 20051029 This should refresh the parser and also take a
514
 
        # file lock on bazaar.conf.
515
 
        conf_dir = os.path.dirname(self._get_filename())
516
 
        ensure_config_dir_exists(conf_dir)
 
943
        self.reload()
517
944
        self._get_parser().setdefault(section, {})[option] = value
518
945
        self._write_config_file()
519
946
 
520
 
    def _write_config_file(self):
521
 
        path = self._get_filename()
522
 
        f = open(path, 'wb')
523
 
        osutils.copy_ownership_from_path(path)
524
 
        self._get_parser().write(f)
525
 
        f.close()
526
 
 
527
 
 
528
 
class LocationConfig(IniBasedConfig):
 
947
 
 
948
    def _get_sections(self, name=None):
 
949
        """See IniBasedConfig._get_sections()."""
 
950
        parser = self._get_parser()
 
951
        # We don't give access to options defined outside of any section, we
 
952
        # used the DEFAULT section by... default.
 
953
        if name in (None, 'DEFAULT'):
 
954
            # This could happen for an empty file where the DEFAULT section
 
955
            # doesn't exist yet. So we force DEFAULT when yielding
 
956
            name = 'DEFAULT'
 
957
            if 'DEFAULT' not in parser:
 
958
               parser['DEFAULT']= {}
 
959
        yield (name, parser[name], self.config_id())
 
960
 
 
961
    @needs_write_lock
 
962
    def remove_user_option(self, option_name, section_name=None):
 
963
        if section_name is None:
 
964
            # We need to force the default section.
 
965
            section_name = 'DEFAULT'
 
966
        # We need to avoid the LockableConfig implementation or we'll lock
 
967
        # twice
 
968
        super(LockableConfig, self).remove_user_option(option_name,
 
969
                                                       section_name)
 
970
 
 
971
 
 
972
class LocationConfig(LockableConfig):
529
973
    """A configuration object that gives the policy for a location."""
530
974
 
531
975
    def __init__(self, location):
532
 
        name_generator = locations_config_filename
533
 
        if (not os.path.exists(name_generator()) and
534
 
                os.path.exists(branches_config_filename())):
535
 
            if sys.platform == 'win32':
536
 
                trace.warning('Please rename %s to %s'
537
 
                              % (branches_config_filename(),
538
 
                                 locations_config_filename()))
539
 
            else:
540
 
                trace.warning('Please rename ~/.bazaar/branches.conf'
541
 
                              ' to ~/.bazaar/locations.conf')
542
 
            name_generator = branches_config_filename
543
 
        super(LocationConfig, self).__init__(name_generator)
 
976
        super(LocationConfig, self).__init__(
 
977
            file_name=locations_config_filename())
544
978
        # local file locations are looked up by local path, rather than
545
979
        # by file url. This is because the config file is a user
546
980
        # file, and we would rather not expose the user to file urls.
548
982
            location = urlutils.local_path_from_url(location)
549
983
        self.location = location
550
984
 
 
985
    def config_id(self):
 
986
        return 'locations'
 
987
 
 
988
    @classmethod
 
989
    def from_string(cls, str_or_unicode, location, save=False):
 
990
        """Create a config object from a string.
 
991
 
 
992
        :param str_or_unicode: A string representing the file content. This will
 
993
            be utf-8 encoded.
 
994
 
 
995
        :param location: The location url to filter the configuration.
 
996
 
 
997
        :param save: Whether the file should be saved upon creation.
 
998
        """
 
999
        conf = cls(location)
 
1000
        conf._create_from_string(str_or_unicode, save)
 
1001
        return conf
 
1002
 
551
1003
    def _get_matching_sections(self):
552
1004
        """Return an ordered list of section names matching this location."""
553
1005
        sections = self._get_parser()
570
1022
            names = zip(location_names, section_names)
571
1023
            matched = True
572
1024
            for name in names:
573
 
                if not fnmatch(name[0], name[1]):
 
1025
                if not fnmatch.fnmatch(name[0], name[1]):
574
1026
                    matched = False
575
1027
                    break
576
1028
            if not matched:
581
1033
                continue
582
1034
            matches.append((len(section_names), section,
583
1035
                            '/'.join(location_names[len(section_names):])))
 
1036
        # put the longest (aka more specific) locations first
584
1037
        matches.sort(reverse=True)
585
1038
        sections = []
586
1039
        for (length, section, extra_path) in matches:
593
1046
                pass
594
1047
        return sections
595
1048
 
 
1049
    def _get_sections(self, name=None):
 
1050
        """See IniBasedConfig._get_sections()."""
 
1051
        # We ignore the name here as the only sections handled are named with
 
1052
        # the location path and we don't expose embedded sections either.
 
1053
        parser = self._get_parser()
 
1054
        for name, extra_path in self._get_matching_sections():
 
1055
            yield (name, parser[name], self.config_id())
 
1056
 
596
1057
    def _get_option_policy(self, section, option_name):
597
1058
        """Return the policy for the given (section, option_name) pair."""
598
1059
        # check for the old 'recurse=False' flag
641
1102
            if policy_key in self._get_parser()[section]:
642
1103
                del self._get_parser()[section][policy_key]
643
1104
 
 
1105
    @needs_write_lock
644
1106
    def set_user_option(self, option, value, store=STORE_LOCATION):
645
1107
        """Save option and its value in the configuration."""
646
1108
        if store not in [STORE_LOCATION,
648
1110
                         STORE_LOCATION_APPENDPATH]:
649
1111
            raise ValueError('bad storage policy %r for %r' %
650
1112
                (store, option))
651
 
        # FIXME: RBC 20051029 This should refresh the parser and also take a
652
 
        # file lock on locations.conf.
653
 
        conf_dir = os.path.dirname(self._get_filename())
654
 
        ensure_config_dir_exists(conf_dir)
 
1113
        self.reload()
655
1114
        location = self.location
656
1115
        if location.endswith('/'):
657
1116
            location = location[:-1]
658
 
        if (not location in self._get_parser() and
659
 
            not location + '/' in self._get_parser()):
660
 
            self._get_parser()[location]={}
661
 
        elif location + '/' in self._get_parser():
 
1117
        parser = self._get_parser()
 
1118
        if not location in parser and not location + '/' in parser:
 
1119
            parser[location] = {}
 
1120
        elif location + '/' in parser:
662
1121
            location = location + '/'
663
 
        self._get_parser()[location][option]=value
 
1122
        parser[location][option]=value
664
1123
        # the allowed values of store match the config policies
665
1124
        self._set_option_policy(location, option, store)
666
 
        self._get_parser().write(file(self._get_filename(), 'wb'))
 
1125
        self._write_config_file()
667
1126
 
668
1127
 
669
1128
class BranchConfig(Config):
670
1129
    """A configuration object giving the policy for a branch."""
671
1130
 
 
1131
    def __init__(self, branch):
 
1132
        super(BranchConfig, self).__init__()
 
1133
        self._location_config = None
 
1134
        self._branch_data_config = None
 
1135
        self._global_config = None
 
1136
        self.branch = branch
 
1137
        self.option_sources = (self._get_location_config,
 
1138
                               self._get_branch_data_config,
 
1139
                               self._get_global_config)
 
1140
 
 
1141
    def config_id(self):
 
1142
        return 'branch'
 
1143
 
672
1144
    def _get_branch_data_config(self):
673
1145
        if self._branch_data_config is None:
674
1146
            self._branch_data_config = TreeConfig(self.branch)
 
1147
            self._branch_data_config.config_id = self.config_id
675
1148
        return self._branch_data_config
676
1149
 
677
1150
    def _get_location_config(self):
745
1218
                return value
746
1219
        return None
747
1220
 
 
1221
    def _get_sections(self, name=None):
 
1222
        """See IniBasedConfig.get_sections()."""
 
1223
        for source in self.option_sources:
 
1224
            for section in source()._get_sections(name):
 
1225
                yield section
 
1226
 
 
1227
    def _get_options(self, sections=None):
 
1228
        opts = []
 
1229
        # First the locations options
 
1230
        for option in self._get_location_config()._get_options():
 
1231
            yield option
 
1232
        # Then the branch options
 
1233
        branch_config = self._get_branch_data_config()
 
1234
        if sections is None:
 
1235
            sections = [('DEFAULT', branch_config._get_parser())]
 
1236
        # FIXME: We shouldn't have to duplicate the code in IniBasedConfig but
 
1237
        # Config itself has no notion of sections :( -- vila 20101001
 
1238
        config_id = self.config_id()
 
1239
        for (section_name, section) in sections:
 
1240
            for (name, value) in section.iteritems():
 
1241
                yield (name, value, section_name,
 
1242
                       config_id, branch_config._get_parser())
 
1243
        # Then the global options
 
1244
        for option in self._get_global_config()._get_options():
 
1245
            yield option
 
1246
 
748
1247
    def set_user_option(self, name, value, store=STORE_BRANCH,
749
1248
        warn_masked=False):
750
1249
        if store == STORE_BRANCH:
768
1267
                        trace.warning('Value "%s" is masked by "%s" from'
769
1268
                                      ' branch.conf', value, mask_value)
770
1269
 
 
1270
    def remove_user_option(self, option_name, section_name=None):
 
1271
        self._get_branch_data_config().remove_option(option_name, section_name)
 
1272
 
771
1273
    def _gpg_signing_command(self):
772
1274
        """See Config.gpg_signing_command."""
773
1275
        return self._get_safe_value('_gpg_signing_command')
774
1276
 
775
 
    def __init__(self, branch):
776
 
        super(BranchConfig, self).__init__()
777
 
        self._location_config = None
778
 
        self._branch_data_config = None
779
 
        self._global_config = None
780
 
        self.branch = branch
781
 
        self.option_sources = (self._get_location_config,
782
 
                               self._get_branch_data_config,
783
 
                               self._get_global_config)
784
 
 
785
1277
    def _post_commit(self):
786
1278
        """See Config.post_commit."""
787
1279
        return self._get_safe_value('_post_commit')
817
1309
            parent_dir = os.path.dirname(path)
818
1310
            if not os.path.isdir(parent_dir):
819
1311
                trace.mutter('creating config parent directory: %r', parent_dir)
820
 
            os.mkdir(parent_dir)
 
1312
                os.mkdir(parent_dir)
821
1313
        trace.mutter('creating config directory: %r', path)
822
1314
        os.mkdir(path)
823
1315
        osutils.copy_ownership_from_path(path)
826
1318
def config_dir():
827
1319
    """Return per-user configuration directory.
828
1320
 
829
 
    By default this is ~/.bazaar/
 
1321
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
 
1322
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
 
1323
    that will be used instead.
830
1324
 
831
1325
    TODO: Global option --config-dir to override this.
832
1326
    """
833
1327
    base = os.environ.get('BZR_HOME', None)
834
1328
    if sys.platform == 'win32':
 
1329
        # environ variables on Windows are in user encoding/mbcs. So decode
 
1330
        # before using one
 
1331
        if base is not None:
 
1332
            base = base.decode('mbcs')
835
1333
        if base is None:
836
1334
            base = win32utils.get_appdata_location_unicode()
837
1335
        if base is None:
838
1336
            base = os.environ.get('HOME', None)
 
1337
            if base is not None:
 
1338
                base = base.decode('mbcs')
839
1339
        if base is None:
840
1340
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
841
1341
                                  ' or HOME set')
842
1342
        return osutils.pathjoin(base, 'bazaar', '2.0')
 
1343
    elif sys.platform == 'darwin':
 
1344
        if base is None:
 
1345
            # this takes into account $HOME
 
1346
            base = os.path.expanduser("~")
 
1347
        return osutils.pathjoin(base, '.bazaar')
843
1348
    else:
844
 
        # cygwin, linux, and darwin all have a $HOME directory
845
1349
        if base is None:
 
1350
 
 
1351
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
 
1352
            if xdg_dir is None:
 
1353
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
 
1354
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
 
1355
            if osutils.isdir(xdg_dir):
 
1356
                trace.mutter(
 
1357
                    "Using configuration in XDG directory %s." % xdg_dir)
 
1358
                return xdg_dir
 
1359
 
846
1360
            base = os.path.expanduser("~")
847
1361
        return osutils.pathjoin(base, ".bazaar")
848
1362
 
852
1366
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
853
1367
 
854
1368
 
855
 
def branches_config_filename():
856
 
    """Return per-user configuration ini file filename."""
857
 
    return osutils.pathjoin(config_dir(), 'branches.conf')
858
 
 
859
 
 
860
1369
def locations_config_filename():
861
1370
    """Return per-user configuration ini file filename."""
862
1371
    return osutils.pathjoin(config_dir(), 'locations.conf')
899
1408
        return os.path.expanduser('~/.cache')
900
1409
 
901
1410
 
 
1411
def _get_default_mail_domain():
 
1412
    """If possible, return the assumed default email domain.
 
1413
 
 
1414
    :returns: string mail domain, or None.
 
1415
    """
 
1416
    if sys.platform == 'win32':
 
1417
        # No implementation yet; patches welcome
 
1418
        return None
 
1419
    try:
 
1420
        f = open('/etc/mailname')
 
1421
    except (IOError, OSError), e:
 
1422
        return None
 
1423
    try:
 
1424
        domain = f.read().strip()
 
1425
        return domain
 
1426
    finally:
 
1427
        f.close()
 
1428
 
 
1429
 
902
1430
def _auto_user_id():
903
1431
    """Calculate automatic user identification.
904
1432
 
905
 
    Returns (realname, email).
 
1433
    :returns: (realname, email), either of which may be None if they can't be
 
1434
    determined.
906
1435
 
907
1436
    Only used when none is set in the environment or the id file.
908
1437
 
909
 
    This previously used the FQDN as the default domain, but that can
910
 
    be very slow on machines where DNS is broken.  So now we simply
911
 
    use the hostname.
 
1438
    This only returns an email address if we can be fairly sure the 
 
1439
    address is reasonable, ie if /etc/mailname is set on unix.
 
1440
 
 
1441
    This doesn't use the FQDN as the default domain because that may be 
 
1442
    slow, and it doesn't use the hostname alone because that's not normally 
 
1443
    a reasonable address.
912
1444
    """
913
 
    import socket
914
 
 
915
1445
    if sys.platform == 'win32':
916
 
        name = win32utils.get_user_name_unicode()
917
 
        if name is None:
918
 
            raise errors.BzrError("Cannot autodetect user name.\n"
919
 
                                  "Please, set your name with command like:\n"
920
 
                                  'bzr whoami "Your Name <name@domain.com>"')
921
 
        host = win32utils.get_host_name_unicode()
922
 
        if host is None:
923
 
            host = socket.gethostname()
924
 
        return name, (name + '@' + host)
925
 
 
926
 
    try:
927
 
        import pwd
928
 
        uid = os.getuid()
929
 
        try:
930
 
            w = pwd.getpwuid(uid)
931
 
        except KeyError:
932
 
            raise errors.BzrCommandError('Unable to determine your name.  '
933
 
                'Please use "bzr whoami" to set it.')
934
 
 
935
 
        # we try utf-8 first, because on many variants (like Linux),
936
 
        # /etc/passwd "should" be in utf-8, and because it's unlikely to give
937
 
        # false positives.  (many users will have their user encoding set to
938
 
        # latin-1, which cannot raise UnicodeError.)
939
 
        try:
940
 
            gecos = w.pw_gecos.decode('utf-8')
941
 
            encoding = 'utf-8'
942
 
        except UnicodeError:
943
 
            try:
944
 
                encoding = osutils.get_user_encoding()
945
 
                gecos = w.pw_gecos.decode(encoding)
946
 
            except UnicodeError:
947
 
                raise errors.BzrCommandError('Unable to determine your name.  '
948
 
                   'Use "bzr whoami" to set it.')
949
 
        try:
950
 
            username = w.pw_name.decode(encoding)
951
 
        except UnicodeError:
952
 
            raise errors.BzrCommandError('Unable to determine your name.  '
953
 
                'Use "bzr whoami" to set it.')
954
 
 
955
 
        comma = gecos.find(',')
956
 
        if comma == -1:
957
 
            realname = gecos
958
 
        else:
959
 
            realname = gecos[:comma]
960
 
        if not realname:
961
 
            realname = username
962
 
 
963
 
    except ImportError:
964
 
        import getpass
965
 
        try:
966
 
            user_encoding = osutils.get_user_encoding()
967
 
            realname = username = getpass.getuser().decode(user_encoding)
968
 
        except UnicodeDecodeError:
969
 
            raise errors.BzrError("Can't decode username as %s." % \
970
 
                    user_encoding)
971
 
 
972
 
    return realname, (username + '@' + socket.gethostname())
 
1446
        # No implementation to reliably determine Windows default mail
 
1447
        # address; please add one.
 
1448
        return None, None
 
1449
 
 
1450
    default_mail_domain = _get_default_mail_domain()
 
1451
    if not default_mail_domain:
 
1452
        return None, None
 
1453
 
 
1454
    import pwd
 
1455
    uid = os.getuid()
 
1456
    try:
 
1457
        w = pwd.getpwuid(uid)
 
1458
    except KeyError:
 
1459
        mutter('no passwd entry for uid %d?' % uid)
 
1460
        return None, None
 
1461
 
 
1462
    # we try utf-8 first, because on many variants (like Linux),
 
1463
    # /etc/passwd "should" be in utf-8, and because it's unlikely to give
 
1464
    # false positives.  (many users will have their user encoding set to
 
1465
    # latin-1, which cannot raise UnicodeError.)
 
1466
    try:
 
1467
        gecos = w.pw_gecos.decode('utf-8')
 
1468
        encoding = 'utf-8'
 
1469
    except UnicodeError:
 
1470
        try:
 
1471
            encoding = osutils.get_user_encoding()
 
1472
            gecos = w.pw_gecos.decode(encoding)
 
1473
        except UnicodeError, e:
 
1474
            mutter("cannot decode passwd entry %s" % w)
 
1475
            return None, None
 
1476
    try:
 
1477
        username = w.pw_name.decode(encoding)
 
1478
    except UnicodeError, e:
 
1479
        mutter("cannot decode passwd entry %s" % w)
 
1480
        return None, None
 
1481
 
 
1482
    comma = gecos.find(',')
 
1483
    if comma == -1:
 
1484
        realname = gecos
 
1485
    else:
 
1486
        realname = gecos[:comma]
 
1487
 
 
1488
    return realname, (username + '@' + default_mail_domain)
973
1489
 
974
1490
 
975
1491
def parse_username(username):
1020
1536
 
1021
1537
    def set_option(self, value, name, section=None):
1022
1538
        """Set a per-branch configuration option"""
 
1539
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1540
        # higher levels providing the right lock -- vila 20101004
1023
1541
        self.branch.lock_write()
1024
1542
        try:
1025
1543
            self._config.set_option(value, name, section)
1026
1544
        finally:
1027
1545
            self.branch.unlock()
1028
1546
 
 
1547
    def remove_option(self, option_name, section_name=None):
 
1548
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1549
        # higher levels providing the right lock -- vila 20101004
 
1550
        self.branch.lock_write()
 
1551
        try:
 
1552
            self._config.remove_option(option_name, section_name)
 
1553
        finally:
 
1554
            self.branch.unlock()
 
1555
 
1029
1556
 
1030
1557
class AuthenticationConfig(object):
1031
1558
    """The authentication configuration file based on a ini file.
1063
1590
        """Save the config file, only tests should use it for now."""
1064
1591
        conf_dir = os.path.dirname(self._filename)
1065
1592
        ensure_config_dir_exists(conf_dir)
1066
 
        self._get_config().write(file(self._filename, 'wb'))
 
1593
        f = file(self._filename, 'wb')
 
1594
        try:
 
1595
            self._get_config().write(f)
 
1596
        finally:
 
1597
            f.close()
1067
1598
 
1068
1599
    def _set_option(self, section_name, option_name, value):
1069
1600
        """Set an authentication configuration option"""
1470
2001
    """A Config that reads/writes a config file on a Transport.
1471
2002
 
1472
2003
    It is a low-level object that considers config data to be name/value pairs
1473
 
    that may be associated with a section.  Assigning meaning to the these
1474
 
    values is done at higher levels like TreeConfig.
 
2004
    that may be associated with a section.  Assigning meaning to these values
 
2005
    is done at higher levels like TreeConfig.
1475
2006
    """
1476
2007
 
1477
2008
    def __init__(self, transport, filename):
1510
2041
            configobj.setdefault(section, {})[name] = value
1511
2042
        self._set_configobj(configobj)
1512
2043
 
 
2044
    def remove_option(self, option_name, section_name=None):
 
2045
        configobj = self._get_configobj()
 
2046
        if section_name is None:
 
2047
            del configobj[option_name]
 
2048
        else:
 
2049
            del configobj[section_name][option_name]
 
2050
        self._set_configobj(configobj)
 
2051
 
1513
2052
    def _get_config_file(self):
1514
2053
        try:
1515
2054
            return StringIO(self._transport.get_bytes(self._filename))
1517
2056
            return StringIO()
1518
2057
 
1519
2058
    def _get_configobj(self):
1520
 
        return ConfigObj(self._get_config_file(), encoding='utf-8')
 
2059
        f = self._get_config_file()
 
2060
        try:
 
2061
            return ConfigObj(f, encoding='utf-8')
 
2062
        finally:
 
2063
            f.close()
1521
2064
 
1522
2065
    def _set_configobj(self, configobj):
1523
2066
        out_file = StringIO()
1524
2067
        configobj.write(out_file)
1525
2068
        out_file.seek(0)
1526
2069
        self._transport.put_file(self._filename, out_file)
 
2070
 
 
2071
 
 
2072
class cmd_config(commands.Command):
 
2073
    __doc__ = """Display, set or remove a configuration option.
 
2074
 
 
2075
    Display the active value for a given option.
 
2076
 
 
2077
    If --all is specified, NAME is interpreted as a regular expression and all
 
2078
    matching options are displayed mentioning their scope. The active value
 
2079
    that bzr will take into account is the first one displayed for each option.
 
2080
 
 
2081
    If no NAME is given, --all .* is implied.
 
2082
 
 
2083
    Setting a value is achieved by using name=value without spaces. The value
 
2084
    is set in the most relevant scope and can be checked by displaying the
 
2085
    option again.
 
2086
    """
 
2087
 
 
2088
    takes_args = ['name?']
 
2089
 
 
2090
    takes_options = [
 
2091
        'directory',
 
2092
        # FIXME: This should be a registry option so that plugins can register
 
2093
        # their own config files (or not) -- vila 20101002
 
2094
        commands.Option('scope', help='Reduce the scope to the specified'
 
2095
                        ' configuration file',
 
2096
                        type=unicode),
 
2097
        commands.Option('all',
 
2098
            help='Display all the defined values for the matching options.',
 
2099
            ),
 
2100
        commands.Option('remove', help='Remove the option from'
 
2101
                        ' the configuration file'),
 
2102
        ]
 
2103
 
 
2104
    @commands.display_command
 
2105
    def run(self, name=None, all=False, directory=None, scope=None,
 
2106
            remove=False):
 
2107
        if directory is None:
 
2108
            directory = '.'
 
2109
        directory = urlutils.normalize_url(directory)
 
2110
        if remove and all:
 
2111
            raise errors.BzrError(
 
2112
                '--all and --remove are mutually exclusive.')
 
2113
        elif remove:
 
2114
            # Delete the option in the given scope
 
2115
            self._remove_config_option(name, directory, scope)
 
2116
        elif name is None:
 
2117
            # Defaults to all options
 
2118
            self._show_matching_options('.*', directory, scope)
 
2119
        else:
 
2120
            try:
 
2121
                name, value = name.split('=', 1)
 
2122
            except ValueError:
 
2123
                # Display the option(s) value(s)
 
2124
                if all:
 
2125
                    self._show_matching_options(name, directory, scope)
 
2126
                else:
 
2127
                    self._show_value(name, directory, scope)
 
2128
            else:
 
2129
                if all:
 
2130
                    raise errors.BzrError(
 
2131
                        'Only one option can be set.')
 
2132
                # Set the option value
 
2133
                self._set_config_option(name, value, directory, scope)
 
2134
 
 
2135
    def _get_configs(self, directory, scope=None):
 
2136
        """Iterate the configurations specified by ``directory`` and ``scope``.
 
2137
 
 
2138
        :param directory: Where the configurations are derived from.
 
2139
 
 
2140
        :param scope: A specific config to start from.
 
2141
        """
 
2142
        if scope is not None:
 
2143
            if scope == 'bazaar':
 
2144
                yield GlobalConfig()
 
2145
            elif scope == 'locations':
 
2146
                yield LocationConfig(directory)
 
2147
            elif scope == 'branch':
 
2148
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2149
                    directory)
 
2150
                yield br.get_config()
 
2151
        else:
 
2152
            try:
 
2153
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2154
                    directory)
 
2155
                yield br.get_config()
 
2156
            except errors.NotBranchError:
 
2157
                yield LocationConfig(directory)
 
2158
                yield GlobalConfig()
 
2159
 
 
2160
    def _show_value(self, name, directory, scope):
 
2161
        displayed = False
 
2162
        for c in self._get_configs(directory, scope):
 
2163
            if displayed:
 
2164
                break
 
2165
            for (oname, value, section, conf_id, parser) in c._get_options():
 
2166
                if name == oname:
 
2167
                    # Display only the first value and exit
 
2168
 
 
2169
                    # FIXME: We need to use get_user_option to take policies
 
2170
                    # into account and we need to make sure the option exists
 
2171
                    # too (hence the two for loops), this needs a better API
 
2172
                    # -- vila 20101117
 
2173
                    value = c.get_user_option(name)
 
2174
                    # Quote the value appropriately
 
2175
                    value = parser._quote(value)
 
2176
                    self.outf.write('%s\n' % (value,))
 
2177
                    displayed = True
 
2178
                    break
 
2179
        if not displayed:
 
2180
            raise errors.NoSuchConfigOption(name)
 
2181
 
 
2182
    def _show_matching_options(self, name, directory, scope):
 
2183
        name = re.compile(name)
 
2184
        # We want any error in the regexp to be raised *now* so we need to
 
2185
        # avoid the delay introduced by the lazy regexp.
 
2186
        name._compile_and_collapse()
 
2187
        cur_conf_id = None
 
2188
        cur_section = None
 
2189
        for c in self._get_configs(directory, scope):
 
2190
            for (oname, value, section, conf_id, parser) in c._get_options():
 
2191
                if name.search(oname):
 
2192
                    if cur_conf_id != conf_id:
 
2193
                        # Explain where the options are defined
 
2194
                        self.outf.write('%s:\n' % (conf_id,))
 
2195
                        cur_conf_id = conf_id
 
2196
                        cur_section = None
 
2197
                    if (section not in (None, 'DEFAULT')
 
2198
                        and cur_section != section):
 
2199
                        # Display the section if it's not the default (or only)
 
2200
                        # one.
 
2201
                        self.outf.write('  [%s]\n' % (section,))
 
2202
                        cur_section = section
 
2203
                    self.outf.write('  %s = %s\n' % (oname, value))
 
2204
 
 
2205
    def _set_config_option(self, name, value, directory, scope):
 
2206
        for conf in self._get_configs(directory, scope):
 
2207
            conf.set_user_option(name, value)
 
2208
            break
 
2209
        else:
 
2210
            raise errors.NoSuchConfig(scope)
 
2211
 
 
2212
    def _remove_config_option(self, name, directory, scope):
 
2213
        if name is None:
 
2214
            raise errors.BzrCommandError(
 
2215
                '--remove expects an option to remove.')
 
2216
        removed = False
 
2217
        for conf in self._get_configs(directory, scope):
 
2218
            for (section_name, section, conf_id) in conf._get_sections():
 
2219
                if scope is not None and conf_id != scope:
 
2220
                    # Not the right configuration file
 
2221
                    continue
 
2222
                if name in section:
 
2223
                    if conf_id != conf.config_id():
 
2224
                        conf = self._get_configs(directory, conf_id).next()
 
2225
                    # We use the first section in the first config where the
 
2226
                    # option is defined to remove it
 
2227
                    conf.remove_user_option(name, section_name)
 
2228
                    removed = True
 
2229
                    break
 
2230
            break
 
2231
        else:
 
2232
            raise errors.NoSuchConfig(scope)
 
2233
        if not removed:
 
2234
            raise errors.NoSuchConfigOption(name)