~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Andrew Bennetts
  • Date: 2010-10-08 08:15:14 UTC
  • mto: This revision was merged to the branch mainline in revision 5498.
  • Revision ID: andrew.bennetts@canonical.com-20101008081514-dviqzrdfwyzsqbz2
Split NEWS into per-release doc/en/release-notes/bzr-*.txt

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
67
66
import sys
68
67
 
69
 
from bzrlib import commands
70
68
from bzrlib.decorators import needs_write_lock
71
69
from bzrlib.lazy_import import lazy_import
72
70
lazy_import(globals(), """
73
 
import fnmatch
 
71
import errno
 
72
from fnmatch import fnmatch
74
73
import re
75
74
from cStringIO import StringIO
76
75
 
77
76
import bzrlib
78
77
from bzrlib import (
79
78
    atomicfile,
80
 
    bzrdir,
81
79
    debug,
82
80
    errors,
83
81
    lockdir,
84
82
    mail_client,
85
 
    mergetools,
86
83
    osutils,
87
84
    registry,
88
85
    symbol_versioning,
129
126
STORE_BRANCH = 3
130
127
STORE_GLOBAL = 4
131
128
 
132
 
 
133
 
class ConfigObj(configobj.ConfigObj):
134
 
 
135
 
    def __init__(self, infile=None, **kwargs):
136
 
        # We define our own interpolation mechanism calling it option expansion
137
 
        super(ConfigObj, self).__init__(infile=infile,
138
 
                                        interpolation=False,
139
 
                                        **kwargs)
140
 
 
141
 
 
142
 
    def get_bool(self, section, key):
143
 
        return self[section].as_bool(key)
144
 
 
145
 
    def get_value(self, section, name):
146
 
        # Try [] for the old DEFAULT section.
147
 
        if section == "DEFAULT":
148
 
            try:
149
 
                return self[name]
150
 
            except KeyError:
151
 
                pass
152
 
        return self[section][name]
153
 
 
154
 
 
155
 
# FIXME: Until we can guarantee that each config file is loaded once and and
156
 
# only once for a given bzrlib session, we don't want to re-read the file every
157
 
# time we query for an option so we cache the value (bad ! watch out for tests
158
 
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
159
 
# yell at mgz^W vila and the RM if this is still present at that time
160
 
# -- vila 20110219
161
 
_expand_default_value = None
162
 
def _get_expand_default_value():
163
 
    global _expand_default_value
164
 
    if _expand_default_value is not None:
165
 
        return _expand_default_value
166
 
    conf = GlobalConfig()
167
 
    # Note that we must not use None for the expand value below or we'll run
168
 
    # into infinite recursion. Using False really would be quite silly ;)
169
 
    expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
170
 
    if expand is None:
171
 
        # This is an opt-in feature, you *really* need to clearly say you want
172
 
        # to activate it !
173
 
        expand = False
174
 
    _expand_default_value = expand
175
 
    return expand
 
129
_ConfigObj = None
 
130
def ConfigObj(*args, **kwargs):
 
131
    global _ConfigObj
 
132
    if _ConfigObj is None:
 
133
        class ConfigObj(configobj.ConfigObj):
 
134
 
 
135
            def get_bool(self, section, key):
 
136
                return self[section].as_bool(key)
 
137
 
 
138
            def get_value(self, section, name):
 
139
                # Try [] for the old DEFAULT section.
 
140
                if section == "DEFAULT":
 
141
                    try:
 
142
                        return self[name]
 
143
                    except KeyError:
 
144
                        pass
 
145
                return self[section][name]
 
146
        _ConfigObj = ConfigObj
 
147
    return _ConfigObj(*args, **kwargs)
176
148
 
177
149
 
178
150
class Config(object):
181
153
    def __init__(self):
182
154
        super(Config, self).__init__()
183
155
 
184
 
    def config_id(self):
185
 
        """Returns a unique ID for the config."""
186
 
        raise NotImplementedError(self.config_id)
187
 
 
188
156
    def get_editor(self):
189
157
        """Get the users pop up editor."""
190
158
        raise NotImplementedError
214
182
    def _get_signing_policy(self):
215
183
        """Template method to override signature creation policy."""
216
184
 
217
 
    option_ref_re = None
218
 
 
219
 
    def expand_options(self, string, env=None):
220
 
        """Expand option references in the string in the configuration context.
221
 
 
222
 
        :param string: The string containing option to expand.
223
 
 
224
 
        :param env: An option dict defining additional configuration options or
225
 
            overriding existing ones.
226
 
 
227
 
        :returns: The expanded string.
228
 
        """
229
 
        return self._expand_options_in_string(string, env)
230
 
 
231
 
    def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
232
 
        """Expand options in  a list of strings in the configuration context.
233
 
 
234
 
        :param slist: A list of strings.
235
 
 
236
 
        :param env: An option dict defining additional configuration options or
237
 
            overriding existing ones.
238
 
 
239
 
        :param _ref_stack: Private list containing the options being
240
 
            expanded to detect loops.
241
 
 
242
 
        :returns: The flatten list of expanded strings.
243
 
        """
244
 
        # expand options in each value separately flattening lists
245
 
        result = []
246
 
        for s in slist:
247
 
            value = self._expand_options_in_string(s, env, _ref_stack)
248
 
            if isinstance(value, list):
249
 
                result.extend(value)
250
 
            else:
251
 
                result.append(value)
252
 
        return result
253
 
 
254
 
    def _expand_options_in_string(self, string, env=None, _ref_stack=None):
255
 
        """Expand options in the string in the configuration context.
256
 
 
257
 
        :param string: The string to be expanded.
258
 
 
259
 
        :param env: An option dict defining additional configuration options or
260
 
            overriding existing ones.
261
 
 
262
 
        :param _ref_stack: Private list containing the options being
263
 
            expanded to detect loops.
264
 
 
265
 
        :returns: The expanded string.
266
 
        """
267
 
        if string is None:
268
 
            # Not much to expand there
269
 
            return None
270
 
        if _ref_stack is None:
271
 
            # What references are currently resolved (to detect loops)
272
 
            _ref_stack = []
273
 
        if self.option_ref_re is None:
274
 
            # We want to match the most embedded reference first (i.e. for
275
 
            # '{{foo}}' we will get '{foo}',
276
 
            # for '{bar{baz}}' we will get '{baz}'
277
 
            self.option_ref_re = re.compile('({[^{}]+})')
278
 
        result = string
279
 
        # We need to iterate until no more refs appear ({{foo}} will need two
280
 
        # iterations for example).
281
 
        while True:
282
 
            raw_chunks = self.option_ref_re.split(result)
283
 
            if len(raw_chunks) == 1:
284
 
                # Shorcut the trivial case: no refs
285
 
                return result
286
 
            chunks = []
287
 
            list_value = False
288
 
            # Split will isolate refs so that every other chunk is a ref
289
 
            chunk_is_ref = False
290
 
            for chunk in raw_chunks:
291
 
                if not chunk_is_ref:
292
 
                    if chunk:
293
 
                        # Keep only non-empty strings (or we get bogus empty
294
 
                        # slots when a list value is involved).
295
 
                        chunks.append(chunk)
296
 
                    chunk_is_ref = True
297
 
                else:
298
 
                    name = chunk[1:-1]
299
 
                    if name in _ref_stack:
300
 
                        raise errors.OptionExpansionLoop(string, _ref_stack)
301
 
                    _ref_stack.append(name)
302
 
                    value = self._expand_option(name, env, _ref_stack)
303
 
                    if value is None:
304
 
                        raise errors.ExpandingUnknownOption(name, string)
305
 
                    if isinstance(value, list):
306
 
                        list_value = True
307
 
                        chunks.extend(value)
308
 
                    else:
309
 
                        chunks.append(value)
310
 
                    _ref_stack.pop()
311
 
                    chunk_is_ref = False
312
 
            if list_value:
313
 
                # Once a list appears as the result of an expansion, all
314
 
                # callers will get a list result. This allows a consistent
315
 
                # behavior even when some options in the expansion chain
316
 
                # defined as strings (no comma in their value) but their
317
 
                # expanded value is a list.
318
 
                return self._expand_options_in_list(chunks, env, _ref_stack)
319
 
            else:
320
 
                result = ''.join(chunks)
321
 
        return result
322
 
 
323
 
    def _expand_option(self, name, env, _ref_stack):
324
 
        if env is not None and name in env:
325
 
            # Special case, values provided in env takes precedence over
326
 
            # anything else
327
 
            value = env[name]
328
 
        else:
329
 
            # FIXME: This is a limited implementation, what we really need is a
330
 
            # way to query the bzr config for the value of an option,
331
 
            # respecting the scope rules (That is, once we implement fallback
332
 
            # configs, getting the option value should restart from the top
333
 
            # config, not the current one) -- vila 20101222
334
 
            value = self.get_user_option(name, expand=False)
335
 
            if isinstance(value, list):
336
 
                value = self._expand_options_in_list(value, env, _ref_stack)
337
 
            else:
338
 
                value = self._expand_options_in_string(value, env, _ref_stack)
339
 
        return value
340
 
 
341
185
    def _get_user_option(self, option_name):
342
186
        """Template method to provide a user option."""
343
187
        return None
344
188
 
345
 
    def get_user_option(self, option_name, expand=None):
346
 
        """Get a generic option - no special process, no default.
347
 
 
348
 
        :param option_name: The queried option.
349
 
 
350
 
        :param expand: Whether options references should be expanded.
351
 
 
352
 
        :returns: The value of the option.
353
 
        """
354
 
        if expand is None:
355
 
            expand = _get_expand_default_value()
356
 
        value = self._get_user_option(option_name)
357
 
        if expand:
358
 
            if isinstance(value, list):
359
 
                value = self._expand_options_in_list(value)
360
 
            elif isinstance(value, dict):
361
 
                trace.warning('Cannot expand "%s":'
362
 
                              ' Dicts do not support option expansion'
363
 
                              % (option_name,))
364
 
            else:
365
 
                value = self._expand_options_in_string(value)
366
 
        return value
367
 
 
368
 
    def get_user_option_as_bool(self, option_name, expand=None):
 
189
    def get_user_option(self, option_name):
 
190
        """Get a generic option - no special process, no default."""
 
191
        return self._get_user_option(option_name)
 
192
 
 
193
    def get_user_option_as_bool(self, option_name):
369
194
        """Get a generic option as a boolean - no special process, no default.
370
195
 
371
196
        :return None if the option doesn't exist or its value can't be
372
197
            interpreted as a boolean. Returns True or False otherwise.
373
198
        """
374
 
        s = self.get_user_option(option_name, expand=expand)
 
199
        s = self._get_user_option(option_name)
375
200
        if s is None:
376
201
            # The option doesn't exist
377
202
            return None
382
207
                          s, option_name)
383
208
        return val
384
209
 
385
 
    def get_user_option_as_list(self, option_name, expand=None):
 
210
    def get_user_option_as_list(self, option_name):
386
211
        """Get a generic option as a list - no special process, no default.
387
212
 
388
213
        :return None if the option doesn't exist. Returns the value as a list
389
214
            otherwise.
390
215
        """
391
 
        l = self.get_user_option(option_name, expand=expand)
 
216
        l = self._get_user_option(option_name)
392
217
        if isinstance(l, (str, unicode)):
393
 
            # A single value, most probably the user forgot (or didn't care to
394
 
            # add) the final ','
 
218
            # A single value, most probably the user forgot the final ','
395
219
            l = [l]
396
220
        return l
397
221
 
441
265
        the concrete policy type is checked, and finally
442
266
        $EMAIL is examined.
443
267
        If no username can be found, errors.NoWhoami exception is raised.
 
268
 
 
269
        TODO: Check it's reasonably well-formed.
444
270
        """
445
271
        v = os.environ.get('BZR_EMAIL')
446
272
        if v:
447
273
            return v.decode(osutils.get_user_encoding())
 
274
 
448
275
        v = self._get_user_id()
449
276
        if v:
450
277
            return v
 
278
 
451
279
        v = os.environ.get('EMAIL')
452
280
        if v:
453
281
            return v.decode(osutils.get_user_encoding())
454
 
        name, email = _auto_user_id()
455
 
        if name and email:
456
 
            return '%s <%s>' % (name, email)
457
 
        elif email:
458
 
            return email
 
282
 
459
283
        raise errors.NoWhoami()
460
284
 
461
285
    def ensure_username(self):
527
351
        else:
528
352
            return True
529
353
 
530
 
    def get_merge_tools(self):
531
 
        tools = {}
532
 
        for (oname, value, section, conf_id, parser) in self._get_options():
533
 
            if oname.startswith('bzr.mergetool.'):
534
 
                tool_name = oname[len('bzr.mergetool.'):]
535
 
                tools[tool_name] = value
536
 
        trace.mutter('loaded merge tools: %r' % tools)
537
 
        return tools
538
 
 
539
 
    def find_merge_tool(self, name):
540
 
        # We fake a defaults mechanism here by checking if the given name can 
541
 
        # be found in the known_merge_tools if it's not found in the config.
542
 
        # This should be done through the proposed config defaults mechanism
543
 
        # when it becomes available in the future.
544
 
        command_line = (self.get_user_option('bzr.mergetool.%s' % name,
545
 
                                             expand=False)
546
 
                        or mergetools.known_merge_tools.get(name, None))
547
 
        return command_line
548
 
 
549
354
 
550
355
class IniBasedConfig(Config):
551
356
    """A configuration policy that draws from ini files."""
639
444
        """Override this to define the section used by the config."""
640
445
        return "DEFAULT"
641
446
 
642
 
    def _get_sections(self, name=None):
643
 
        """Returns an iterator of the sections specified by ``name``.
644
 
 
645
 
        :param name: The section name. If None is supplied, the default
646
 
            configurations are yielded.
647
 
 
648
 
        :return: A tuple (name, section, config_id) for all sections that will
649
 
            be walked by user_get_option() in the 'right' order. The first one
650
 
            is where set_user_option() will update the value.
651
 
        """
652
 
        parser = self._get_parser()
653
 
        if name is not None:
654
 
            yield (name, parser[name], self.config_id())
655
 
        else:
656
 
            # No section name has been given so we fallback to the configobj
657
 
            # itself which holds the variables defined outside of any section.
658
 
            yield (None, parser, self.config_id())
659
 
 
660
 
    def _get_options(self, sections=None):
661
 
        """Return an ordered list of (name, value, section, config_id) tuples.
662
 
 
663
 
        All options are returned with their associated value and the section
664
 
        they appeared in. ``config_id`` is a unique identifier for the
665
 
        configuration file the option is defined in.
666
 
 
667
 
        :param sections: Default to ``_get_matching_sections`` if not
668
 
            specified. This gives a better control to daughter classes about
669
 
            which sections should be searched. This is a list of (name,
670
 
            configobj) tuples.
671
 
        """
672
 
        opts = []
673
 
        if sections is None:
674
 
            parser = self._get_parser()
675
 
            sections = []
676
 
            for (section_name, _) in self._get_matching_sections():
677
 
                try:
678
 
                    section = parser[section_name]
679
 
                except KeyError:
680
 
                    # This could happen for an empty file for which we define a
681
 
                    # DEFAULT section. FIXME: Force callers to provide sections
682
 
                    # instead ? -- vila 20100930
683
 
                    continue
684
 
                sections.append((section_name, section))
685
 
        config_id = self.config_id()
686
 
        for (section_name, section) in sections:
687
 
            for (name, value) in section.iteritems():
688
 
                yield (name, parser._quote(value), section_name,
689
 
                       config_id, parser)
690
 
 
691
447
    def _get_option_policy(self, section, option_name):
692
448
        """Return the policy for the given (section, option_name) pair."""
693
449
        return POLICY_NONE
780
536
    def _get_nickname(self):
781
537
        return self.get_user_option('nickname')
782
538
 
783
 
    def remove_user_option(self, option_name, section_name=None):
784
 
        """Remove a user option and save the configuration file.
785
 
 
786
 
        :param option_name: The option to be removed.
787
 
 
788
 
        :param section_name: The section the option is defined in, default to
789
 
            the default section.
790
 
        """
791
 
        self.reload()
792
 
        parser = self._get_parser()
793
 
        if section_name is None:
794
 
            section = parser
795
 
        else:
796
 
            section = parser[section_name]
797
 
        try:
798
 
            del section[option_name]
799
 
        except KeyError:
800
 
            raise errors.NoSuchConfigOption(option_name)
801
 
        self._write_config_file()
802
 
 
803
539
    def _write_config_file(self):
804
540
        if self.file_name is None:
805
541
            raise AssertionError('We cannot save, self.file_name is None')
842
578
    def __init__(self, file_name):
843
579
        super(LockableConfig, self).__init__(file_name=file_name)
844
580
        self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
845
 
        # FIXME: It doesn't matter that we don't provide possible_transports
846
 
        # below since this is currently used only for local config files ;
847
 
        # local transports are not shared. But if/when we start using
848
 
        # LockableConfig for other kind of transports, we will need to reuse
849
 
        # whatever connection is already established -- vila 20100929
850
581
        self.transport = transport.get_transport(self.dir)
851
582
        self._lock = lockdir.LockDir(self.transport, 'lock')
852
583
 
873
604
    def break_lock(self):
874
605
        self._lock.break_lock()
875
606
 
876
 
    @needs_write_lock
877
 
    def remove_user_option(self, option_name, section_name=None):
878
 
        super(LockableConfig, self).remove_user_option(option_name,
879
 
                                                       section_name)
880
 
 
881
607
    def _write_config_file(self):
882
608
        if self._lock is None or not self._lock.is_held:
883
609
            # NB: if the following exception is raised it probably means a
892
618
    def __init__(self):
893
619
        super(GlobalConfig, self).__init__(file_name=config_filename())
894
620
 
895
 
    def config_id(self):
896
 
        return 'bazaar'
897
 
 
898
621
    @classmethod
899
622
    def from_string(cls, str_or_unicode, save=False):
900
623
        """Create a config object from a string.
944
667
        self._write_config_file()
945
668
 
946
669
 
947
 
    def _get_sections(self, name=None):
948
 
        """See IniBasedConfig._get_sections()."""
949
 
        parser = self._get_parser()
950
 
        # We don't give access to options defined outside of any section, we
951
 
        # used the DEFAULT section by... default.
952
 
        if name in (None, 'DEFAULT'):
953
 
            # This could happen for an empty file where the DEFAULT section
954
 
            # doesn't exist yet. So we force DEFAULT when yielding
955
 
            name = 'DEFAULT'
956
 
            if 'DEFAULT' not in parser:
957
 
               parser['DEFAULT']= {}
958
 
        yield (name, parser[name], self.config_id())
959
 
 
960
 
    @needs_write_lock
961
 
    def remove_user_option(self, option_name, section_name=None):
962
 
        if section_name is None:
963
 
            # We need to force the default section.
964
 
            section_name = 'DEFAULT'
965
 
        # We need to avoid the LockableConfig implementation or we'll lock
966
 
        # twice
967
 
        super(LockableConfig, self).remove_user_option(option_name,
968
 
                                                       section_name)
969
 
 
970
 
 
971
670
class LocationConfig(LockableConfig):
972
671
    """A configuration object that gives the policy for a location."""
973
672
 
981
680
            location = urlutils.local_path_from_url(location)
982
681
        self.location = location
983
682
 
984
 
    def config_id(self):
985
 
        return 'locations'
986
 
 
987
683
    @classmethod
988
684
    def from_string(cls, str_or_unicode, location, save=False):
989
685
        """Create a config object from a string.
1021
717
            names = zip(location_names, section_names)
1022
718
            matched = True
1023
719
            for name in names:
1024
 
                if not fnmatch.fnmatch(name[0], name[1]):
 
720
                if not fnmatch(name[0], name[1]):
1025
721
                    matched = False
1026
722
                    break
1027
723
            if not matched:
1032
728
                continue
1033
729
            matches.append((len(section_names), section,
1034
730
                            '/'.join(location_names[len(section_names):])))
1035
 
        # put the longest (aka more specific) locations first
1036
731
        matches.sort(reverse=True)
1037
732
        sections = []
1038
733
        for (length, section, extra_path) in matches:
1045
740
                pass
1046
741
        return sections
1047
742
 
1048
 
    def _get_sections(self, name=None):
1049
 
        """See IniBasedConfig._get_sections()."""
1050
 
        # We ignore the name here as the only sections handled are named with
1051
 
        # the location path and we don't expose embedded sections either.
1052
 
        parser = self._get_parser()
1053
 
        for name, extra_path in self._get_matching_sections():
1054
 
            yield (name, parser[name], self.config_id())
1055
 
 
1056
743
    def _get_option_policy(self, section, option_name):
1057
744
        """Return the policy for the given (section, option_name) pair."""
1058
745
        # check for the old 'recurse=False' flag
1137
824
                               self._get_branch_data_config,
1138
825
                               self._get_global_config)
1139
826
 
1140
 
    def config_id(self):
1141
 
        return 'branch'
1142
 
 
1143
827
    def _get_branch_data_config(self):
1144
828
        if self._branch_data_config is None:
1145
829
            self._branch_data_config = TreeConfig(self.branch)
1146
 
            self._branch_data_config.config_id = self.config_id
1147
830
        return self._branch_data_config
1148
831
 
1149
832
    def _get_location_config(self):
1217
900
                return value
1218
901
        return None
1219
902
 
1220
 
    def _get_sections(self, name=None):
1221
 
        """See IniBasedConfig.get_sections()."""
1222
 
        for source in self.option_sources:
1223
 
            for section in source()._get_sections(name):
1224
 
                yield section
1225
 
 
1226
 
    def _get_options(self, sections=None):
1227
 
        opts = []
1228
 
        # First the locations options
1229
 
        for option in self._get_location_config()._get_options():
1230
 
            yield option
1231
 
        # Then the branch options
1232
 
        branch_config = self._get_branch_data_config()
1233
 
        if sections is None:
1234
 
            sections = [('DEFAULT', branch_config._get_parser())]
1235
 
        # FIXME: We shouldn't have to duplicate the code in IniBasedConfig but
1236
 
        # Config itself has no notion of sections :( -- vila 20101001
1237
 
        config_id = self.config_id()
1238
 
        for (section_name, section) in sections:
1239
 
            for (name, value) in section.iteritems():
1240
 
                yield (name, value, section_name,
1241
 
                       config_id, branch_config._get_parser())
1242
 
        # Then the global options
1243
 
        for option in self._get_global_config()._get_options():
1244
 
            yield option
1245
 
 
1246
903
    def set_user_option(self, name, value, store=STORE_BRANCH,
1247
904
        warn_masked=False):
1248
905
        if store == STORE_BRANCH:
1266
923
                        trace.warning('Value "%s" is masked by "%s" from'
1267
924
                                      ' branch.conf', value, mask_value)
1268
925
 
1269
 
    def remove_user_option(self, option_name, section_name=None):
1270
 
        self._get_branch_data_config().remove_option(option_name, section_name)
1271
 
 
1272
926
    def _gpg_signing_command(self):
1273
927
        """See Config.gpg_signing_command."""
1274
928
        return self._get_safe_value('_gpg_signing_command')
1308
962
            parent_dir = os.path.dirname(path)
1309
963
            if not os.path.isdir(parent_dir):
1310
964
                trace.mutter('creating config parent directory: %r', parent_dir)
1311
 
                os.mkdir(parent_dir)
 
965
            os.mkdir(parent_dir)
1312
966
        trace.mutter('creating config directory: %r', path)
1313
967
        os.mkdir(path)
1314
968
        osutils.copy_ownership_from_path(path)
1317
971
def config_dir():
1318
972
    """Return per-user configuration directory.
1319
973
 
1320
 
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1321
 
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1322
 
    that will be used instead.
 
974
    By default this is ~/.bazaar/
1323
975
 
1324
976
    TODO: Global option --config-dir to override this.
1325
977
    """
1326
978
    base = os.environ.get('BZR_HOME', None)
1327
979
    if sys.platform == 'win32':
1328
 
        # environ variables on Windows are in user encoding/mbcs. So decode
1329
 
        # before using one
1330
 
        if base is not None:
1331
 
            base = base.decode('mbcs')
1332
980
        if base is None:
1333
981
            base = win32utils.get_appdata_location_unicode()
1334
982
        if base is None:
1335
983
            base = os.environ.get('HOME', None)
1336
 
            if base is not None:
1337
 
                base = base.decode('mbcs')
1338
984
        if base is None:
1339
985
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1340
986
                                  ' or HOME set')
1341
987
        return osutils.pathjoin(base, 'bazaar', '2.0')
1342
 
    elif sys.platform == 'darwin':
1343
 
        if base is None:
1344
 
            # this takes into account $HOME
1345
 
            base = os.path.expanduser("~")
1346
 
        return osutils.pathjoin(base, '.bazaar')
1347
988
    else:
1348
989
        if base is None:
1349
 
 
1350
 
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1351
 
            if xdg_dir is None:
1352
 
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1353
 
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1354
 
            if osutils.isdir(xdg_dir):
1355
 
                trace.mutter(
1356
 
                    "Using configuration in XDG directory %s." % xdg_dir)
1357
 
                return xdg_dir
1358
 
 
1359
990
            base = os.path.expanduser("~")
1360
991
        return osutils.pathjoin(base, ".bazaar")
1361
992
 
1407
1038
        return os.path.expanduser('~/.cache')
1408
1039
 
1409
1040
 
1410
 
def _get_default_mail_domain():
1411
 
    """If possible, return the assumed default email domain.
1412
 
 
1413
 
    :returns: string mail domain, or None.
1414
 
    """
1415
 
    if sys.platform == 'win32':
1416
 
        # No implementation yet; patches welcome
1417
 
        return None
1418
 
    try:
1419
 
        f = open('/etc/mailname')
1420
 
    except (IOError, OSError), e:
1421
 
        return None
1422
 
    try:
1423
 
        domain = f.read().strip()
1424
 
        return domain
1425
 
    finally:
1426
 
        f.close()
1427
 
 
1428
 
 
1429
 
def _auto_user_id():
1430
 
    """Calculate automatic user identification.
1431
 
 
1432
 
    :returns: (realname, email), either of which may be None if they can't be
1433
 
    determined.
1434
 
 
1435
 
    Only used when none is set in the environment or the id file.
1436
 
 
1437
 
    This only returns an email address if we can be fairly sure the 
1438
 
    address is reasonable, ie if /etc/mailname is set on unix.
1439
 
 
1440
 
    This doesn't use the FQDN as the default domain because that may be 
1441
 
    slow, and it doesn't use the hostname alone because that's not normally 
1442
 
    a reasonable address.
1443
 
    """
1444
 
    if sys.platform == 'win32':
1445
 
        # No implementation to reliably determine Windows default mail
1446
 
        # address; please add one.
1447
 
        return None, None
1448
 
 
1449
 
    default_mail_domain = _get_default_mail_domain()
1450
 
    if not default_mail_domain:
1451
 
        return None, None
1452
 
 
1453
 
    import pwd
1454
 
    uid = os.getuid()
1455
 
    try:
1456
 
        w = pwd.getpwuid(uid)
1457
 
    except KeyError:
1458
 
        mutter('no passwd entry for uid %d?' % uid)
1459
 
        return None, None
1460
 
 
1461
 
    # we try utf-8 first, because on many variants (like Linux),
1462
 
    # /etc/passwd "should" be in utf-8, and because it's unlikely to give
1463
 
    # false positives.  (many users will have their user encoding set to
1464
 
    # latin-1, which cannot raise UnicodeError.)
1465
 
    try:
1466
 
        gecos = w.pw_gecos.decode('utf-8')
1467
 
        encoding = 'utf-8'
1468
 
    except UnicodeError:
1469
 
        try:
1470
 
            encoding = osutils.get_user_encoding()
1471
 
            gecos = w.pw_gecos.decode(encoding)
1472
 
        except UnicodeError, e:
1473
 
            mutter("cannot decode passwd entry %s" % w)
1474
 
            return None, None
1475
 
    try:
1476
 
        username = w.pw_name.decode(encoding)
1477
 
    except UnicodeError, e:
1478
 
        mutter("cannot decode passwd entry %s" % w)
1479
 
        return None, None
1480
 
 
1481
 
    comma = gecos.find(',')
1482
 
    if comma == -1:
1483
 
        realname = gecos
1484
 
    else:
1485
 
        realname = gecos[:comma]
1486
 
 
1487
 
    return realname, (username + '@' + default_mail_domain)
1488
 
 
1489
 
 
1490
1041
def parse_username(username):
1491
1042
    """Parse e-mail username and return a (name, address) tuple."""
1492
1043
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1535
1086
 
1536
1087
    def set_option(self, value, name, section=None):
1537
1088
        """Set a per-branch configuration option"""
1538
 
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
1539
 
        # higher levels providing the right lock -- vila 20101004
1540
1089
        self.branch.lock_write()
1541
1090
        try:
1542
1091
            self._config.set_option(value, name, section)
1543
1092
        finally:
1544
1093
            self.branch.unlock()
1545
1094
 
1546
 
    def remove_option(self, option_name, section_name=None):
1547
 
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
1548
 
        # higher levels providing the right lock -- vila 20101004
1549
 
        self.branch.lock_write()
1550
 
        try:
1551
 
            self._config.remove_option(option_name, section_name)
1552
 
        finally:
1553
 
            self.branch.unlock()
1554
 
 
1555
1095
 
1556
1096
class AuthenticationConfig(object):
1557
1097
    """The authentication configuration file based on a ini file.
2000
1540
    """A Config that reads/writes a config file on a Transport.
2001
1541
 
2002
1542
    It is a low-level object that considers config data to be name/value pairs
2003
 
    that may be associated with a section.  Assigning meaning to these values
2004
 
    is done at higher levels like TreeConfig.
 
1543
    that may be associated with a section.  Assigning meaning to the these
 
1544
    values is done at higher levels like TreeConfig.
2005
1545
    """
2006
1546
 
2007
1547
    def __init__(self, transport, filename):
2040
1580
            configobj.setdefault(section, {})[name] = value
2041
1581
        self._set_configobj(configobj)
2042
1582
 
2043
 
    def remove_option(self, option_name, section_name=None):
2044
 
        configobj = self._get_configobj()
2045
 
        if section_name is None:
2046
 
            del configobj[option_name]
2047
 
        else:
2048
 
            del configobj[section_name][option_name]
2049
 
        self._set_configobj(configobj)
2050
 
 
2051
1583
    def _get_config_file(self):
2052
1584
        try:
2053
1585
            return StringIO(self._transport.get_bytes(self._filename))
2066
1598
        configobj.write(out_file)
2067
1599
        out_file.seek(0)
2068
1600
        self._transport.put_file(self._filename, out_file)
2069
 
 
2070
 
 
2071
 
class cmd_config(commands.Command):
2072
 
    __doc__ = """Display, set or remove a configuration option.
2073
 
 
2074
 
    Display the active value for a given option.
2075
 
 
2076
 
    If --all is specified, NAME is interpreted as a regular expression and all
2077
 
    matching options are displayed mentioning their scope. The active value
2078
 
    that bzr will take into account is the first one displayed for each option.
2079
 
 
2080
 
    If no NAME is given, --all .* is implied.
2081
 
 
2082
 
    Setting a value is achieved by using name=value without spaces. The value
2083
 
    is set in the most relevant scope and can be checked by displaying the
2084
 
    option again.
2085
 
    """
2086
 
 
2087
 
    takes_args = ['name?']
2088
 
 
2089
 
    takes_options = [
2090
 
        'directory',
2091
 
        # FIXME: This should be a registry option so that plugins can register
2092
 
        # their own config files (or not) -- vila 20101002
2093
 
        commands.Option('scope', help='Reduce the scope to the specified'
2094
 
                        ' configuration file',
2095
 
                        type=unicode),
2096
 
        commands.Option('all',
2097
 
            help='Display all the defined values for the matching options.',
2098
 
            ),
2099
 
        commands.Option('remove', help='Remove the option from'
2100
 
                        ' the configuration file'),
2101
 
        ]
2102
 
 
2103
 
    @commands.display_command
2104
 
    def run(self, name=None, all=False, directory=None, scope=None,
2105
 
            remove=False):
2106
 
        if directory is None:
2107
 
            directory = '.'
2108
 
        directory = urlutils.normalize_url(directory)
2109
 
        if remove and all:
2110
 
            raise errors.BzrError(
2111
 
                '--all and --remove are mutually exclusive.')
2112
 
        elif remove:
2113
 
            # Delete the option in the given scope
2114
 
            self._remove_config_option(name, directory, scope)
2115
 
        elif name is None:
2116
 
            # Defaults to all options
2117
 
            self._show_matching_options('.*', directory, scope)
2118
 
        else:
2119
 
            try:
2120
 
                name, value = name.split('=', 1)
2121
 
            except ValueError:
2122
 
                # Display the option(s) value(s)
2123
 
                if all:
2124
 
                    self._show_matching_options(name, directory, scope)
2125
 
                else:
2126
 
                    self._show_value(name, directory, scope)
2127
 
            else:
2128
 
                if all:
2129
 
                    raise errors.BzrError(
2130
 
                        'Only one option can be set.')
2131
 
                # Set the option value
2132
 
                self._set_config_option(name, value, directory, scope)
2133
 
 
2134
 
    def _get_configs(self, directory, scope=None):
2135
 
        """Iterate the configurations specified by ``directory`` and ``scope``.
2136
 
 
2137
 
        :param directory: Where the configurations are derived from.
2138
 
 
2139
 
        :param scope: A specific config to start from.
2140
 
        """
2141
 
        if scope is not None:
2142
 
            if scope == 'bazaar':
2143
 
                yield GlobalConfig()
2144
 
            elif scope == 'locations':
2145
 
                yield LocationConfig(directory)
2146
 
            elif scope == 'branch':
2147
 
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2148
 
                    directory)
2149
 
                yield br.get_config()
2150
 
        else:
2151
 
            try:
2152
 
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2153
 
                    directory)
2154
 
                yield br.get_config()
2155
 
            except errors.NotBranchError:
2156
 
                yield LocationConfig(directory)
2157
 
                yield GlobalConfig()
2158
 
 
2159
 
    def _show_value(self, name, directory, scope):
2160
 
        displayed = False
2161
 
        for c in self._get_configs(directory, scope):
2162
 
            if displayed:
2163
 
                break
2164
 
            for (oname, value, section, conf_id, parser) in c._get_options():
2165
 
                if name == oname:
2166
 
                    # Display only the first value and exit
2167
 
 
2168
 
                    # FIXME: We need to use get_user_option to take policies
2169
 
                    # into account and we need to make sure the option exists
2170
 
                    # too (hence the two for loops), this needs a better API
2171
 
                    # -- vila 20101117
2172
 
                    value = c.get_user_option(name)
2173
 
                    # Quote the value appropriately
2174
 
                    value = parser._quote(value)
2175
 
                    self.outf.write('%s\n' % (value,))
2176
 
                    displayed = True
2177
 
                    break
2178
 
        if not displayed:
2179
 
            raise errors.NoSuchConfigOption(name)
2180
 
 
2181
 
    def _show_matching_options(self, name, directory, scope):
2182
 
        name = re.compile(name)
2183
 
        # We want any error in the regexp to be raised *now* so we need to
2184
 
        # avoid the delay introduced by the lazy regexp.
2185
 
        name._compile_and_collapse()
2186
 
        cur_conf_id = None
2187
 
        cur_section = None
2188
 
        for c in self._get_configs(directory, scope):
2189
 
            for (oname, value, section, conf_id, parser) in c._get_options():
2190
 
                if name.search(oname):
2191
 
                    if cur_conf_id != conf_id:
2192
 
                        # Explain where the options are defined
2193
 
                        self.outf.write('%s:\n' % (conf_id,))
2194
 
                        cur_conf_id = conf_id
2195
 
                        cur_section = None
2196
 
                    if (section not in (None, 'DEFAULT')
2197
 
                        and cur_section != section):
2198
 
                        # Display the section if it's not the default (or only)
2199
 
                        # one.
2200
 
                        self.outf.write('  [%s]\n' % (section,))
2201
 
                        cur_section = section
2202
 
                    self.outf.write('  %s = %s\n' % (oname, value))
2203
 
 
2204
 
    def _set_config_option(self, name, value, directory, scope):
2205
 
        for conf in self._get_configs(directory, scope):
2206
 
            conf.set_user_option(name, value)
2207
 
            break
2208
 
        else:
2209
 
            raise errors.NoSuchConfig(scope)
2210
 
 
2211
 
    def _remove_config_option(self, name, directory, scope):
2212
 
        if name is None:
2213
 
            raise errors.BzrCommandError(
2214
 
                '--remove expects an option to remove.')
2215
 
        removed = False
2216
 
        for conf in self._get_configs(directory, scope):
2217
 
            for (section_name, section, conf_id) in conf._get_sections():
2218
 
                if scope is not None and conf_id != scope:
2219
 
                    # Not the right configuration file
2220
 
                    continue
2221
 
                if name in section:
2222
 
                    if conf_id != conf.config_id():
2223
 
                        conf = self._get_configs(directory, conf_id).next()
2224
 
                    # We use the first section in the first config where the
2225
 
                    # option is defined to remove it
2226
 
                    conf.remove_user_option(name, section_name)
2227
 
                    removed = True
2228
 
                    break
2229
 
            break
2230
 
        else:
2231
 
            raise errors.NoSuchConfig(scope)
2232
 
        if not removed:
2233
 
            raise errors.NoSuchConfigOption(name)