~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Jelmer Vernooij
  • Date: 2011-02-24 16:09:47 UTC
  • mto: (5582.10.69 weave-fmt-plugin)
  • mto: This revision was merged to the branch mainline in revision 5688.
  • Revision ID: jelmer@samba.org-20110224160947-e7kqclxnjif28v5q
merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
129
129
STORE_BRANCH = 3
130
130
STORE_GLOBAL = 4
131
131
 
132
 
_ConfigObj = None
133
 
def ConfigObj(*args, **kwargs):
134
 
    global _ConfigObj
135
 
    if _ConfigObj is None:
136
 
        class ConfigObj(configobj.ConfigObj):
137
 
 
138
 
            def get_bool(self, section, key):
139
 
                return self[section].as_bool(key)
140
 
 
141
 
            def get_value(self, section, name):
142
 
                # Try [] for the old DEFAULT section.
143
 
                if section == "DEFAULT":
144
 
                    try:
145
 
                        return self[name]
146
 
                    except KeyError:
147
 
                        pass
148
 
                return self[section][name]
149
 
        _ConfigObj = ConfigObj
150
 
    return _ConfigObj(*args, **kwargs)
 
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
151
176
 
152
177
 
153
178
class Config(object):
189
214
    def _get_signing_policy(self):
190
215
        """Template method to override signature creation policy."""
191
216
 
 
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
            try:
 
283
                raw_chunks = self.option_ref_re.split(result)
 
284
            except TypeError:
 
285
                import pdb; pdb.set_trace()
 
286
            if len(raw_chunks) == 1:
 
287
                # Shorcut the trivial case: no refs
 
288
                return result
 
289
            chunks = []
 
290
            list_value = False
 
291
            # Split will isolate refs so that every other chunk is a ref
 
292
            chunk_is_ref = False
 
293
            for chunk in raw_chunks:
 
294
                if not chunk_is_ref:
 
295
                    if chunk:
 
296
                        # Keep only non-empty strings (or we get bogus empty
 
297
                        # slots when a list value is involved).
 
298
                        chunks.append(chunk)
 
299
                    chunk_is_ref = True
 
300
                else:
 
301
                    name = chunk[1:-1]
 
302
                    if name in _ref_stack:
 
303
                        raise errors.OptionExpansionLoop(string, _ref_stack)
 
304
                    _ref_stack.append(name)
 
305
                    value = self._expand_option(name, env, _ref_stack)
 
306
                    if value is None:
 
307
                        raise errors.ExpandingUnknownOption(name, string)
 
308
                    if isinstance(value, list):
 
309
                        list_value = True
 
310
                        chunks.extend(value)
 
311
                    else:
 
312
                        chunks.append(value)
 
313
                    _ref_stack.pop()
 
314
                    chunk_is_ref = False
 
315
            if list_value:
 
316
                # Once a list appears as the result of an expansion, all
 
317
                # callers will get a list result. This allows a consistent
 
318
                # behavior even when some options in the expansion chain
 
319
                # defined as strings (no comma in their value) but their
 
320
                # expanded value is a list.
 
321
                return self._expand_options_in_list(chunks, env, _ref_stack)
 
322
            else:
 
323
                result = ''.join(chunks)
 
324
        return result
 
325
 
 
326
    def _expand_option(self, name, env, _ref_stack):
 
327
        if env is not None and name in env:
 
328
            # Special case, values provided in env takes precedence over
 
329
            # anything else
 
330
            value = env[name]
 
331
        else:
 
332
            # FIXME: This is a limited implementation, what we really need is a
 
333
            # way to query the bzr config for the value of an option,
 
334
            # respecting the scope rules (That is, once we implement fallback
 
335
            # configs, getting the option value should restart from the top
 
336
            # config, not the current one) -- vila 20101222
 
337
            value = self.get_user_option(name, expand=False)
 
338
            if isinstance(value, list):
 
339
                value = self._expand_options_in_list(value, env, _ref_stack)
 
340
            else:
 
341
                value = self._expand_options_in_string(value, env, _ref_stack)
 
342
        return value
 
343
 
192
344
    def _get_user_option(self, option_name):
193
345
        """Template method to provide a user option."""
194
346
        return None
195
347
 
196
 
    def get_user_option(self, option_name):
197
 
        """Get a generic option - no special process, no default."""
198
 
        return self._get_user_option(option_name)
199
 
 
200
 
    def get_user_option_as_bool(self, option_name):
 
348
    def get_user_option(self, option_name, expand=None):
 
349
        """Get a generic option - no special process, no default.
 
350
 
 
351
        :param option_name: The queried option.
 
352
 
 
353
        :param expand: Whether options references should be expanded.
 
354
 
 
355
        :returns: The value of the option.
 
356
        """
 
357
        if expand is None:
 
358
            expand = _get_expand_default_value()
 
359
        value = self._get_user_option(option_name)
 
360
        if expand:
 
361
            if isinstance(value, list):
 
362
                value = self._expand_options_in_list(value)
 
363
            elif isinstance(value, dict):
 
364
                trace.warning('Cannot expand "%s":'
 
365
                              ' Dicts do not support option expansion'
 
366
                              % (option_name,))
 
367
            else:
 
368
                value = self._expand_options_in_string(value)
 
369
        return value
 
370
 
 
371
    def get_user_option_as_bool(self, option_name, expand=None):
201
372
        """Get a generic option as a boolean - no special process, no default.
202
373
 
203
374
        :return None if the option doesn't exist or its value can't be
204
375
            interpreted as a boolean. Returns True or False otherwise.
205
376
        """
206
 
        s = self._get_user_option(option_name)
 
377
        s = self.get_user_option(option_name, expand=expand)
207
378
        if s is None:
208
379
            # The option doesn't exist
209
380
            return None
214
385
                          s, option_name)
215
386
        return val
216
387
 
217
 
    def get_user_option_as_list(self, option_name):
 
388
    def get_user_option_as_list(self, option_name, expand=None):
218
389
        """Get a generic option as a list - no special process, no default.
219
390
 
220
391
        :return None if the option doesn't exist. Returns the value as a list
221
392
            otherwise.
222
393
        """
223
 
        l = self._get_user_option(option_name)
 
394
        l = self.get_user_option(option_name, expand=expand)
224
395
        if isinstance(l, (str, unicode)):
225
 
            # A single value, most probably the user forgot the final ','
 
396
            # A single value, most probably the user forgot (or didn't care to
 
397
            # add) the final ','
226
398
            l = [l]
227
399
        return l
228
400
 
372
544
        # be found in the known_merge_tools if it's not found in the config.
373
545
        # This should be done through the proposed config defaults mechanism
374
546
        # when it becomes available in the future.
375
 
        command_line = (self.get_user_option('bzr.mergetool.%s' % name) or
376
 
                        mergetools.known_merge_tools.get(name, None))
 
547
        command_line = (self.get_user_option('bzr.mergetool.%s' % name,
 
548
                                             expand=False)
 
549
                        or mergetools.known_merge_tools.get(name, None))
377
550
        return command_line
378
551
 
379
552
 
672
845
    def __init__(self, file_name):
673
846
        super(LockableConfig, self).__init__(file_name=file_name)
674
847
        self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
 
848
        # FIXME: It doesn't matter that we don't provide possible_transports
 
849
        # below since this is currently used only for local config files ;
 
850
        # local transports are not shared. But if/when we start using
 
851
        # LockableConfig for other kind of transports, we will need to reuse
 
852
        # whatever connection is already established -- vila 20100929
675
853
        self.transport = transport.get_transport(self.dir)
676
854
        self._lock = lockdir.LockDir(self.transport, 'lock')
677
855