~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Jelmer Vernooij
  • Date: 2012-02-21 12:51:25 UTC
  • mfrom: (6468.3.1 bzr)
  • mto: This revision was merged to the branch mainline in revision 6519.
  • Revision ID: jelmer@samba.org-20120221125125-7cpkwjmvf3aj2d9x
MergeĀ lp:~jelmer/bzr/use-tree-iter-children

Show diffs side-by-side

added added

removed removed

Lines of Context:
195
195
        return self[section][name]
196
196
 
197
197
 
 
198
# FIXME: Until we can guarantee that each config file is loaded once and
 
199
# only once for a given bzrlib session, we don't want to re-read the file every
 
200
# time we query for an option so we cache the value (bad ! watch out for tests
 
201
# needing to restore the proper value). -- vila 20110219
 
202
_expand_default_value = None
 
203
def _get_expand_default_value():
 
204
    global _expand_default_value
 
205
    if _expand_default_value is not None:
 
206
        return _expand_default_value
 
207
    conf = GlobalConfig()
 
208
    # Note that we must not use None for the expand value below or we'll run
 
209
    # into infinite recursion. Using False really would be quite silly ;)
 
210
    expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
 
211
    if expand is None:
 
212
        # This is an opt-in feature, you *really* need to clearly say you want
 
213
        # to activate it !
 
214
        expand = False
 
215
    _expand_default_value = expand
 
216
    return expand
 
217
 
 
218
 
198
219
class Config(object):
199
220
    """A configuration policy - what username, editor, gpg needs etc."""
200
221
 
205
226
        """Returns a unique ID for the config."""
206
227
        raise NotImplementedError(self.config_id)
207
228
 
 
229
    @deprecated_method(deprecated_in((2, 4, 0)))
 
230
    def get_editor(self):
 
231
        """Get the users pop up editor."""
 
232
        raise NotImplementedError
 
233
 
208
234
    def get_change_editor(self, old_tree, new_tree):
209
235
        from bzrlib import diff
210
236
        cmd = self._get_change_editor()
347
373
        """Template method to provide a user option."""
348
374
        return None
349
375
 
350
 
    def get_user_option(self, option_name, expand=True):
 
376
    def get_user_option(self, option_name, expand=None):
351
377
        """Get a generic option - no special process, no default.
352
378
 
353
379
        :param option_name: The queried option.
356
382
 
357
383
        :returns: The value of the option.
358
384
        """
 
385
        if expand is None:
 
386
            expand = _get_expand_default_value()
359
387
        value = self._get_user_option(option_name)
360
388
        if expand:
361
389
            if isinstance(value, list):
609
637
        for (oname, value, section, conf_id, parser) in self._get_options():
610
638
            if oname.startswith('bzr.mergetool.'):
611
639
                tool_name = oname[len('bzr.mergetool.'):]
612
 
                tools[tool_name] = self.get_user_option(oname, False)
 
640
                tools[tool_name] = self.get_user_option(oname)
613
641
        trace.mutter('loaded merge tools: %r' % tools)
614
642
        return tools
615
643
 
1051
1079
        conf._create_from_string(str_or_unicode, save)
1052
1080
        return conf
1053
1081
 
 
1082
    @deprecated_method(deprecated_in((2, 4, 0)))
 
1083
    def get_editor(self):
 
1084
        return self._get_user_option('editor')
 
1085
 
1054
1086
    @needs_write_lock
1055
1087
    def set_user_option(self, option, value):
1056
1088
        """Save option and its value in the configuration."""
2142
2174
 
2143
2175
        It may be set to a location, or None.
2144
2176
 
2145
 
        This policy affects all branches contained by this control dir, except
2146
 
        for those under repositories.
 
2177
        This policy affects all branches contained by this bzrdir, except for
 
2178
        those under repositories.
2147
2179
        """
2148
2180
        if self._config is None:
2149
2181
            raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
2157
2189
 
2158
2190
        This will either be a location, or None.
2159
2191
 
2160
 
        This policy affects all branches contained by this control dir, except
2161
 
        for those under repositories.
 
2192
        This policy affects all branches contained by this bzrdir, except for
 
2193
        those under repositories.
2162
2194
        """
2163
2195
        if self._config is None:
2164
2196
            return None
2398
2430
                value = self.default()
2399
2431
                if not isinstance(value, unicode):
2400
2432
                    raise AssertionError(
2401
 
                        "Callable default value for '%s' should be unicode"
2402
 
                        % (self.name))
 
2433
                    'Callable default values should be unicode')
2403
2434
            else:
2404
2435
                value = self.default
2405
2436
        return value
2406
2437
 
2407
 
    def get_help_topic(self):
2408
 
        return self.name
2409
 
 
2410
2438
    def get_help_text(self, additional_see_also=None, plain=True):
2411
2439
        result = self.help
2412
2440
        from bzrlib import help_topics
2957
2985
            # Report concurrent updates in an ad-hoc way. This should only
2958
2986
            # occurs when different processes try to update the same option
2959
2987
            # which is not supported (as in: the config framework is not meant
2960
 
            # to be used as a sharing mechanism).
 
2988
            # to be used a sharing mechanism).
2961
2989
            if expected != reloaded:
2962
2990
                if actual is _DeletedOption:
2963
2991
                    actual = '<DELETED>'
2983
3011
    mutable_section_class = MutableSection
2984
3012
 
2985
3013
    def __init__(self):
2986
 
        # Which sections need to be saved (by section id). We use a dict here
2987
 
        # so the dirty sections can be shared by multiple callers.
2988
 
        self.dirty_sections = {}
 
3014
        # Which sections need to be saved
 
3015
        self.dirty_sections = []
2989
3016
 
2990
3017
    def is_loaded(self):
2991
3018
        """Returns True if the Store has been loaded.
3034
3061
        raise NotImplementedError(self.save)
3035
3062
 
3036
3063
    def _need_saving(self):
3037
 
        for s in self.dirty_sections.values():
 
3064
        for s in self.dirty_sections:
3038
3065
            if s.orig:
3039
3066
                # At least one dirty section contains a modification
3040
3067
                return True
3054
3081
        # get_mutable_section() call below.
3055
3082
        self.unload()
3056
3083
        # Apply the changes from the preserved dirty sections
3057
 
        for section_id, dirty in dirty_sections.iteritems():
3058
 
            clean = self.get_mutable_section(section_id)
 
3084
        for dirty in dirty_sections:
 
3085
            clean = self.get_mutable_section(dirty.id)
3059
3086
            clean.apply_changes(dirty, self)
3060
3087
        # Everything is clean now
3061
 
        self.dirty_sections = {}
 
3088
        self.dirty_sections = []
3062
3089
 
3063
3090
    def save_changes(self):
3064
3091
        """Saves the Store to persistent storage if changes occurred.
3144
3171
 
3145
3172
    def unload(self):
3146
3173
        self._config_obj = None
3147
 
        self.dirty_sections = {}
 
3174
        self.dirty_sections = []
3148
3175
 
3149
3176
    def _load_content(self):
3150
3177
        """Load the config file bytes.
3198
3225
        if not self._need_saving():
3199
3226
            return
3200
3227
        # Preserve the current version
3201
 
        dirty_sections = dict(self.dirty_sections.items())
 
3228
        current = self._config_obj
 
3229
        dirty_sections = list(self.dirty_sections)
3202
3230
        self.apply_changes(dirty_sections)
3203
3231
        # Save to the persistent storage
3204
3232
        self.save()
3239
3267
        except errors.NoSuchFile:
3240
3268
            # The file doesn't exist, let's pretend it was empty
3241
3269
            self._load_from_string('')
3242
 
        if section_id in self.dirty_sections:
3243
 
            # We already created a mutable section for this id
3244
 
            return self.dirty_sections[section_id]
3245
3270
        if section_id is None:
3246
3271
            section = self._config_obj
3247
3272
        else:
3248
3273
            section = self._config_obj.setdefault(section_id, {})
3249
3274
        mutable_section = self.mutable_section_class(section_id, section)
3250
3275
        # All mutable sections can become dirty
3251
 
        self.dirty_sections[section_id] = mutable_section
 
3276
        self.dirty_sections.append(mutable_section)
3252
3277
        return mutable_section
3253
3278
 
3254
3279
    def quote(self, value):
3444
3469
 
3445
3470
class LocationSection(Section):
3446
3471
 
3447
 
    def __init__(self, section, extra_path, branch_name=None):
 
3472
    def __init__(self, section, extra_path):
3448
3473
        super(LocationSection, self).__init__(section.id, section.options)
3449
3474
        self.extra_path = extra_path
3450
 
        if branch_name is None:
3451
 
            branch_name = ''
3452
3475
        self.locals = {'relpath': extra_path,
3453
 
                       'basename': urlutils.basename(extra_path),
3454
 
                       'branchname': branch_name}
 
3476
                       'basename': urlutils.basename(extra_path)}
3455
3477
 
3456
3478
    def get(self, name, default=None, expand=True):
3457
3479
        value = super(LocationSection, self).get(name, default)
3527
3549
 
3528
3550
    def __init__(self, store, location):
3529
3551
        super(LocationMatcher, self).__init__(store)
3530
 
        url, params = urlutils.split_segment_parameters(location)
3531
3552
        if location.startswith('file://'):
3532
3553
            location = urlutils.local_path_from_url(location)
3533
3554
        self.location = location
3534
 
        branch_name = params.get('branch')
3535
 
        if branch_name is None:
3536
 
            self.branch_name = urlutils.basename(self.location)
3537
 
        else:
3538
 
            self.branch_name = urlutils.unescape(branch_name)
3539
3555
 
3540
3556
    def _get_matching_sections(self):
3541
3557
        """Get all sections matching ``location``."""
3567
3583
            while True:
3568
3584
                section = iter_all_sections.next()
3569
3585
                if section_id == section.id:
3570
 
                    section = LocationSection(section, extra_path,
3571
 
                                              self.branch_name)
3572
 
                    matching_sections.append((length, section))
 
3586
                    matching_sections.append(
 
3587
                        (length, LocationSection(section, extra_path)))
3573
3588
                    break
3574
3589
        return matching_sections
3575
3590
 
3640
3655
            for store, section in sections():
3641
3656
                yield store, section
3642
3657
 
3643
 
    def get(self, name, expand=True, convert=True):
 
3658
    def get(self, name, expand=None, convert=True):
3644
3659
        """Return the *first* option value found in the sections.
3645
3660
 
3646
3661
        This is where we guarantee that sections coming from Store are loaded
3659
3674
        :returns: The value of the option.
3660
3675
        """
3661
3676
        # FIXME: No caching of options nor sections yet -- vila 20110503
 
3677
        if expand is None:
 
3678
            expand = _get_expand_default_value()
3662
3679
        value = None
3663
3680
        found_store = None # Where the option value has been found
3664
3681
        # If the option is registered, it may provide additional info about