~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

Compare URLs in RemoteRepository.__eq__, rather than '_client' attributes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
 
1
# Copyright (C) 2005, 2007 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
 
3
#            and others
3
4
#
4
5
# This program is free software; you can redistribute it and/or modify
5
6
# it under the terms of the GNU General Public License as published by
18
19
"""Configuration that affects the behaviour of Bazaar.
19
20
 
20
21
Currently this configuration resides in ~/.bazaar/bazaar.conf
21
 
and ~/.bazaar/branches.conf, which is written to by bzr.
 
22
and ~/.bazaar/locations.conf, which is written to by bzr.
22
23
 
23
24
In bazaar.conf the following options may be set:
24
25
[DEFAULT]
27
28
check_signatures=require|ignore|check-available(default)
28
29
create_signatures=always|never|when-required(default)
29
30
gpg_signing_command=name-of-program
 
31
log_format=name-of-format
30
32
 
31
 
in branches.conf, you specify the url of a branch and options for it.
 
33
in locations.conf, you specify the url of a branch and options for it.
32
34
Wildcards may be used - * and ? as normal in shell completion. Options
33
 
set in both bazaar.conf and branches.conf are overriden by the branches.conf
 
35
set in both bazaar.conf and locations.conf are overridden by the locations.conf
34
36
setting.
35
37
[/home/robertc/source]
36
38
recurse=False|True(default)
37
39
email= as above
38
 
check_signatures= as abive 
 
40
check_signatures= as above 
39
41
create_signatures= as above.
40
42
 
41
43
explanation of options
48
50
create_signatures - this option controls whether bzr will always create 
49
51
                    gpg signatures, never create them, or create them if the
50
52
                    branch is configured to require them.
51
 
                    NB: This option is planned, but not implemented yet.
 
53
log_format - this option sets the default log format.  Possible values are
 
54
             long, short, line, or a plugin can register new formats.
 
55
 
 
56
In bazaar.conf you can also define aliases in the ALIASES sections, example
 
57
 
 
58
[ALIASES]
 
59
lastlog=log --line -r-10..-1
 
60
ll=log --line -r-10..-1
 
61
h=help
 
62
up=pull
52
63
"""
53
64
 
54
 
 
55
 
import errno
56
65
import os
57
66
import sys
 
67
 
 
68
from bzrlib.lazy_import import lazy_import
 
69
lazy_import(globals(), """
 
70
import errno
58
71
from fnmatch import fnmatch
59
72
import re
 
73
from StringIO import StringIO
60
74
 
61
75
import bzrlib
62
 
import bzrlib.errors as errors
63
 
from bzrlib.osutils import pathjoin
64
 
from bzrlib.trace import mutter
 
76
from bzrlib import (
 
77
    errors,
 
78
    osutils,
 
79
    symbol_versioning,
 
80
    trace,
 
81
    urlutils,
 
82
    win32utils,
 
83
    )
65
84
import bzrlib.util.configobj.configobj as configobj
66
 
from StringIO import StringIO
 
85
""")
 
86
 
 
87
from bzrlib.trace import mutter, warning
 
88
 
67
89
 
68
90
CHECK_IF_POSSIBLE=0
69
91
CHECK_ALWAYS=1
70
92
CHECK_NEVER=2
71
93
 
72
94
 
 
95
SIGN_WHEN_REQUIRED=0
 
96
SIGN_ALWAYS=1
 
97
SIGN_NEVER=2
 
98
 
 
99
 
 
100
POLICY_NONE = 0
 
101
POLICY_NORECURSE = 1
 
102
POLICY_APPENDPATH = 2
 
103
 
 
104
_policy_name = {
 
105
    POLICY_NONE: None,
 
106
    POLICY_NORECURSE: 'norecurse',
 
107
    POLICY_APPENDPATH: 'appendpath',
 
108
    }
 
109
_policy_value = {
 
110
    None: POLICY_NONE,
 
111
    'none': POLICY_NONE,
 
112
    'norecurse': POLICY_NORECURSE,
 
113
    'appendpath': POLICY_APPENDPATH,
 
114
    }
 
115
 
 
116
 
 
117
STORE_LOCATION = POLICY_NONE
 
118
STORE_LOCATION_NORECURSE = POLICY_NORECURSE
 
119
STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
 
120
STORE_BRANCH = 3
 
121
STORE_GLOBAL = 4
 
122
 
 
123
 
73
124
class ConfigObj(configobj.ConfigObj):
74
125
 
75
126
    def get_bool(self, section, key):
76
 
        val = self[section][key].lower()
77
 
        if val in ('1', 'yes', 'true', 'on'):
78
 
            return True
79
 
        elif val in ('0', 'no', 'false', 'off'):
80
 
            return False
81
 
        else:
82
 
            raise ValueError("Value %r is not boolean" % val)
 
127
        return self[section].as_bool(key)
83
128
 
84
129
    def get_value(self, section, name):
85
130
        # Try [] for the old DEFAULT section.
101
146
    def _get_signature_checking(self):
102
147
        """Template method to override signature checking policy."""
103
148
 
 
149
    def _get_signing_policy(self):
 
150
        """Template method to override signature creation policy."""
 
151
 
104
152
    def _get_user_option(self, option_name):
105
153
        """Template method to provide a user option."""
106
154
        return None
120
168
        """See gpg_signing_command()."""
121
169
        return None
122
170
 
 
171
    def log_format(self):
 
172
        """What log format should be used"""
 
173
        result = self._log_format()
 
174
        if result is None:
 
175
            result = "long"
 
176
        return result
 
177
 
 
178
    def _log_format(self):
 
179
        """See log_format()."""
 
180
        return None
 
181
 
123
182
    def __init__(self):
124
183
        super(Config, self).__init__()
125
184
 
143
202
    
144
203
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
145
204
        
146
 
        $BZREMAIL can be set to override this, then
 
205
        $BZR_EMAIL can be set to override this (as well as the
 
206
        deprecated $BZREMAIL), then
147
207
        the concrete policy type is checked, and finally
148
208
        $EMAIL is examined.
149
209
        If none is found, a reasonable default is (hopefully)
151
211
    
152
212
        TODO: Check it's reasonably well-formed.
153
213
        """
 
214
        v = os.environ.get('BZR_EMAIL')
 
215
        if v:
 
216
            return v.decode(bzrlib.user_encoding)
154
217
        v = os.environ.get('BZREMAIL')
155
218
        if v:
 
219
            warning('BZREMAIL is deprecated in favor of BZR_EMAIL. Please update your configuration.')
156
220
            return v.decode(bzrlib.user_encoding)
157
221
    
158
222
        v = self._get_user_id()
176
240
            return policy
177
241
        return CHECK_IF_POSSIBLE
178
242
 
 
243
    def signing_policy(self):
 
244
        """What is the current policy for signature checking?."""
 
245
        policy = self._get_signing_policy()
 
246
        if policy is not None:
 
247
            return policy
 
248
        return SIGN_WHEN_REQUIRED
 
249
 
179
250
    def signature_needed(self):
180
251
        """Is a signature needed when committing ?."""
181
 
        policy = self._get_signature_checking()
182
 
        if policy == CHECK_ALWAYS:
 
252
        policy = self._get_signing_policy()
 
253
        if policy is None:
 
254
            policy = self._get_signature_checking()
 
255
            if policy is not None:
 
256
                warning("Please use create_signatures, not check_signatures "
 
257
                        "to set signing policy.")
 
258
            if policy == CHECK_ALWAYS:
 
259
                return True
 
260
        elif policy == SIGN_ALWAYS:
183
261
            return True
184
262
        return False
185
263
 
 
264
    def get_alias(self, value):
 
265
        return self._get_alias(value)
 
266
 
 
267
    def _get_alias(self, value):
 
268
        pass
 
269
 
 
270
    def get_nickname(self):
 
271
        return self._get_nickname()
 
272
 
 
273
    def _get_nickname(self):
 
274
        return None
 
275
 
186
276
 
187
277
class IniBasedConfig(Config):
188
278
    """A configuration policy that draws from ini files."""
195
285
        else:
196
286
            input = file
197
287
        try:
198
 
            self._parser = ConfigObj(input)
 
288
            self._parser = ConfigObj(input, encoding='utf-8')
199
289
        except configobj.ConfigObjError, e:
200
290
            raise errors.ParseConfigError(e.errors, e.config.filename)
201
291
        return self._parser
202
292
 
 
293
    def _get_matching_sections(self):
 
294
        """Return an ordered list of (section_name, extra_path) pairs.
 
295
 
 
296
        If the section contains inherited configuration, extra_path is
 
297
        a string containing the additional path components.
 
298
        """
 
299
        section = self._get_section()
 
300
        if section is not None:
 
301
            return [(section, '')]
 
302
        else:
 
303
            return []
 
304
 
203
305
    def _get_section(self):
204
306
        """Override this to define the section used by the config."""
205
307
        return "DEFAULT"
206
308
 
 
309
    def _get_option_policy(self, section, option_name):
 
310
        """Return the policy for the given (section, option_name) pair."""
 
311
        return POLICY_NONE
 
312
 
207
313
    def _get_signature_checking(self):
208
314
        """See Config._get_signature_checking."""
209
315
        policy = self._get_user_option('check_signatures')
210
316
        if policy:
211
317
            return self._string_to_signature_policy(policy)
212
318
 
 
319
    def _get_signing_policy(self):
 
320
        """See Config._get_signing_policy"""
 
321
        policy = self._get_user_option('create_signatures')
 
322
        if policy:
 
323
            return self._string_to_signing_policy(policy)
 
324
 
213
325
    def _get_user_id(self):
214
326
        """Get the user id from the 'email' key in the current section."""
215
327
        return self._get_user_option('email')
216
328
 
217
329
    def _get_user_option(self, option_name):
218
330
        """See Config._get_user_option."""
219
 
        try:
220
 
            return self._get_parser().get_value(self._get_section(),
221
 
                                                option_name)
222
 
        except KeyError:
223
 
            pass
 
331
        for (section, extra_path) in self._get_matching_sections():
 
332
            try:
 
333
                value = self._get_parser().get_value(section, option_name)
 
334
            except KeyError:
 
335
                continue
 
336
            policy = self._get_option_policy(section, option_name)
 
337
            if policy == POLICY_NONE:
 
338
                return value
 
339
            elif policy == POLICY_NORECURSE:
 
340
                # norecurse items only apply to the exact path
 
341
                if extra_path:
 
342
                    continue
 
343
                else:
 
344
                    return value
 
345
            elif policy == POLICY_APPENDPATH:
 
346
                if extra_path:
 
347
                    value = urlutils.join(value, extra_path)
 
348
                return value
 
349
            else:
 
350
                raise AssertionError('Unexpected config policy %r' % policy)
 
351
        else:
 
352
            return None
224
353
 
225
354
    def _gpg_signing_command(self):
226
355
        """See Config.gpg_signing_command."""
227
356
        return self._get_user_option('gpg_signing_command')
228
357
 
 
358
    def _log_format(self):
 
359
        """See Config.log_format."""
 
360
        return self._get_user_option('log_format')
 
361
 
229
362
    def __init__(self, get_filename):
230
363
        super(IniBasedConfig, self).__init__()
231
364
        self._get_filename = get_filename
246
379
        raise errors.BzrError("Invalid signatures policy '%s'"
247
380
                              % signature_string)
248
381
 
 
382
    def _string_to_signing_policy(self, signature_string):
 
383
        """Convert a string to a signing policy."""
 
384
        if signature_string.lower() == 'when-required':
 
385
            return SIGN_WHEN_REQUIRED
 
386
        if signature_string.lower() == 'never':
 
387
            return SIGN_NEVER
 
388
        if signature_string.lower() == 'always':
 
389
            return SIGN_ALWAYS
 
390
        raise errors.BzrError("Invalid signing policy '%s'"
 
391
                              % signature_string)
 
392
 
 
393
    def _get_alias(self, value):
 
394
        try:
 
395
            return self._get_parser().get_value("ALIASES", 
 
396
                                                value)
 
397
        except KeyError:
 
398
            pass
 
399
 
 
400
    def _get_nickname(self):
 
401
        return self.get_user_option('nickname')
 
402
 
249
403
 
250
404
class GlobalConfig(IniBasedConfig):
251
405
    """The configuration that should be used for a specific location."""
256
410
    def __init__(self):
257
411
        super(GlobalConfig, self).__init__(config_filename)
258
412
 
 
413
    def set_user_option(self, option, value):
 
414
        """Save option and its value in the configuration."""
 
415
        # FIXME: RBC 20051029 This should refresh the parser and also take a
 
416
        # file lock on bazaar.conf.
 
417
        conf_dir = os.path.dirname(self._get_filename())
 
418
        ensure_config_dir_exists(conf_dir)
 
419
        if 'DEFAULT' not in self._get_parser():
 
420
            self._get_parser()['DEFAULT'] = {}
 
421
        self._get_parser()['DEFAULT'][option] = value
 
422
        f = open(self._get_filename(), 'wb')
 
423
        self._get_parser().write(f)
 
424
        f.close()
 
425
 
259
426
 
260
427
class LocationConfig(IniBasedConfig):
261
428
    """A configuration object that gives the policy for a location."""
262
429
 
263
430
    def __init__(self, location):
264
 
        super(LocationConfig, self).__init__(branches_config_filename)
265
 
        self._global_config = None
 
431
        name_generator = locations_config_filename
 
432
        if (not os.path.exists(name_generator()) and 
 
433
                os.path.exists(branches_config_filename())):
 
434
            if sys.platform == 'win32':
 
435
                warning('Please rename %s to %s' 
 
436
                         % (branches_config_filename(),
 
437
                            locations_config_filename()))
 
438
            else:
 
439
                warning('Please rename ~/.bazaar/branches.conf'
 
440
                        ' to ~/.bazaar/locations.conf')
 
441
            name_generator = branches_config_filename
 
442
        super(LocationConfig, self).__init__(name_generator)
 
443
        # local file locations are looked up by local path, rather than
 
444
        # by file url. This is because the config file is a user
 
445
        # file, and we would rather not expose the user to file urls.
 
446
        if location.startswith('file://'):
 
447
            location = urlutils.local_path_from_url(location)
266
448
        self.location = location
267
449
 
268
 
    def _get_global_config(self):
269
 
        if self._global_config is None:
270
 
            self._global_config = GlobalConfig()
271
 
        return self._global_config
272
 
 
273
 
    def _get_section(self):
274
 
        """Get the section we should look in for config items.
275
 
 
276
 
        Returns None if none exists. 
277
 
        TODO: perhaps return a NullSection that thunks through to the 
278
 
              global config.
279
 
        """
 
450
    def _get_matching_sections(self):
 
451
        """Return an ordered list of section names matching this location."""
280
452
        sections = self._get_parser()
281
453
        location_names = self.location.split('/')
282
454
        if self.location.endswith('/'):
283
455
            del location_names[-1]
284
456
        matches=[]
285
457
        for section in sections:
286
 
            section_names = section.split('/')
 
458
            # location is a local path if possible, so we need
 
459
            # to convert 'file://' urls to local paths if necessary.
 
460
            # This also avoids having file:///path be a more exact
 
461
            # match than '/path'.
 
462
            if section.startswith('file://'):
 
463
                section_path = urlutils.local_path_from_url(section)
 
464
            else:
 
465
                section_path = section
 
466
            section_names = section_path.split('/')
287
467
            if section.endswith('/'):
288
468
                del section_names[-1]
289
469
            names = zip(location_names, section_names)
298
478
            # if section is longer, no match.
299
479
            if len(section_names) > len(location_names):
300
480
                continue
301
 
            # if path is longer, and recurse is not true, no match
302
 
            if len(section_names) < len(location_names):
303
 
                try:
304
 
                    if not self._get_parser().get_bool(section, 'recurse'):
305
 
                        continue
306
 
                except KeyError:
307
 
                    pass
308
 
            matches.append((len(section_names), section))
309
 
        if not len(matches):
310
 
            return None
 
481
            matches.append((len(section_names), section,
 
482
                            '/'.join(location_names[len(section_names):])))
311
483
        matches.sort(reverse=True)
312
 
        return matches[0][1]
313
 
 
314
 
    def _gpg_signing_command(self):
315
 
        """See Config.gpg_signing_command."""
316
 
        command = super(LocationConfig, self)._gpg_signing_command()
317
 
        if command is not None:
318
 
            return command
319
 
        return self._get_global_config()._gpg_signing_command()
320
 
 
321
 
    def _get_user_id(self):
322
 
        user_id = super(LocationConfig, self)._get_user_id()
323
 
        if user_id is not None:
324
 
            return user_id
325
 
        return self._get_global_config()._get_user_id()
326
 
 
327
 
    def _get_user_option(self, option_name):
328
 
        """See Config._get_user_option."""
329
 
        option_value = super(LocationConfig, 
330
 
                             self)._get_user_option(option_name)
331
 
        if option_value is not None:
332
 
            return option_value
333
 
        return self._get_global_config()._get_user_option(option_name)
334
 
 
335
 
    def _get_signature_checking(self):
336
 
        """See Config._get_signature_checking."""
337
 
        check = super(LocationConfig, self)._get_signature_checking()
338
 
        if check is not None:
339
 
            return check
340
 
        return self._get_global_config()._get_signature_checking()
341
 
 
342
 
    def _post_commit(self):
343
 
        """See Config.post_commit."""
344
 
        hook = self._get_user_option('post_commit')
345
 
        if hook is not None:
346
 
            return hook
347
 
        return self._get_global_config()._post_commit()
348
 
 
349
 
    def set_user_option(self, option, value):
 
484
        sections = []
 
485
        for (length, section, extra_path) in matches:
 
486
            sections.append((section, extra_path))
 
487
            # should we stop looking for parent configs here?
 
488
            try:
 
489
                if self._get_parser()[section].as_bool('ignore_parents'):
 
490
                    break
 
491
            except KeyError:
 
492
                pass
 
493
        return sections
 
494
 
 
495
    def _get_option_policy(self, section, option_name):
 
496
        """Return the policy for the given (section, option_name) pair."""
 
497
        # check for the old 'recurse=False' flag
 
498
        try:
 
499
            recurse = self._get_parser()[section].as_bool('recurse')
 
500
        except KeyError:
 
501
            recurse = True
 
502
        if not recurse:
 
503
            return POLICY_NORECURSE
 
504
 
 
505
        policy_key = option_name + ':policy'
 
506
        try:
 
507
            policy_name = self._get_parser()[section][policy_key]
 
508
        except KeyError:
 
509
            policy_name = None
 
510
 
 
511
        return _policy_value[policy_name]
 
512
 
 
513
    def _set_option_policy(self, section, option_name, option_policy):
 
514
        """Set the policy for the given option name in the given section."""
 
515
        # The old recurse=False option affects all options in the
 
516
        # section.  To handle multiple policies in the section, we
 
517
        # need to convert it to a policy_norecurse key.
 
518
        try:
 
519
            recurse = self._get_parser()[section].as_bool('recurse')
 
520
        except KeyError:
 
521
            pass
 
522
        else:
 
523
            symbol_versioning.warn(
 
524
                'The recurse option is deprecated as of 0.14.  '
 
525
                'The section "%s" has been converted to use policies.'
 
526
                % section,
 
527
                DeprecationWarning)
 
528
            del self._get_parser()[section]['recurse']
 
529
            if not recurse:
 
530
                for key in self._get_parser()[section].keys():
 
531
                    if not key.endswith(':policy'):
 
532
                        self._get_parser()[section][key +
 
533
                                                    ':policy'] = 'norecurse'
 
534
 
 
535
        policy_key = option_name + ':policy'
 
536
        policy_name = _policy_name[option_policy]
 
537
        if policy_name is not None:
 
538
            self._get_parser()[section][policy_key] = policy_name
 
539
        else:
 
540
            if policy_key in self._get_parser()[section]:
 
541
                del self._get_parser()[section][policy_key]
 
542
 
 
543
    def set_user_option(self, option, value, store=STORE_LOCATION):
350
544
        """Save option and its value in the configuration."""
 
545
        assert store in [STORE_LOCATION,
 
546
                         STORE_LOCATION_NORECURSE,
 
547
                         STORE_LOCATION_APPENDPATH], 'bad storage policy'
351
548
        # FIXME: RBC 20051029 This should refresh the parser and also take a
352
 
        # file lock on branches.conf.
 
549
        # file lock on locations.conf.
353
550
        conf_dir = os.path.dirname(self._get_filename())
354
551
        ensure_config_dir_exists(conf_dir)
355
552
        location = self.location
361
558
        elif location + '/' in self._get_parser():
362
559
            location = location + '/'
363
560
        self._get_parser()[location][option]=value
364
 
        self._get_parser().write()
 
561
        # the allowed values of store match the config policies
 
562
        self._set_option_policy(location, option, store)
 
563
        self._get_parser().write(file(self._get_filename(), 'wb'))
365
564
 
366
565
 
367
566
class BranchConfig(Config):
368
567
    """A configuration object giving the policy for a branch."""
369
568
 
 
569
    def _get_branch_data_config(self):
 
570
        if self._branch_data_config is None:
 
571
            self._branch_data_config = TreeConfig(self.branch)
 
572
        return self._branch_data_config
 
573
 
370
574
    def _get_location_config(self):
371
575
        if self._location_config is None:
372
576
            self._location_config = LocationConfig(self.branch.base)
373
577
        return self._location_config
374
578
 
 
579
    def _get_global_config(self):
 
580
        if self._global_config is None:
 
581
            self._global_config = GlobalConfig()
 
582
        return self._global_config
 
583
 
 
584
    def _get_best_value(self, option_name):
 
585
        """This returns a user option from local, tree or global config.
 
586
 
 
587
        They are tried in that order.  Use get_safe_value if trusted values
 
588
        are necessary.
 
589
        """
 
590
        for source in self.option_sources:
 
591
            value = getattr(source(), option_name)()
 
592
            if value is not None:
 
593
                return value
 
594
        return None
 
595
 
 
596
    def _get_safe_value(self, option_name):
 
597
        """This variant of get_best_value never returns untrusted values.
 
598
        
 
599
        It does not return values from the branch data, because the branch may
 
600
        not be controlled by the user.
 
601
 
 
602
        We may wish to allow locations.conf to control whether branches are
 
603
        trusted in the future.
 
604
        """
 
605
        for source in (self._get_location_config, self._get_global_config):
 
606
            value = getattr(source(), option_name)()
 
607
            if value is not None:
 
608
                return value
 
609
        return None
 
610
 
375
611
    def _get_user_id(self):
376
612
        """Return the full user id for the branch.
377
613
    
379
615
        This is looked up in the email controlfile for the branch.
380
616
        """
381
617
        try:
382
 
            return (self.branch.control_files.controlfile("email", "r") 
 
618
            return (self.branch.control_files.get_utf8("email") 
383
619
                    .read()
384
620
                    .decode(bzrlib.user_encoding)
385
621
                    .rstrip("\r\n"))
386
622
        except errors.NoSuchFile, e:
387
623
            pass
388
624
        
389
 
        return self._get_location_config()._get_user_id()
 
625
        return self._get_best_value('_get_user_id')
390
626
 
391
627
    def _get_signature_checking(self):
392
628
        """See Config._get_signature_checking."""
393
 
        return self._get_location_config()._get_signature_checking()
 
629
        return self._get_best_value('_get_signature_checking')
 
630
 
 
631
    def _get_signing_policy(self):
 
632
        """See Config._get_signing_policy."""
 
633
        return self._get_best_value('_get_signing_policy')
394
634
 
395
635
    def _get_user_option(self, option_name):
396
636
        """See Config._get_user_option."""
397
 
        return self._get_location_config()._get_user_option(option_name)
 
637
        for source in self.option_sources:
 
638
            value = source()._get_user_option(option_name)
 
639
            if value is not None:
 
640
                return value
 
641
        return None
 
642
 
 
643
    def set_user_option(self, name, value, store=STORE_BRANCH,
 
644
        warn_masked=False):
 
645
        if store == STORE_BRANCH:
 
646
            self._get_branch_data_config().set_option(value, name)
 
647
        elif store == STORE_GLOBAL:
 
648
            self._get_global_config().set_user_option(name, value)
 
649
        else:
 
650
            self._get_location_config().set_user_option(name, value, store)
 
651
        if not warn_masked:
 
652
            return
 
653
        if store in (STORE_GLOBAL, STORE_BRANCH):
 
654
            mask_value = self._get_location_config().get_user_option(name)
 
655
            if mask_value is not None:
 
656
                trace.warning('Value "%s" is masked by "%s" from'
 
657
                              ' locations.conf', value, mask_value)
 
658
            else:
 
659
                if store == STORE_GLOBAL:
 
660
                    branch_config = self._get_branch_data_config()
 
661
                    mask_value = branch_config.get_user_option(name)
 
662
                    if mask_value is not None:
 
663
                        trace.warning('Value "%s" is masked by "%s" from'
 
664
                                      ' branch.conf', value, mask_value)
 
665
 
398
666
 
399
667
    def _gpg_signing_command(self):
400
668
        """See Config.gpg_signing_command."""
401
 
        return self._get_location_config()._gpg_signing_command()
 
669
        return self._get_safe_value('_gpg_signing_command')
402
670
        
403
671
    def __init__(self, branch):
404
672
        super(BranchConfig, self).__init__()
405
673
        self._location_config = None
 
674
        self._branch_data_config = None
 
675
        self._global_config = None
406
676
        self.branch = branch
 
677
        self.option_sources = (self._get_location_config, 
 
678
                               self._get_branch_data_config,
 
679
                               self._get_global_config)
407
680
 
408
681
    def _post_commit(self):
409
682
        """See Config.post_commit."""
410
 
        return self._get_location_config()._post_commit()
 
683
        return self._get_safe_value('_post_commit')
 
684
 
 
685
    def _get_nickname(self):
 
686
        value = self._get_explicit_nickname()
 
687
        if value is not None:
 
688
            return value
 
689
        return urlutils.unescape(self.branch.base.split('/')[-2])
 
690
 
 
691
    def has_explicit_nickname(self):
 
692
        """Return true if a nickname has been explicitly assigned."""
 
693
        return self._get_explicit_nickname() is not None
 
694
 
 
695
    def _get_explicit_nickname(self):
 
696
        return self._get_best_value('_get_nickname')
 
697
 
 
698
    def _log_format(self):
 
699
        """See Config.log_format."""
 
700
        return self._get_best_value('_log_format')
411
701
 
412
702
 
413
703
def ensure_config_dir_exists(path=None):
438
728
    base = os.environ.get('BZR_HOME', None)
439
729
    if sys.platform == 'win32':
440
730
        if base is None:
441
 
            base = os.environ.get('APPDATA', None)
 
731
            base = win32utils.get_appdata_location_unicode()
442
732
        if base is None:
443
733
            base = os.environ.get('HOME', None)
444
734
        if base is None:
445
 
            raise BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
446
 
        return pathjoin(base, 'bazaar', '2.0')
 
735
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
 
736
        return osutils.pathjoin(base, 'bazaar', '2.0')
447
737
    else:
448
738
        # cygwin, linux, and darwin all have a $HOME directory
449
739
        if base is None:
450
740
            base = os.path.expanduser("~")
451
 
        return pathjoin(base, ".bazaar")
 
741
        return osutils.pathjoin(base, ".bazaar")
452
742
 
453
743
 
454
744
def config_filename():
455
745
    """Return per-user configuration ini file filename."""
456
 
    return pathjoin(config_dir(), 'bazaar.conf')
 
746
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
457
747
 
458
748
 
459
749
def branches_config_filename():
460
750
    """Return per-user configuration ini file filename."""
461
 
    return pathjoin(config_dir(), 'branches.conf')
 
751
    return osutils.pathjoin(config_dir(), 'branches.conf')
 
752
 
 
753
 
 
754
def locations_config_filename():
 
755
    """Return per-user configuration ini file filename."""
 
756
    return osutils.pathjoin(config_dir(), 'locations.conf')
 
757
 
 
758
 
 
759
def user_ignore_config_filename():
 
760
    """Return the user default ignore filename"""
 
761
    return osutils.pathjoin(config_dir(), 'ignore')
462
762
 
463
763
 
464
764
def _auto_user_id():
474
774
    """
475
775
    import socket
476
776
 
477
 
    # XXX: Any good way to get real user name on win32?
 
777
    if sys.platform == 'win32':
 
778
        name = win32utils.get_user_name_unicode()
 
779
        if name is None:
 
780
            raise errors.BzrError("Cannot autodetect user name.\n"
 
781
                                  "Please, set your name with command like:\n"
 
782
                                  'bzr whoami "Your Name <name@domain.com>"')
 
783
        host = win32utils.get_host_name_unicode()
 
784
        if host is None:
 
785
            host = socket.gethostname()
 
786
        return name, (name + '@' + host)
478
787
 
479
788
    try:
480
789
        import pwd
481
790
        uid = os.getuid()
482
791
        w = pwd.getpwuid(uid)
483
 
        gecos = w.pw_gecos.decode(bzrlib.user_encoding)
484
 
        username = w.pw_name.decode(bzrlib.user_encoding)
 
792
 
 
793
        # we try utf-8 first, because on many variants (like Linux),
 
794
        # /etc/passwd "should" be in utf-8, and because it's unlikely to give
 
795
        # false positives.  (many users will have their user encoding set to
 
796
        # latin-1, which cannot raise UnicodeError.)
 
797
        try:
 
798
            gecos = w.pw_gecos.decode('utf-8')
 
799
            encoding = 'utf-8'
 
800
        except UnicodeError:
 
801
            try:
 
802
                gecos = w.pw_gecos.decode(bzrlib.user_encoding)
 
803
                encoding = bzrlib.user_encoding
 
804
            except UnicodeError:
 
805
                raise errors.BzrCommandError('Unable to determine your name.  '
 
806
                   'Use "bzr whoami" to set it.')
 
807
        try:
 
808
            username = w.pw_name.decode(encoding)
 
809
        except UnicodeError:
 
810
            raise errors.BzrCommandError('Unable to determine your name.  '
 
811
                'Use "bzr whoami" to set it.')
 
812
 
485
813
        comma = gecos.find(',')
486
814
        if comma == -1:
487
815
            realname = gecos
492
820
 
493
821
    except ImportError:
494
822
        import getpass
495
 
        realname = username = getpass.getuser().decode(bzrlib.user_encoding)
 
823
        try:
 
824
            realname = username = getpass.getuser().decode(bzrlib.user_encoding)
 
825
        except UnicodeDecodeError:
 
826
            raise errors.BzrError("Can't decode username as %s." % \
 
827
                    bzrlib.user_encoding)
496
828
 
497
829
    return realname, (username + '@' + socket.gethostname())
498
830
 
509
841
    """
510
842
    m = re.search(r'[\w+.-]+@[\w+.-]+', e)
511
843
    if not m:
512
 
        raise errors.BzrError("%r doesn't seem to contain "
513
 
                              "a reasonable email address" % e)
 
844
        raise errors.NoEmailInUsername(e)
514
845
    return m.group(0)
515
846
 
516
 
class TreeConfig(object):
 
847
 
 
848
class TreeConfig(IniBasedConfig):
517
849
    """Branch configuration data associated with its contents, not location"""
518
850
    def __init__(self, branch):
519
851
        self.branch = branch
520
852
 
 
853
    def _get_parser(self, file=None):
 
854
        if file is not None:
 
855
            return IniBasedConfig._get_parser(file)
 
856
        return self._get_config()
 
857
 
521
858
    def _get_config(self):
522
859
        try:
523
 
            obj = ConfigObj(self.branch.control_files.controlfile('branch.conf',
524
 
                                                    'rb').readlines())
525
 
            obj.decode('UTF-8')
 
860
            obj = ConfigObj(self.branch.control_files.get('branch.conf'),
 
861
                            encoding='utf-8')
526
862
        except errors.NoSuchFile:
527
 
            obj = ConfigObj()
 
863
            obj = ConfigObj(encoding='utf=8')
528
864
        return obj
529
865
 
530
866
    def get_option(self, name, section=None, default=None):
533
869
            obj = self._get_config()
534
870
            try:
535
871
                if section is not None:
536
 
                    obj[section]
 
872
                    obj = obj[section]
537
873
                result = obj[name]
538
874
            except KeyError:
539
875
                result = default
555
891
                    cfg_obj[section] = {}
556
892
                    obj = cfg_obj[section]
557
893
            obj[name] = value
558
 
            cfg_obj.encode('UTF-8')
559
 
            out_file = StringIO(''.join([l+'\n' for l in cfg_obj.write()]))
 
894
            out_file = StringIO()
 
895
            cfg_obj.write(out_file)
560
896
            out_file.seek(0)
561
897
            self.branch.control_files.put('branch.conf', out_file)
562
898
        finally: