~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-09-29 22:03:03 UTC
  • mfrom: (5416.2.6 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100929220303-cr95h8iwtggco721
(mbp) Add 'break-lock --force'

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2008 Canonical Ltd
2
 
#   Authors: Robert Collins <robert.collins@canonical.com>
 
1
# Copyright (C) 2005-2010 Canonical Ltd
3
2
#
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
18
17
"""Tests for finding and reading the bzr config file[s]."""
19
18
# import system imports here
20
19
from cStringIO import StringIO
21
 
import getpass
22
20
import os
23
21
import sys
 
22
import threading
24
23
 
25
24
#import bzrlib specific imports here
26
25
from bzrlib import (
27
26
    branch,
28
27
    bzrdir,
29
28
    config,
 
29
    diff,
30
30
    errors,
31
31
    osutils,
32
32
    mail_client,
36
36
    trace,
37
37
    transport,
38
38
    )
 
39
from bzrlib.tests import features
39
40
from bzrlib.util.configobj import configobj
40
41
 
41
42
 
 
43
def lockable_config_scenarios():
 
44
    return [
 
45
        ('global',
 
46
         {'config_class': config.GlobalConfig,
 
47
          'config_args': [],
 
48
          'config_section': 'DEFAULT'}),
 
49
        ('locations',
 
50
         {'config_class': config.LocationConfig,
 
51
          'config_args': ['.'],
 
52
          'config_section': '.'}),]
 
53
 
 
54
 
 
55
def load_tests(standard_tests, module, loader):
 
56
    suite = loader.suiteClass()
 
57
 
 
58
    lc_tests, remaining_tests = tests.split_suite_by_condition(
 
59
        standard_tests, tests.condition_isinstance((
 
60
                TestLockableConfig,
 
61
                )))
 
62
    tests.multiply_tests(lc_tests, lockable_config_scenarios(), suite)
 
63
    suite.addTest(remaining_tests)
 
64
    return suite
 
65
 
 
66
 
42
67
sample_long_alias="log -r-15..-1 --line"
43
68
sample_config_text = u"""
44
69
[DEFAULT]
45
70
email=Erik B\u00e5gfors <erik@bagfors.nu>
46
71
editor=vim
 
72
change_editor=vimdiff -of @new_path @old_path
47
73
gpg_signing_command=gnome-gpg
48
74
log_format=short
49
75
user_global_option=something
129
155
        self._calls.append(('keys',))
130
156
        return []
131
157
 
 
158
    def reload(self):
 
159
        self._calls.append(('reload',))
 
160
 
132
161
    def write(self, arg):
133
162
        self._calls.append(('write',))
134
163
 
210
239
        self._calls.append('_get_signature_checking')
211
240
        return self._signatures
212
241
 
 
242
    def _get_change_editor(self):
 
243
        self._calls.append('_get_change_editor')
 
244
        return 'vimdiff -fo @new_path @old_path'
 
245
 
213
246
 
214
247
bool_config = """[DEFAULT]
215
248
active = true
316
349
        my_config = config.Config()
317
350
        self.assertEqual('long', my_config.log_format())
318
351
 
 
352
    def test_get_change_editor(self):
 
353
        my_config = InstrumentedConfig()
 
354
        change_editor = my_config.get_change_editor('old_tree', 'new_tree')
 
355
        self.assertEqual(['_get_change_editor'], my_config._calls)
 
356
        self.assertIs(diff.DiffFromTool, change_editor.__class__)
 
357
        self.assertEqual(['vimdiff', '-fo', '@new_path', '@old_path'],
 
358
                         change_editor.command_template)
 
359
 
319
360
 
320
361
class TestConfigPath(tests.TestCase):
321
362
 
322
363
    def setUp(self):
323
364
        super(TestConfigPath, self).setUp()
324
365
        os.environ['HOME'] = '/home/bogus'
 
366
        os.environ['XDG_CACHE_DIR'] = ''
325
367
        if sys.platform == 'win32':
326
368
            os.environ['BZR_HOME'] = \
327
369
                r'C:\Documents and Settings\bogus\Application Data'
337
379
        self.assertEqual(config.config_filename(),
338
380
                         self.bzr_home + '/bazaar.conf')
339
381
 
340
 
    def test_branches_config_filename(self):
341
 
        self.assertEqual(config.branches_config_filename(),
342
 
                         self.bzr_home + '/branches.conf')
343
 
 
344
382
    def test_locations_config_filename(self):
345
383
        self.assertEqual(config.locations_config_filename(),
346
384
                         self.bzr_home + '/locations.conf')
349
387
        self.assertEqual(config.authentication_config_filename(),
350
388
                         self.bzr_home + '/authentication.conf')
351
389
 
352
 
 
353
 
class TestIniConfig(tests.TestCase):
 
390
    def test_xdg_cache_dir(self):
 
391
        self.assertEqual(config.xdg_cache_dir(),
 
392
            '/home/bogus/.cache')
 
393
 
 
394
 
 
395
class TestIniConfig(tests.TestCaseInTempDir):
 
396
 
 
397
    def make_config_parser(self, s):
 
398
        conf = config.IniBasedConfig.from_string(s)
 
399
        return conf, conf._get_parser()
 
400
 
 
401
 
 
402
class TestIniConfigBuilding(TestIniConfig):
354
403
 
355
404
    def test_contructs(self):
356
 
        my_config = config.IniBasedConfig("nothing")
 
405
        my_config = config.IniBasedConfig()
357
406
 
358
407
    def test_from_fp(self):
359
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
360
 
        my_config = config.IniBasedConfig(None)
361
 
        self.failUnless(
362
 
            isinstance(my_config._get_parser(file=config_file),
363
 
                        configobj.ConfigObj))
 
408
        my_config = config.IniBasedConfig.from_string(sample_config_text)
 
409
        self.assertIsInstance(my_config._get_parser(), configobj.ConfigObj)
364
410
 
365
411
    def test_cached(self):
366
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
367
 
        my_config = config.IniBasedConfig(None)
368
 
        parser = my_config._get_parser(file=config_file)
 
412
        my_config = config.IniBasedConfig.from_string(sample_config_text)
 
413
        parser = my_config._get_parser()
369
414
        self.failUnless(my_config._get_parser() is parser)
370
415
 
 
416
    def _dummy_chown(self, path, uid, gid):
 
417
        self.path, self.uid, self.gid = path, uid, gid
 
418
 
 
419
    def test_ini_config_ownership(self):
 
420
        """Ensure that chown is happening during _write_config_file"""
 
421
        self.requireFeature(features.chown_feature)
 
422
        self.overrideAttr(os, 'chown', self._dummy_chown)
 
423
        self.path = self.uid = self.gid = None
 
424
        conf = config.IniBasedConfig(file_name='./foo.conf')
 
425
        conf._write_config_file()
 
426
        self.assertEquals(self.path, './foo.conf')
 
427
        self.assertTrue(isinstance(self.uid, int))
 
428
        self.assertTrue(isinstance(self.gid, int))
 
429
 
 
430
    def test_get_filename_parameter_is_deprecated_(self):
 
431
        conf = self.callDeprecated([
 
432
            'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
 
433
            ' Use file_name instead.'],
 
434
            config.IniBasedConfig, lambda: 'ini.conf')
 
435
        self.assertEqual('ini.conf', conf.file_name)
 
436
 
 
437
    def test_get_parser_file_parameter_is_deprecated_(self):
 
438
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
439
        conf = config.IniBasedConfig.from_string(sample_config_text)
 
440
        conf = self.callDeprecated([
 
441
            'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
 
442
            ' Use IniBasedConfig(_content=xxx) instead.'],
 
443
            conf._get_parser, file=config_file)
 
444
 
 
445
class TestIniConfigSaving(tests.TestCaseInTempDir):
 
446
 
 
447
    def test_cant_save_without_a_file_name(self):
 
448
        conf = config.IniBasedConfig()
 
449
        self.assertRaises(AssertionError, conf._write_config_file)
 
450
 
 
451
    def test_saved_with_content(self):
 
452
        content = 'foo = bar\n'
 
453
        conf = config.IniBasedConfig.from_string(
 
454
            content, file_name='./test.conf', save=True)
 
455
        self.assertFileEqual(content, 'test.conf')
 
456
 
 
457
 
 
458
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
 
459
 
 
460
    def test_cannot_reload_without_name(self):
 
461
        conf = config.IniBasedConfig.from_string(sample_config_text)
 
462
        self.assertRaises(AssertionError, conf.reload)
 
463
 
 
464
    def test_reload_see_new_value(self):
 
465
        c1 = config.IniBasedConfig.from_string('editor=vim\n',
 
466
                                               file_name='./test/conf')
 
467
        c1._write_config_file()
 
468
        c2 = config.IniBasedConfig.from_string('editor=emacs\n',
 
469
                                               file_name='./test/conf')
 
470
        c2._write_config_file()
 
471
        self.assertEqual('vim', c1.get_user_option('editor'))
 
472
        self.assertEqual('emacs', c2.get_user_option('editor'))
 
473
        # Make sure we get the Right value
 
474
        c1.reload()
 
475
        self.assertEqual('emacs', c1.get_user_option('editor'))
 
476
 
 
477
 
 
478
class TestLockableConfig(tests.TestCaseInTempDir):
 
479
 
 
480
    # Set by load_tests
 
481
    config_class = None
 
482
    config_args = None
 
483
    config_section = None
 
484
 
 
485
    def setUp(self):
 
486
        super(TestLockableConfig, self).setUp()
 
487
        self._content = '[%s]\none=1\ntwo=2\n' % (self.config_section,)
 
488
        self.config = self.create_config(self._content)
 
489
 
 
490
    def get_existing_config(self):
 
491
        return self.config_class(*self.config_args)
 
492
 
 
493
    def create_config(self, content):
 
494
        kwargs = dict(save=True)
 
495
        c = self.config_class.from_string(content, *self.config_args, **kwargs)
 
496
        return c
 
497
 
 
498
    def test_simple_read_access(self):
 
499
        self.assertEquals('1', self.config.get_user_option('one'))
 
500
 
 
501
    def test_simple_write_access(self):
 
502
        self.config.set_user_option('one', 'one')
 
503
        self.assertEquals('one', self.config.get_user_option('one'))
 
504
 
 
505
    def test_listen_to_the_last_speaker(self):
 
506
        c1 = self.config
 
507
        c2 = self.get_existing_config()
 
508
        c1.set_user_option('one', 'ONE')
 
509
        c2.set_user_option('two', 'TWO')
 
510
        self.assertEquals('ONE', c1.get_user_option('one'))
 
511
        self.assertEquals('TWO', c2.get_user_option('two'))
 
512
        # The second update respect the first one
 
513
        self.assertEquals('ONE', c2.get_user_option('one'))
 
514
 
 
515
    def test_last_speaker_wins(self):
 
516
        # If the same config is not shared, the same variable modified twice
 
517
        # can only see a single result.
 
518
        c1 = self.config
 
519
        c2 = self.get_existing_config()
 
520
        c1.set_user_option('one', 'c1')
 
521
        c2.set_user_option('one', 'c2')
 
522
        self.assertEquals('c2', c2._get_user_option('one'))
 
523
        # The first modification is still available until another refresh
 
524
        # occur
 
525
        self.assertEquals('c1', c1._get_user_option('one'))
 
526
        c1.set_user_option('two', 'done')
 
527
        self.assertEquals('c2', c1._get_user_option('one'))
 
528
 
 
529
    def test_writes_are_serialized(self):
 
530
        c1 = self.config
 
531
        c2 = self.get_existing_config()
 
532
 
 
533
        # We spawn a thread that will pause *during* the write
 
534
        before_writing = threading.Event()
 
535
        after_writing = threading.Event()
 
536
        writing_done = threading.Event()
 
537
        c1_orig = c1._write_config_file
 
538
        def c1_write_config_file():
 
539
            before_writing.set()
 
540
            c1_orig()
 
541
            # The lock is held we wait for the main thread to decide when to
 
542
            # continue
 
543
            after_writing.wait()
 
544
        c1._write_config_file = c1_write_config_file
 
545
        def c1_set_option():
 
546
            c1.set_user_option('one', 'c1')
 
547
            writing_done.set()
 
548
        t1 = threading.Thread(target=c1_set_option)
 
549
        # Collect the thread after the test
 
550
        self.addCleanup(t1.join)
 
551
        # Be ready to unblock the thread if the test goes wrong
 
552
        self.addCleanup(after_writing.set)
 
553
        t1.start()
 
554
        before_writing.wait()
 
555
        self.assertTrue(c1._lock.is_held)
 
556
        self.assertRaises(errors.LockContention,
 
557
                          c2.set_user_option, 'one', 'c2')
 
558
        self.assertEquals('c1', c1.get_user_option('one'))
 
559
        # Let the lock be released
 
560
        after_writing.set()
 
561
        writing_done.wait()
 
562
        c2.set_user_option('one', 'c2')
 
563
        self.assertEquals('c2', c2.get_user_option('one'))
 
564
 
 
565
    def test_read_while_writing(self):
 
566
       c1 = self.config
 
567
       # We spawn a thread that will pause *during* the write
 
568
       ready_to_write = threading.Event()
 
569
       do_writing = threading.Event()
 
570
       writing_done = threading.Event()
 
571
       c1_orig = c1._write_config_file
 
572
       def c1_write_config_file():
 
573
           ready_to_write.set()
 
574
           # The lock is held we wait for the main thread to decide when to
 
575
           # continue
 
576
           do_writing.wait()
 
577
           c1_orig()
 
578
           writing_done.set()
 
579
       c1._write_config_file = c1_write_config_file
 
580
       def c1_set_option():
 
581
           c1.set_user_option('one', 'c1')
 
582
       t1 = threading.Thread(target=c1_set_option)
 
583
       # Collect the thread after the test
 
584
       self.addCleanup(t1.join)
 
585
       # Be ready to unblock the thread if the test goes wrong
 
586
       self.addCleanup(do_writing.set)
 
587
       t1.start()
 
588
       # Ensure the thread is ready to write
 
589
       ready_to_write.wait()
 
590
       self.assertTrue(c1._lock.is_held)
 
591
       self.assertEquals('c1', c1.get_user_option('one'))
 
592
       # If we read during the write, we get the old value
 
593
       c2 = self.get_existing_config()
 
594
       self.assertEquals('1', c2.get_user_option('one'))
 
595
       # Let the writing occur and ensure it occurred
 
596
       do_writing.set()
 
597
       writing_done.wait()
 
598
       # Now we get the updated value
 
599
       c3 = self.get_existing_config()
 
600
       self.assertEquals('c1', c3.get_user_option('one'))
 
601
 
 
602
 
 
603
class TestGetUserOptionAs(TestIniConfig):
 
604
 
 
605
    def test_get_user_option_as_bool(self):
 
606
        conf, parser = self.make_config_parser("""
 
607
a_true_bool = true
 
608
a_false_bool = 0
 
609
an_invalid_bool = maybe
 
610
a_list = hmm, who knows ? # This is interpreted as a list !
 
611
""")
 
612
        get_bool = conf.get_user_option_as_bool
 
613
        self.assertEqual(True, get_bool('a_true_bool'))
 
614
        self.assertEqual(False, get_bool('a_false_bool'))
 
615
        warnings = []
 
616
        def warning(*args):
 
617
            warnings.append(args[0] % args[1:])
 
618
        self.overrideAttr(trace, 'warning', warning)
 
619
        msg = 'Value "%s" is not a boolean for "%s"'
 
620
        self.assertIs(None, get_bool('an_invalid_bool'))
 
621
        self.assertEquals(msg % ('maybe', 'an_invalid_bool'), warnings[0])
 
622
        warnings = []
 
623
        self.assertIs(None, get_bool('not_defined_in_this_config'))
 
624
        self.assertEquals([], warnings)
 
625
 
 
626
    def test_get_user_option_as_list(self):
 
627
        conf, parser = self.make_config_parser("""
 
628
a_list = a,b,c
 
629
length_1 = 1,
 
630
one_item = x
 
631
""")
 
632
        get_list = conf.get_user_option_as_list
 
633
        self.assertEqual(['a', 'b', 'c'], get_list('a_list'))
 
634
        self.assertEqual(['1'], get_list('length_1'))
 
635
        self.assertEqual('x', conf.get_user_option('one_item'))
 
636
        # automatically cast to list
 
637
        self.assertEqual(['x'], get_list('one_item'))
 
638
 
 
639
 
 
640
class TestSupressWarning(TestIniConfig):
 
641
 
 
642
    def make_warnings_config(self, s):
 
643
        conf, parser = self.make_config_parser(s)
 
644
        return conf.suppress_warning
 
645
 
 
646
    def test_suppress_warning_unknown(self):
 
647
        suppress_warning = self.make_warnings_config('')
 
648
        self.assertEqual(False, suppress_warning('unknown_warning'))
 
649
 
 
650
    def test_suppress_warning_known(self):
 
651
        suppress_warning = self.make_warnings_config('suppress_warnings=a,b')
 
652
        self.assertEqual(False, suppress_warning('c'))
 
653
        self.assertEqual(True, suppress_warning('a'))
 
654
        self.assertEqual(True, suppress_warning('b'))
 
655
 
371
656
 
372
657
class TestGetConfig(tests.TestCase):
373
658
 
426
711
        branch = self.make_branch('branch')
427
712
        self.assertEqual('branch', branch.nick)
428
713
 
429
 
        locations = config.locations_config_filename()
430
 
        config.ensure_config_dir_exists()
431
714
        local_url = urlutils.local_path_to_url('branch')
432
 
        open(locations, 'wb').write('[%s]\nnickname = foobar'
433
 
                                    % (local_url,))
 
715
        conf = config.LocationConfig.from_string(
 
716
            '[%s]\nnickname = foobar' % (local_url,),
 
717
            local_url, save=True)
434
718
        self.assertEqual('foobar', branch.nick)
435
719
 
436
720
    def test_config_local_path(self):
438
722
        branch = self.make_branch('branch')
439
723
        self.assertEqual('branch', branch.nick)
440
724
 
441
 
        locations = config.locations_config_filename()
442
 
        config.ensure_config_dir_exists()
443
 
        open(locations, 'wb').write('[%s/branch]\nnickname = barry'
444
 
                                    % (osutils.getcwd().encode('utf8'),))
 
725
        local_path = osutils.getcwd().encode('utf8')
 
726
        conf = config.LocationConfig.from_string(
 
727
            '[%s/branch]\nnickname = barry' % (local_path,),
 
728
            'branch',  save=True)
445
729
        self.assertEqual('barry', branch.nick)
446
730
 
447
731
    def test_config_creates_local(self):
448
732
        """Creating a new entry in config uses a local path."""
449
733
        branch = self.make_branch('branch', format='knit')
450
734
        branch.set_push_location('http://foobar')
451
 
        locations = config.locations_config_filename()
452
735
        local_path = osutils.getcwd().encode('utf8')
453
736
        # Surprisingly ConfigObj doesn't create a trailing newline
454
 
        self.check_file_contents(locations,
 
737
        self.check_file_contents(config.locations_config_filename(),
455
738
                                 '[%s/branch]\n'
456
739
                                 'push_location = http://foobar\n'
457
740
                                 'push_location:policy = norecurse\n'
462
745
        self.assertEqual('!repo', b.get_config().get_nickname())
463
746
 
464
747
    def test_warn_if_masked(self):
465
 
        _warning = trace.warning
466
748
        warnings = []
467
749
        def warning(*args):
468
750
            warnings.append(args[0] % args[1:])
 
751
        self.overrideAttr(trace, 'warning', warning)
469
752
 
470
753
        def set_option(store, warn_masked=True):
471
754
            warnings[:] = []
477
760
            else:
478
761
                self.assertEqual(1, len(warnings))
479
762
                self.assertEqual(warning, warnings[0])
480
 
        trace.warning = warning
481
 
        try:
482
 
            branch = self.make_branch('.')
483
 
            conf = branch.get_config()
484
 
            set_option(config.STORE_GLOBAL)
485
 
            assertWarning(None)
486
 
            set_option(config.STORE_BRANCH)
487
 
            assertWarning(None)
488
 
            set_option(config.STORE_GLOBAL)
489
 
            assertWarning('Value "4" is masked by "3" from branch.conf')
490
 
            set_option(config.STORE_GLOBAL, warn_masked=False)
491
 
            assertWarning(None)
492
 
            set_option(config.STORE_LOCATION)
493
 
            assertWarning(None)
494
 
            set_option(config.STORE_BRANCH)
495
 
            assertWarning('Value "3" is masked by "0" from locations.conf')
496
 
            set_option(config.STORE_BRANCH, warn_masked=False)
497
 
            assertWarning(None)
498
 
        finally:
499
 
            trace.warning = _warning
500
 
 
501
 
 
502
 
class TestGlobalConfigItems(tests.TestCase):
 
763
        branch = self.make_branch('.')
 
764
        conf = branch.get_config()
 
765
        set_option(config.STORE_GLOBAL)
 
766
        assertWarning(None)
 
767
        set_option(config.STORE_BRANCH)
 
768
        assertWarning(None)
 
769
        set_option(config.STORE_GLOBAL)
 
770
        assertWarning('Value "4" is masked by "3" from branch.conf')
 
771
        set_option(config.STORE_GLOBAL, warn_masked=False)
 
772
        assertWarning(None)
 
773
        set_option(config.STORE_LOCATION)
 
774
        assertWarning(None)
 
775
        set_option(config.STORE_BRANCH)
 
776
        assertWarning('Value "3" is masked by "0" from locations.conf')
 
777
        set_option(config.STORE_BRANCH, warn_masked=False)
 
778
        assertWarning(None)
 
779
 
 
780
 
 
781
class TestGlobalConfigItems(tests.TestCaseInTempDir):
503
782
 
504
783
    def test_user_id(self):
505
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
506
 
        my_config = config.GlobalConfig()
507
 
        my_config._parser = my_config._get_parser(file=config_file)
 
784
        my_config = config.GlobalConfig.from_string(sample_config_text)
508
785
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
509
786
                         my_config._get_user_id())
510
787
 
511
788
    def test_absent_user_id(self):
512
 
        config_file = StringIO("")
513
789
        my_config = config.GlobalConfig()
514
 
        my_config._parser = my_config._get_parser(file=config_file)
515
790
        self.assertEqual(None, my_config._get_user_id())
516
791
 
517
792
    def test_configured_editor(self):
518
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
519
 
        my_config = config.GlobalConfig()
520
 
        my_config._parser = my_config._get_parser(file=config_file)
 
793
        my_config = config.GlobalConfig.from_string(sample_config_text)
521
794
        self.assertEqual("vim", my_config.get_editor())
522
795
 
523
796
    def test_signatures_always(self):
524
 
        config_file = StringIO(sample_always_signatures)
525
 
        my_config = config.GlobalConfig()
526
 
        my_config._parser = my_config._get_parser(file=config_file)
 
797
        my_config = config.GlobalConfig.from_string(sample_always_signatures)
527
798
        self.assertEqual(config.CHECK_NEVER,
528
799
                         my_config.signature_checking())
529
800
        self.assertEqual(config.SIGN_ALWAYS,
531
802
        self.assertEqual(True, my_config.signature_needed())
532
803
 
533
804
    def test_signatures_if_possible(self):
534
 
        config_file = StringIO(sample_maybe_signatures)
535
 
        my_config = config.GlobalConfig()
536
 
        my_config._parser = my_config._get_parser(file=config_file)
 
805
        my_config = config.GlobalConfig.from_string(sample_maybe_signatures)
537
806
        self.assertEqual(config.CHECK_NEVER,
538
807
                         my_config.signature_checking())
539
808
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
541
810
        self.assertEqual(False, my_config.signature_needed())
542
811
 
543
812
    def test_signatures_ignore(self):
544
 
        config_file = StringIO(sample_ignore_signatures)
545
 
        my_config = config.GlobalConfig()
546
 
        my_config._parser = my_config._get_parser(file=config_file)
 
813
        my_config = config.GlobalConfig.from_string(sample_ignore_signatures)
547
814
        self.assertEqual(config.CHECK_ALWAYS,
548
815
                         my_config.signature_checking())
549
816
        self.assertEqual(config.SIGN_NEVER,
551
818
        self.assertEqual(False, my_config.signature_needed())
552
819
 
553
820
    def _get_sample_config(self):
554
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
555
 
        my_config = config.GlobalConfig()
556
 
        my_config._parser = my_config._get_parser(file=config_file)
 
821
        my_config = config.GlobalConfig.from_string(sample_config_text)
557
822
        return my_config
558
823
 
559
824
    def test_gpg_signing_command(self):
562
827
        self.assertEqual(False, my_config.signature_needed())
563
828
 
564
829
    def _get_empty_config(self):
565
 
        config_file = StringIO("")
566
830
        my_config = config.GlobalConfig()
567
 
        my_config._parser = my_config._get_parser(file=config_file)
568
831
        return my_config
569
832
 
570
833
    def test_gpg_signing_command_unset(self):
608
871
        my_config = self._get_sample_config()
609
872
        self.assertEqual(sample_long_alias, my_config.get_alias('ll'))
610
873
 
 
874
    def test_get_change_editor(self):
 
875
        my_config = self._get_sample_config()
 
876
        change_editor = my_config.get_change_editor('old', 'new')
 
877
        self.assertIs(diff.DiffFromTool, change_editor.__class__)
 
878
        self.assertEqual('vimdiff -of @new_path @old_path',
 
879
                         ' '.join(change_editor.command_template))
 
880
 
 
881
    def test_get_no_change_editor(self):
 
882
        my_config = self._get_empty_config()
 
883
        change_editor = my_config.get_change_editor('old', 'new')
 
884
        self.assertIs(None, change_editor)
 
885
 
611
886
 
612
887
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
613
888
 
653
928
        self.assertEqual(parser._calls,
654
929
                         [('__init__', config.locations_config_filename(),
655
930
                           'utf-8')])
656
 
        config.ensure_config_dir_exists()
657
 
        #os.mkdir(config.config_dir())
658
 
        f = file(config.branches_config_filename(), 'wb')
659
 
        f.write('')
660
 
        f.close()
661
 
        oldparserclass = config.ConfigObj
662
 
        config.ConfigObj = InstrumentedConfigObj
663
 
        try:
664
 
            my_config = config.LocationConfig('http://www.example.com')
665
 
            parser = my_config._get_parser()
666
 
        finally:
667
 
            config.ConfigObj = oldparserclass
668
931
 
669
932
    def test_get_global_config(self):
670
933
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
899
1162
                         self.my_config.post_commit())
900
1163
 
901
1164
    def get_branch_config(self, location, global_config=None):
 
1165
        my_branch = FakeBranch(location)
902
1166
        if global_config is None:
903
 
            global_file = StringIO(sample_config_text.encode('utf-8'))
904
 
        else:
905
 
            global_file = StringIO(global_config.encode('utf-8'))
906
 
        branches_file = StringIO(sample_branches_text.encode('utf-8'))
907
 
        self.my_config = config.BranchConfig(FakeBranch(location))
908
 
        # Force location config to use specified file
909
 
        self.my_location_config = self.my_config._get_location_config()
910
 
        self.my_location_config._get_parser(branches_file)
911
 
        # Force global config to use specified file
912
 
        self.my_config._get_global_config()._get_parser(global_file)
 
1167
            global_config = sample_config_text
 
1168
 
 
1169
        my_global_config = config.GlobalConfig.from_string(global_config,
 
1170
                                                           save=True)
 
1171
        my_location_config = config.LocationConfig.from_string(
 
1172
            sample_branches_text, my_branch.base, save=True)
 
1173
        my_config = config.BranchConfig(my_branch)
 
1174
        self.my_config = my_config
 
1175
        self.my_location_config = my_config._get_location_config()
913
1176
 
914
1177
    def test_set_user_setting_sets_and_saves(self):
915
1178
        self.get_branch_config('/a/c')
916
1179
        record = InstrumentedConfigObj("foo")
917
1180
        self.my_location_config._parser = record
918
1181
 
919
 
        real_mkdir = os.mkdir
920
 
        self.created = False
921
 
        def checked_mkdir(path, mode=0777):
922
 
            self.log('making directory: %s', path)
923
 
            real_mkdir(path, mode)
924
 
            self.created = True
925
 
 
926
 
        os.mkdir = checked_mkdir
927
 
        try:
928
 
            self.callDeprecated(['The recurse option is deprecated as of '
929
 
                                 '0.14.  The section "/a/c" has been '
930
 
                                 'converted to use policies.'],
931
 
                                self.my_config.set_user_option,
932
 
                                'foo', 'bar', store=config.STORE_LOCATION)
933
 
        finally:
934
 
            os.mkdir = real_mkdir
935
 
 
936
 
        self.failUnless(self.created, 'Failed to create ~/.bazaar')
937
 
        self.assertEqual([('__contains__', '/a/c'),
 
1182
        self.callDeprecated(['The recurse option is deprecated as of '
 
1183
                             '0.14.  The section "/a/c" has been '
 
1184
                             'converted to use policies.'],
 
1185
                            self.my_config.set_user_option,
 
1186
                            'foo', 'bar', store=config.STORE_LOCATION)
 
1187
        self.assertEqual([('reload',),
 
1188
                          ('__contains__', '/a/c'),
938
1189
                          ('__contains__', '/a/c/'),
939
1190
                          ('__setitem__', '/a/c', {}),
940
1191
                          ('__getitem__', '/a/c'),
983
1234
option = exact
984
1235
"""
985
1236
 
986
 
 
987
1237
class TestBranchConfigItems(tests.TestCaseInTempDir):
988
1238
 
989
1239
    def get_branch_config(self, global_config=None, location=None,
990
1240
                          location_config=None, branch_data_config=None):
991
 
        my_config = config.BranchConfig(FakeBranch(location))
 
1241
        my_branch = FakeBranch(location)
992
1242
        if global_config is not None:
993
 
            global_file = StringIO(global_config.encode('utf-8'))
994
 
            my_config._get_global_config()._get_parser(global_file)
995
 
        self.my_location_config = my_config._get_location_config()
 
1243
            my_global_config = config.GlobalConfig.from_string(global_config,
 
1244
                                                               save=True)
996
1245
        if location_config is not None:
997
 
            location_file = StringIO(location_config.encode('utf-8'))
998
 
            self.my_location_config._get_parser(location_file)
 
1246
            my_location_config = config.LocationConfig.from_string(
 
1247
                location_config, my_branch.base, save=True)
 
1248
        my_config = config.BranchConfig(my_branch)
999
1249
        if branch_data_config is not None:
1000
1250
            my_config.branch.control_files.files['branch.conf'] = \
1001
1251
                branch_data_config
1015
1265
                         my_config.username())
1016
1266
 
1017
1267
    def test_not_set_in_branch(self):
1018
 
        my_config = self.get_branch_config(sample_config_text)
 
1268
        my_config = self.get_branch_config(global_config=sample_config_text)
1019
1269
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
1020
1270
                         my_config._get_user_id())
1021
1271
        my_config.branch.control_files.files['email'] = "John"
1045
1295
 
1046
1296
    def test_gpg_signing_command(self):
1047
1297
        my_config = self.get_branch_config(
 
1298
            global_config=sample_config_text,
1048
1299
            # branch data cannot set gpg_signing_command
1049
1300
            branch_data_config="gpg_signing_command=pgp")
1050
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
1051
 
        my_config._get_global_config()._get_parser(config_file)
1052
1301
        self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
1053
1302
 
1054
1303
    def test_get_user_option_global(self):
1055
 
        branch = FakeBranch()
1056
 
        my_config = config.BranchConfig(branch)
1057
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
1058
 
        (my_config._get_global_config()._get_parser(config_file))
 
1304
        my_config = self.get_branch_config(global_config=sample_config_text)
1059
1305
        self.assertEqual('something',
1060
1306
                         my_config.get_user_option('user_global_option'))
1061
1307
 
1062
1308
    def test_post_commit_default(self):
1063
 
        branch = FakeBranch()
1064
 
        my_config = self.get_branch_config(sample_config_text, '/a/c',
1065
 
                                           sample_branches_text)
 
1309
        my_config = self.get_branch_config(global_config=sample_config_text,
 
1310
                                      location='/a/c',
 
1311
                                      location_config=sample_branches_text)
1066
1312
        self.assertEqual(my_config.branch.base, '/a/c')
1067
1313
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1068
1314
                         my_config.post_commit())
1069
1315
        my_config.set_user_option('post_commit', 'rmtree_root')
1070
 
        # post-commit is ignored when bresent in branch data
 
1316
        # post-commit is ignored when present in branch data
1071
1317
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1072
1318
                         my_config.post_commit())
1073
1319
        my_config.set_user_option('post_commit', 'rmtree_root',
1075
1321
        self.assertEqual('rmtree_root', my_config.post_commit())
1076
1322
 
1077
1323
    def test_config_precedence(self):
 
1324
        # FIXME: eager test, luckily no persitent config file makes it fail
 
1325
        # -- vila 20100716
1078
1326
        my_config = self.get_branch_config(global_config=precedence_global)
1079
1327
        self.assertEqual(my_config.get_user_option('option'), 'global')
1080
1328
        my_config = self.get_branch_config(global_config=precedence_global,
1081
 
                                      branch_data_config=precedence_branch)
 
1329
                                           branch_data_config=precedence_branch)
1082
1330
        self.assertEqual(my_config.get_user_option('option'), 'branch')
1083
 
        my_config = self.get_branch_config(global_config=precedence_global,
1084
 
                                      branch_data_config=precedence_branch,
1085
 
                                      location_config=precedence_location)
 
1331
        my_config = self.get_branch_config(
 
1332
            global_config=precedence_global,
 
1333
            branch_data_config=precedence_branch,
 
1334
            location_config=precedence_location)
1086
1335
        self.assertEqual(my_config.get_user_option('option'), 'recurse')
1087
 
        my_config = self.get_branch_config(global_config=precedence_global,
1088
 
                                      branch_data_config=precedence_branch,
1089
 
                                      location_config=precedence_location,
1090
 
                                      location='http://example.com/specific')
 
1336
        my_config = self.get_branch_config(
 
1337
            global_config=precedence_global,
 
1338
            branch_data_config=precedence_branch,
 
1339
            location_config=precedence_location,
 
1340
            location='http://example.com/specific')
1091
1341
        self.assertEqual(my_config.get_user_option('option'), 'exact')
1092
1342
 
1093
1343
    def test_get_mail_client(self):
1548
1798
"""))
1549
1799
        entered_password = 'typed-by-hand'
1550
1800
        stdout = tests.StringIOWrapper()
 
1801
        stderr = tests.StringIOWrapper()
1551
1802
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
1552
 
                                            stdout=stdout)
 
1803
                                            stdout=stdout, stderr=stderr)
1553
1804
 
1554
1805
        # Since the password defined in the authentication config is ignored,
1555
1806
        # the user is prompted
1556
1807
        self.assertEquals(entered_password,
1557
1808
                          conf.get_password('ssh', 'bar.org', user='jim'))
1558
1809
        self.assertContainsRe(
1559
 
            self._get_log(keep_log_file=True),
 
1810
            self.get_log(),
1560
1811
            'password ignored in section \[ssh with password\]')
1561
1812
 
1562
1813
    def test_ssh_without_password_doesnt_emit_warning(self):
1569
1820
"""))
1570
1821
        entered_password = 'typed-by-hand'
1571
1822
        stdout = tests.StringIOWrapper()
 
1823
        stderr = tests.StringIOWrapper()
1572
1824
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
1573
 
                                            stdout=stdout)
 
1825
                                            stdout=stdout,
 
1826
                                            stderr=stderr)
1574
1827
 
1575
1828
        # Since the password defined in the authentication config is ignored,
1576
1829
        # the user is prompted
1579
1832
        # No warning shoud be emitted since there is no password. We are only
1580
1833
        # providing "user".
1581
1834
        self.assertNotContainsRe(
1582
 
            self._get_log(keep_log_file=True),
 
1835
            self.get_log(),
1583
1836
            'password ignored in section \[ssh with password\]')
1584
1837
 
1585
1838
    def test_uses_fallback_stores(self):
1586
 
        self._old_cs_registry = config.credential_store_registry
1587
 
        def restore():
1588
 
            config.credential_store_registry = self._old_cs_registry
1589
 
        self.addCleanup(restore)
1590
 
        config.credential_store_registry = config.CredentialStoreRegistry()
 
1839
        self.overrideAttr(config, 'credential_store_registry',
 
1840
                          config.CredentialStoreRegistry())
1591
1841
        store = StubCredentialStore()
1592
1842
        store.add_credentials("http", "example.com", "joe", "secret")
1593
1843
        config.credential_store_registry.register("stub", store, fallback=True)