~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Michael Ellerman
  • Date: 2006-02-28 14:45:51 UTC
  • mto: (1558.1.18 Aaron's integration)
  • mto: This revision was merged to the branch mainline in revision 1586.
  • Revision ID: michael@ellerman.id.au-20060228144551-3d9941ecde4a0b0a
Update contrib/pwk for -p1 diffs from bzr

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
"""Configuration that affects the behaviour of Bazaar.
19
19
 
20
20
Currently this configuration resides in ~/.bazaar/bazaar.conf
21
 
and ~/.bazaar/locations.conf, which is written to by bzr.
 
21
and ~/.bazaar/branches.conf, which is written to by bzr.
22
22
 
23
23
In bazaar.conf the following options may be set:
24
24
[DEFAULT]
29
29
gpg_signing_command=name-of-program
30
30
log_format=name-of-format
31
31
 
32
 
in locations.conf, you specify the url of a branch and options for it.
 
32
in branches.conf, you specify the url of a branch and options for it.
33
33
Wildcards may be used - * and ? as normal in shell completion. Options
34
 
set in both bazaar.conf and locations.conf are overridden by the locations.conf
 
34
set in both bazaar.conf and branches.conf are overriden by the branches.conf
35
35
setting.
36
36
[/home/robertc/source]
37
37
recurse=False|True(default)
38
38
email= as above
39
 
check_signatures= as above 
 
39
check_signatures= as abive 
40
40
create_signatures= as above.
41
41
 
42
42
explanation of options
49
49
create_signatures - this option controls whether bzr will always create 
50
50
                    gpg signatures, never create them, or create them if the
51
51
                    branch is configured to require them.
 
52
                    NB: This option is planned, but not implemented yet.
52
53
log_format - This options set the default log format.  Options are long, 
53
54
             short, line, or a plugin can register new formats
54
55
 
63
64
 
64
65
 
65
66
import errno
 
67
import os
 
68
import sys
66
69
from fnmatch import fnmatch
67
 
import os
68
70
import re
69
 
import sys
70
 
from StringIO import StringIO
71
71
 
72
72
import bzrlib
73
73
import bzrlib.errors as errors
74
74
from bzrlib.osutils import pathjoin
75
 
from bzrlib.trace import mutter, warning
 
75
from bzrlib.trace import mutter
76
76
import bzrlib.util.configobj.configobj as configobj
77
 
 
 
77
from StringIO import StringIO
78
78
 
79
79
CHECK_IF_POSSIBLE=0
80
80
CHECK_ALWAYS=1
81
81
CHECK_NEVER=2
82
82
 
83
83
 
84
 
SIGN_WHEN_REQUIRED=0
85
 
SIGN_ALWAYS=1
86
 
SIGN_NEVER=2
87
 
 
88
 
 
89
84
class ConfigObj(configobj.ConfigObj):
90
85
 
91
86
    def get_bool(self, section, key):
111
106
    def _get_signature_checking(self):
112
107
        """Template method to override signature checking policy."""
113
108
 
114
 
    def _get_signing_policy(self):
115
 
        """Template method to override signature creation policy."""
116
 
 
117
109
    def _get_user_option(self, option_name):
118
110
        """Template method to provide a user option."""
119
111
        return None
200
192
            return policy
201
193
        return CHECK_IF_POSSIBLE
202
194
 
203
 
    def signing_policy(self):
204
 
        """What is the current policy for signature checking?."""
205
 
        policy = self._get_signing_policy()
206
 
        if policy is not None:
207
 
            return policy
208
 
        return SIGN_WHEN_REQUIRED
209
 
 
210
195
    def signature_needed(self):
211
196
        """Is a signature needed when committing ?."""
212
 
        policy = self._get_signing_policy()
213
 
        if policy is None:
214
 
            policy = self._get_signature_checking()
215
 
            if policy is not None:
216
 
                warning("Please use create_signatures, not check_signatures "
217
 
                        "to set signing policy.")
218
 
            if policy == CHECK_ALWAYS:
219
 
                return True
220
 
        elif policy == SIGN_ALWAYS:
 
197
        policy = self._get_signature_checking()
 
198
        if policy == CHECK_ALWAYS:
221
199
            return True
222
200
        return False
223
201
 
227
205
    def _get_alias(self, value):
228
206
        pass
229
207
 
230
 
    def get_nickname(self):
231
 
        return self._get_nickname()
232
 
 
233
 
    def _get_nickname(self):
234
 
        return None
235
 
 
236
208
 
237
209
class IniBasedConfig(Config):
238
210
    """A configuration policy that draws from ini files."""
245
217
        else:
246
218
            input = file
247
219
        try:
248
 
            self._parser = ConfigObj(input, encoding='utf-8')
 
220
            self._parser = ConfigObj(input)
249
221
        except configobj.ConfigObjError, e:
250
222
            raise errors.ParseConfigError(e.errors, e.config.filename)
251
223
        return self._parser
260
232
        if policy:
261
233
            return self._string_to_signature_policy(policy)
262
234
 
263
 
    def _get_signing_policy(self):
264
 
        """See Config._get_signing_policy"""
265
 
        policy = self._get_user_option('create_signatures')
266
 
        if policy:
267
 
            return self._string_to_signing_policy(policy)
268
 
 
269
235
    def _get_user_id(self):
270
236
        """Get the user id from the 'email' key in the current section."""
271
237
        return self._get_user_option('email')
306
272
        raise errors.BzrError("Invalid signatures policy '%s'"
307
273
                              % signature_string)
308
274
 
309
 
    def _string_to_signing_policy(self, signature_string):
310
 
        """Convert a string to a signing policy."""
311
 
        if signature_string.lower() == 'when-required':
312
 
            return SIGN_WHEN_REQUIRED
313
 
        if signature_string.lower() == 'never':
314
 
            return SIGN_NEVER
315
 
        if signature_string.lower() == 'always':
316
 
            return SIGN_ALWAYS
317
 
        raise errors.BzrError("Invalid signing policy '%s'"
318
 
                              % signature_string)
319
 
 
320
275
    def _get_alias(self, value):
321
276
        try:
322
277
            return self._get_parser().get_value("ALIASES", 
324
279
        except KeyError:
325
280
            pass
326
281
 
327
 
    def _get_nickname(self):
328
 
        return self.get_user_option('nickname')
329
 
 
330
282
 
331
283
class GlobalConfig(IniBasedConfig):
332
284
    """The configuration that should be used for a specific location."""
337
289
    def __init__(self):
338
290
        super(GlobalConfig, self).__init__(config_filename)
339
291
 
340
 
    def set_user_option(self, option, value):
341
 
        """Save option and its value in the configuration."""
342
 
        # FIXME: RBC 20051029 This should refresh the parser and also take a
343
 
        # file lock on bazaar.conf.
344
 
        conf_dir = os.path.dirname(self._get_filename())
345
 
        ensure_config_dir_exists(conf_dir)
346
 
        if 'DEFAULT' not in self._get_parser():
347
 
            self._get_parser()['DEFAULT'] = {}
348
 
        self._get_parser()['DEFAULT'][option] = value
349
 
        f = open(self._get_filename(), 'wb')
350
 
        self._get_parser().write(f)
351
 
        f.close()
352
 
 
353
292
 
354
293
class LocationConfig(IniBasedConfig):
355
294
    """A configuration object that gives the policy for a location."""
356
295
 
357
296
    def __init__(self, location):
358
 
        name_generator = locations_config_filename
359
 
        if (not os.path.exists(name_generator()) and 
360
 
                os.path.exists(branches_config_filename())):
361
 
            if sys.platform == 'win32':
362
 
                warning('Please rename %s to %s' 
363
 
                         % (branches_config_filename(),
364
 
                            locations_config_filename()))
365
 
            else:
366
 
                warning('Please rename ~/.bazaar/branches.conf'
367
 
                        ' to ~/.bazaar/locations.conf')
368
 
            name_generator = branches_config_filename
369
 
        super(LocationConfig, self).__init__(name_generator)
 
297
        super(LocationConfig, self).__init__(branches_config_filename)
 
298
        self._global_config = None
370
299
        self.location = location
371
300
 
 
301
    def _get_global_config(self):
 
302
        if self._global_config is None:
 
303
            self._global_config = GlobalConfig()
 
304
        return self._global_config
 
305
 
372
306
    def _get_section(self):
373
307
        """Get the section we should look in for config items.
374
308
 
400
334
            # if path is longer, and recurse is not true, no match
401
335
            if len(section_names) < len(location_names):
402
336
                try:
403
 
                    if not self._get_parser()[section].as_bool('recurse'):
 
337
                    if not self._get_parser().get_bool(section, 'recurse'):
404
338
                        continue
405
339
                except KeyError:
406
340
                    pass
410
344
        matches.sort(reverse=True)
411
345
        return matches[0][1]
412
346
 
 
347
    def _gpg_signing_command(self):
 
348
        """See Config.gpg_signing_command."""
 
349
        command = super(LocationConfig, self)._gpg_signing_command()
 
350
        if command is not None:
 
351
            return command
 
352
        return self._get_global_config()._gpg_signing_command()
 
353
 
 
354
    def _log_format(self):
 
355
        """See Config.log_format."""
 
356
        command = super(LocationConfig, self)._log_format()
 
357
        if command is not None:
 
358
            return command
 
359
        return self._get_global_config()._log_format()
 
360
 
 
361
    def _get_user_id(self):
 
362
        user_id = super(LocationConfig, self)._get_user_id()
 
363
        if user_id is not None:
 
364
            return user_id
 
365
        return self._get_global_config()._get_user_id()
 
366
 
 
367
    def _get_user_option(self, option_name):
 
368
        """See Config._get_user_option."""
 
369
        option_value = super(LocationConfig, 
 
370
                             self)._get_user_option(option_name)
 
371
        if option_value is not None:
 
372
            return option_value
 
373
        return self._get_global_config()._get_user_option(option_name)
 
374
 
 
375
    def _get_signature_checking(self):
 
376
        """See Config._get_signature_checking."""
 
377
        check = super(LocationConfig, self)._get_signature_checking()
 
378
        if check is not None:
 
379
            return check
 
380
        return self._get_global_config()._get_signature_checking()
 
381
 
 
382
    def _post_commit(self):
 
383
        """See Config.post_commit."""
 
384
        hook = self._get_user_option('post_commit')
 
385
        if hook is not None:
 
386
            return hook
 
387
        return self._get_global_config()._post_commit()
 
388
 
413
389
    def set_user_option(self, option, value):
414
390
        """Save option and its value in the configuration."""
415
391
        # FIXME: RBC 20051029 This should refresh the parser and also take a
416
 
        # file lock on locations.conf.
 
392
        # file lock on branches.conf.
417
393
        conf_dir = os.path.dirname(self._get_filename())
418
394
        ensure_config_dir_exists(conf_dir)
419
395
        location = self.location
425
401
        elif location + '/' in self._get_parser():
426
402
            location = location + '/'
427
403
        self._get_parser()[location][option]=value
428
 
        self._get_parser().write(file(self._get_filename(), 'wb'))
 
404
        self._get_parser().write()
429
405
 
430
406
 
431
407
class BranchConfig(Config):
432
408
    """A configuration object giving the policy for a branch."""
433
409
 
434
 
    def _get_branch_data_config(self):
435
 
        if self._branch_data_config is None:
436
 
            self._branch_data_config = TreeConfig(self.branch)
437
 
        return self._branch_data_config
438
 
 
439
410
    def _get_location_config(self):
440
411
        if self._location_config is None:
441
412
            self._location_config = LocationConfig(self.branch.base)
442
413
        return self._location_config
443
414
 
444
 
    def _get_global_config(self):
445
 
        if self._global_config is None:
446
 
            self._global_config = GlobalConfig()
447
 
        return self._global_config
448
 
 
449
 
    def _get_best_value(self, option_name):
450
 
        """This returns a user option from local, tree or global config.
451
 
 
452
 
        They are tried in that order.  Use get_safe_value if trusted values
453
 
        are necessary.
454
 
        """
455
 
        for source in self.option_sources:
456
 
            value = getattr(source(), option_name)()
457
 
            if value is not None:
458
 
                return value
459
 
        return None
460
 
 
461
 
    def _get_safe_value(self, option_name):
462
 
        """This variant of get_best_value never returns untrusted values.
463
 
        
464
 
        It does not return values from the branch data, because the branch may
465
 
        not be controlled by the user.
466
 
 
467
 
        We may wish to allow locations.conf to control whether branches are
468
 
        trusted in the future.
469
 
        """
470
 
        for source in (self._get_location_config, self._get_global_config):
471
 
            value = getattr(source(), option_name)()
472
 
            if value is not None:
473
 
                return value
474
 
        return None
475
 
 
476
415
    def _get_user_id(self):
477
416
        """Return the full user id for the branch.
478
417
    
487
426
        except errors.NoSuchFile, e:
488
427
            pass
489
428
        
490
 
        return self._get_best_value('_get_user_id')
 
429
        return self._get_location_config()._get_user_id()
491
430
 
492
431
    def _get_signature_checking(self):
493
432
        """See Config._get_signature_checking."""
494
 
        return self._get_best_value('_get_signature_checking')
495
 
 
496
 
    def _get_signing_policy(self):
497
 
        """See Config._get_signing_policy."""
498
 
        return self._get_best_value('_get_signing_policy')
 
433
        return self._get_location_config()._get_signature_checking()
499
434
 
500
435
    def _get_user_option(self, option_name):
501
436
        """See Config._get_user_option."""
502
 
        for source in self.option_sources:
503
 
            value = source()._get_user_option(option_name)
504
 
            if value is not None:
505
 
                return value
506
 
        return None
507
 
 
508
 
    def set_user_option(self, name, value, local=False):
509
 
        if local is True:
510
 
            self._get_location_config().set_user_option(name, value)
511
 
        else:
512
 
            self._get_branch_data_config().set_option(value, name)
513
 
 
 
437
        return self._get_location_config()._get_user_option(option_name)
514
438
 
515
439
    def _gpg_signing_command(self):
516
440
        """See Config.gpg_signing_command."""
517
 
        return self._get_safe_value('_gpg_signing_command')
 
441
        return self._get_location_config()._gpg_signing_command()
518
442
        
519
443
    def __init__(self, branch):
520
444
        super(BranchConfig, self).__init__()
521
445
        self._location_config = None
522
 
        self._branch_data_config = None
523
 
        self._global_config = None
524
446
        self.branch = branch
525
 
        self.option_sources = (self._get_location_config, 
526
 
                               self._get_branch_data_config,
527
 
                               self._get_global_config)
528
447
 
529
448
    def _post_commit(self):
530
449
        """See Config.post_commit."""
531
 
        return self._get_safe_value('_post_commit')
532
 
 
533
 
    def _get_nickname(self):
534
 
        value = self._get_explicit_nickname()
535
 
        if value is not None:
536
 
            return value
537
 
        return self.branch.base.split('/')[-2]
538
 
 
539
 
    def has_explicit_nickname(self):
540
 
        """Return true if a nickname has been explicitly assigned."""
541
 
        return self._get_explicit_nickname() is not None
542
 
 
543
 
    def _get_explicit_nickname(self):
544
 
        return self._get_best_value('_get_nickname')
 
450
        return self._get_location_config()._post_commit()
545
451
 
546
452
    def _log_format(self):
547
453
        """See Config.log_format."""
548
 
        return self._get_best_value('_log_format')
 
454
        return self._get_location_config()._log_format()
549
455
 
550
456
 
551
457
def ensure_config_dir_exists(path=None):
580
486
        if base is None:
581
487
            base = os.environ.get('HOME', None)
582
488
        if base is None:
583
 
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
 
489
            raise BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
584
490
        return pathjoin(base, 'bazaar', '2.0')
585
491
    else:
586
492
        # cygwin, linux, and darwin all have a $HOME directory
599
505
    return pathjoin(config_dir(), 'branches.conf')
600
506
 
601
507
 
602
 
def locations_config_filename():
603
 
    """Return per-user configuration ini file filename."""
604
 
    return pathjoin(config_dir(), 'locations.conf')
605
 
 
606
 
 
607
508
def _auto_user_id():
608
509
    """Calculate automatic user identification.
609
510
 
623
524
        import pwd
624
525
        uid = os.getuid()
625
526
        w = pwd.getpwuid(uid)
626
 
 
627
 
        # we try utf-8 first, because on many variants (like Linux),
628
 
        # /etc/passwd "should" be in utf-8, and because it's unlikely to give
629
 
        # false positives.  (many users will have their user encoding set to
630
 
        # latin-1, which cannot raise UnicodeError.)
631
 
        try:
632
 
            gecos = w.pw_gecos.decode('utf-8')
633
 
            encoding = 'utf-8'
634
 
        except UnicodeError:
635
 
            try:
636
 
                gecos = w.pw_gecos.decode(bzrlib.user_encoding)
637
 
                encoding = bzrlib.user_encoding
638
 
            except UnicodeError:
639
 
                raise errors.BzrCommandError('Unable to determine your name.  '
640
 
                   'Use "bzr whoami" to set it.')
641
 
        try:
642
 
            username = w.pw_name.decode(encoding)
643
 
        except UnicodeError:
644
 
            raise errors.BzrCommandError('Unable to determine your name.  '
645
 
                'Use "bzr whoami" to set it.')
646
 
 
 
527
        gecos = w.pw_gecos.decode(bzrlib.user_encoding)
 
528
        username = w.pw_name.decode(bzrlib.user_encoding)
647
529
        comma = gecos.find(',')
648
530
        if comma == -1:
649
531
            realname = gecos
654
536
 
655
537
    except ImportError:
656
538
        import getpass
657
 
        try:
658
 
            realname = username = getpass.getuser().decode(bzrlib.user_encoding)
659
 
        except UnicodeDecodeError:
660
 
            raise errors.BzrError("Can't decode username as %s." % \
661
 
                    bzrlib.user_encoding)
 
539
        realname = username = getpass.getuser().decode(bzrlib.user_encoding)
662
540
 
663
541
    return realname, (username + '@' + socket.gethostname())
664
542
 
679
557
                              "a reasonable email address" % e)
680
558
    return m.group(0)
681
559
 
682
 
 
683
 
class TreeConfig(IniBasedConfig):
 
560
class TreeConfig(object):
684
561
    """Branch configuration data associated with its contents, not location"""
685
562
    def __init__(self, branch):
686
563
        self.branch = branch
687
564
 
688
 
    def _get_parser(self, file=None):
689
 
        if file is not None:
690
 
            return IniBasedConfig._get_parser(file)
691
 
        return self._get_config()
692
 
 
693
565
    def _get_config(self):
694
566
        try:
695
567
            obj = ConfigObj(self.branch.control_files.get('branch.conf'),