/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

Make merge correctly locate a lca where there is a criss-cross merge
        of a new root.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
from cStringIO import StringIO
20
20
import os
21
21
import sys
 
22
import threading
22
23
 
23
24
#import bzrlib specific imports here
24
25
from bzrlib import (
35
36
    trace,
36
37
    transport,
37
38
    )
 
39
from bzrlib.tests import (
 
40
    features,
 
41
    scenarios,
 
42
    )
38
43
from bzrlib.util.configobj import configobj
39
44
 
40
45
 
 
46
def lockable_config_scenarios():
 
47
    return [
 
48
        ('global',
 
49
         {'config_class': config.GlobalConfig,
 
50
          'config_args': [],
 
51
          'config_section': 'DEFAULT'}),
 
52
        ('locations',
 
53
         {'config_class': config.LocationConfig,
 
54
          'config_args': ['.'],
 
55
          'config_section': '.'}),]
 
56
 
 
57
 
 
58
load_tests = scenarios.load_tests_apply_scenarios
 
59
 
 
60
 
41
61
sample_long_alias="log -r-15..-1 --line"
42
62
sample_config_text = u"""
43
63
[DEFAULT]
129
149
        self._calls.append(('keys',))
130
150
        return []
131
151
 
 
152
    def reload(self):
 
153
        self._calls.append(('reload',))
 
154
 
132
155
    def write(self, arg):
133
156
        self._calls.append(('write',))
134
157
 
350
373
        self.assertEqual(config.config_filename(),
351
374
                         self.bzr_home + '/bazaar.conf')
352
375
 
353
 
    def test_branches_config_filename(self):
354
 
        self.assertEqual(config.branches_config_filename(),
355
 
                         self.bzr_home + '/branches.conf')
356
 
 
357
376
    def test_locations_config_filename(self):
358
377
        self.assertEqual(config.locations_config_filename(),
359
378
                         self.bzr_home + '/locations.conf')
367
386
            '/home/bogus/.cache')
368
387
 
369
388
 
370
 
class TestIniConfig(tests.TestCase):
 
389
class TestIniConfig(tests.TestCaseInTempDir):
371
390
 
372
391
    def make_config_parser(self, s):
373
 
        conf = config.IniBasedConfig(None)
374
 
        parser = conf._get_parser(file=StringIO(s.encode('utf-8')))
375
 
        return conf, parser
 
392
        conf = config.IniBasedConfig.from_string(s)
 
393
        return conf, conf._get_parser()
376
394
 
377
395
 
378
396
class TestIniConfigBuilding(TestIniConfig):
379
397
 
380
398
    def test_contructs(self):
381
 
        my_config = config.IniBasedConfig("nothing")
 
399
        my_config = config.IniBasedConfig()
382
400
 
383
401
    def test_from_fp(self):
384
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
385
 
        my_config = config.IniBasedConfig(None)
386
 
        self.failUnless(
387
 
            isinstance(my_config._get_parser(file=config_file),
388
 
                        configobj.ConfigObj))
 
402
        my_config = config.IniBasedConfig.from_string(sample_config_text)
 
403
        self.assertIsInstance(my_config._get_parser(), configobj.ConfigObj)
389
404
 
390
405
    def test_cached(self):
391
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
392
 
        my_config = config.IniBasedConfig(None)
393
 
        parser = my_config._get_parser(file=config_file)
 
406
        my_config = config.IniBasedConfig.from_string(sample_config_text)
 
407
        parser = my_config._get_parser()
394
408
        self.failUnless(my_config._get_parser() is parser)
395
409
 
 
410
    def _dummy_chown(self, path, uid, gid):
 
411
        self.path, self.uid, self.gid = path, uid, gid
 
412
 
 
413
    def test_ini_config_ownership(self):
 
414
        """Ensure that chown is happening during _write_config_file"""
 
415
        self.requireFeature(features.chown_feature)
 
416
        self.overrideAttr(os, 'chown', self._dummy_chown)
 
417
        self.path = self.uid = self.gid = None
 
418
        conf = config.IniBasedConfig(file_name='./foo.conf')
 
419
        conf._write_config_file()
 
420
        self.assertEquals(self.path, './foo.conf')
 
421
        self.assertTrue(isinstance(self.uid, int))
 
422
        self.assertTrue(isinstance(self.gid, int))
 
423
 
 
424
    def test_get_filename_parameter_is_deprecated_(self):
 
425
        conf = self.callDeprecated([
 
426
            'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
 
427
            ' Use file_name instead.'],
 
428
            config.IniBasedConfig, lambda: 'ini.conf')
 
429
        self.assertEqual('ini.conf', conf.file_name)
 
430
 
 
431
    def test_get_parser_file_parameter_is_deprecated_(self):
 
432
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
433
        conf = config.IniBasedConfig.from_string(sample_config_text)
 
434
        conf = self.callDeprecated([
 
435
            'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
 
436
            ' Use IniBasedConfig(_content=xxx) instead.'],
 
437
            conf._get_parser, file=config_file)
 
438
 
 
439
class TestIniConfigSaving(tests.TestCaseInTempDir):
 
440
 
 
441
    def test_cant_save_without_a_file_name(self):
 
442
        conf = config.IniBasedConfig()
 
443
        self.assertRaises(AssertionError, conf._write_config_file)
 
444
 
 
445
    def test_saved_with_content(self):
 
446
        content = 'foo = bar\n'
 
447
        conf = config.IniBasedConfig.from_string(
 
448
            content, file_name='./test.conf', save=True)
 
449
        self.assertFileEqual(content, 'test.conf')
 
450
 
 
451
 
 
452
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
 
453
 
 
454
    def test_cannot_reload_without_name(self):
 
455
        conf = config.IniBasedConfig.from_string(sample_config_text)
 
456
        self.assertRaises(AssertionError, conf.reload)
 
457
 
 
458
    def test_reload_see_new_value(self):
 
459
        c1 = config.IniBasedConfig.from_string('editor=vim\n',
 
460
                                               file_name='./test/conf')
 
461
        c1._write_config_file()
 
462
        c2 = config.IniBasedConfig.from_string('editor=emacs\n',
 
463
                                               file_name='./test/conf')
 
464
        c2._write_config_file()
 
465
        self.assertEqual('vim', c1.get_user_option('editor'))
 
466
        self.assertEqual('emacs', c2.get_user_option('editor'))
 
467
        # Make sure we get the Right value
 
468
        c1.reload()
 
469
        self.assertEqual('emacs', c1.get_user_option('editor'))
 
470
 
 
471
 
 
472
class TestLockableConfig(tests.TestCaseInTempDir):
 
473
 
 
474
    scenarios = lockable_config_scenarios()
 
475
 
 
476
    # Set by load_tests
 
477
    config_class = None
 
478
    config_args = None
 
479
    config_section = None
 
480
 
 
481
    def setUp(self):
 
482
        super(TestLockableConfig, self).setUp()
 
483
        self._content = '[%s]\none=1\ntwo=2\n' % (self.config_section,)
 
484
        self.config = self.create_config(self._content)
 
485
 
 
486
    def get_existing_config(self):
 
487
        return self.config_class(*self.config_args)
 
488
 
 
489
    def create_config(self, content):
 
490
        kwargs = dict(save=True)
 
491
        c = self.config_class.from_string(content, *self.config_args, **kwargs)
 
492
        return c
 
493
 
 
494
    def test_simple_read_access(self):
 
495
        self.assertEquals('1', self.config.get_user_option('one'))
 
496
 
 
497
    def test_simple_write_access(self):
 
498
        self.config.set_user_option('one', 'one')
 
499
        self.assertEquals('one', self.config.get_user_option('one'))
 
500
 
 
501
    def test_listen_to_the_last_speaker(self):
 
502
        c1 = self.config
 
503
        c2 = self.get_existing_config()
 
504
        c1.set_user_option('one', 'ONE')
 
505
        c2.set_user_option('two', 'TWO')
 
506
        self.assertEquals('ONE', c1.get_user_option('one'))
 
507
        self.assertEquals('TWO', c2.get_user_option('two'))
 
508
        # The second update respect the first one
 
509
        self.assertEquals('ONE', c2.get_user_option('one'))
 
510
 
 
511
    def test_last_speaker_wins(self):
 
512
        # If the same config is not shared, the same variable modified twice
 
513
        # can only see a single result.
 
514
        c1 = self.config
 
515
        c2 = self.get_existing_config()
 
516
        c1.set_user_option('one', 'c1')
 
517
        c2.set_user_option('one', 'c2')
 
518
        self.assertEquals('c2', c2._get_user_option('one'))
 
519
        # The first modification is still available until another refresh
 
520
        # occur
 
521
        self.assertEquals('c1', c1._get_user_option('one'))
 
522
        c1.set_user_option('two', 'done')
 
523
        self.assertEquals('c2', c1._get_user_option('one'))
 
524
 
 
525
    def test_writes_are_serialized(self):
 
526
        c1 = self.config
 
527
        c2 = self.get_existing_config()
 
528
 
 
529
        # We spawn a thread that will pause *during* the write
 
530
        before_writing = threading.Event()
 
531
        after_writing = threading.Event()
 
532
        writing_done = threading.Event()
 
533
        c1_orig = c1._write_config_file
 
534
        def c1_write_config_file():
 
535
            before_writing.set()
 
536
            c1_orig()
 
537
            # The lock is held we wait for the main thread to decide when to
 
538
            # continue
 
539
            after_writing.wait()
 
540
        c1._write_config_file = c1_write_config_file
 
541
        def c1_set_option():
 
542
            c1.set_user_option('one', 'c1')
 
543
            writing_done.set()
 
544
        t1 = threading.Thread(target=c1_set_option)
 
545
        # Collect the thread after the test
 
546
        self.addCleanup(t1.join)
 
547
        # Be ready to unblock the thread if the test goes wrong
 
548
        self.addCleanup(after_writing.set)
 
549
        t1.start()
 
550
        before_writing.wait()
 
551
        self.assertTrue(c1._lock.is_held)
 
552
        self.assertRaises(errors.LockContention,
 
553
                          c2.set_user_option, 'one', 'c2')
 
554
        self.assertEquals('c1', c1.get_user_option('one'))
 
555
        # Let the lock be released
 
556
        after_writing.set()
 
557
        writing_done.wait()
 
558
        c2.set_user_option('one', 'c2')
 
559
        self.assertEquals('c2', c2.get_user_option('one'))
 
560
 
 
561
    def test_read_while_writing(self):
 
562
       c1 = self.config
 
563
       # We spawn a thread that will pause *during* the write
 
564
       ready_to_write = threading.Event()
 
565
       do_writing = threading.Event()
 
566
       writing_done = threading.Event()
 
567
       c1_orig = c1._write_config_file
 
568
       def c1_write_config_file():
 
569
           ready_to_write.set()
 
570
           # The lock is held we wait for the main thread to decide when to
 
571
           # continue
 
572
           do_writing.wait()
 
573
           c1_orig()
 
574
           writing_done.set()
 
575
       c1._write_config_file = c1_write_config_file
 
576
       def c1_set_option():
 
577
           c1.set_user_option('one', 'c1')
 
578
       t1 = threading.Thread(target=c1_set_option)
 
579
       # Collect the thread after the test
 
580
       self.addCleanup(t1.join)
 
581
       # Be ready to unblock the thread if the test goes wrong
 
582
       self.addCleanup(do_writing.set)
 
583
       t1.start()
 
584
       # Ensure the thread is ready to write
 
585
       ready_to_write.wait()
 
586
       self.assertTrue(c1._lock.is_held)
 
587
       self.assertEquals('c1', c1.get_user_option('one'))
 
588
       # If we read during the write, we get the old value
 
589
       c2 = self.get_existing_config()
 
590
       self.assertEquals('1', c2.get_user_option('one'))
 
591
       # Let the writing occur and ensure it occurred
 
592
       do_writing.set()
 
593
       writing_done.wait()
 
594
       # Now we get the updated value
 
595
       c3 = self.get_existing_config()
 
596
       self.assertEquals('c1', c3.get_user_option('one'))
 
597
 
396
598
 
397
599
class TestGetUserOptionAs(TestIniConfig):
398
600
 
505
707
        branch = self.make_branch('branch')
506
708
        self.assertEqual('branch', branch.nick)
507
709
 
508
 
        locations = config.locations_config_filename()
509
 
        config.ensure_config_dir_exists()
510
710
        local_url = urlutils.local_path_to_url('branch')
511
 
        open(locations, 'wb').write('[%s]\nnickname = foobar'
512
 
                                    % (local_url,))
 
711
        conf = config.LocationConfig.from_string(
 
712
            '[%s]\nnickname = foobar' % (local_url,),
 
713
            local_url, save=True)
513
714
        self.assertEqual('foobar', branch.nick)
514
715
 
515
716
    def test_config_local_path(self):
517
718
        branch = self.make_branch('branch')
518
719
        self.assertEqual('branch', branch.nick)
519
720
 
520
 
        locations = config.locations_config_filename()
521
 
        config.ensure_config_dir_exists()
522
 
        open(locations, 'wb').write('[%s/branch]\nnickname = barry'
523
 
                                    % (osutils.getcwd().encode('utf8'),))
 
721
        local_path = osutils.getcwd().encode('utf8')
 
722
        conf = config.LocationConfig.from_string(
 
723
            '[%s/branch]\nnickname = barry' % (local_path,),
 
724
            'branch',  save=True)
524
725
        self.assertEqual('barry', branch.nick)
525
726
 
526
727
    def test_config_creates_local(self):
527
728
        """Creating a new entry in config uses a local path."""
528
729
        branch = self.make_branch('branch', format='knit')
529
730
        branch.set_push_location('http://foobar')
530
 
        locations = config.locations_config_filename()
531
731
        local_path = osutils.getcwd().encode('utf8')
532
732
        # Surprisingly ConfigObj doesn't create a trailing newline
533
 
        self.check_file_contents(locations,
 
733
        self.check_file_contents(config.locations_config_filename(),
534
734
                                 '[%s/branch]\n'
535
735
                                 'push_location = http://foobar\n'
536
736
                                 'push_location:policy = norecurse\n'
541
741
        self.assertEqual('!repo', b.get_config().get_nickname())
542
742
 
543
743
    def test_warn_if_masked(self):
544
 
        _warning = trace.warning
545
744
        warnings = []
546
745
        def warning(*args):
547
746
            warnings.append(args[0] % args[1:])
 
747
        self.overrideAttr(trace, 'warning', warning)
548
748
 
549
749
        def set_option(store, warn_masked=True):
550
750
            warnings[:] = []
556
756
            else:
557
757
                self.assertEqual(1, len(warnings))
558
758
                self.assertEqual(warning, warnings[0])
559
 
        trace.warning = warning
560
 
        try:
561
 
            branch = self.make_branch('.')
562
 
            conf = branch.get_config()
563
 
            set_option(config.STORE_GLOBAL)
564
 
            assertWarning(None)
565
 
            set_option(config.STORE_BRANCH)
566
 
            assertWarning(None)
567
 
            set_option(config.STORE_GLOBAL)
568
 
            assertWarning('Value "4" is masked by "3" from branch.conf')
569
 
            set_option(config.STORE_GLOBAL, warn_masked=False)
570
 
            assertWarning(None)
571
 
            set_option(config.STORE_LOCATION)
572
 
            assertWarning(None)
573
 
            set_option(config.STORE_BRANCH)
574
 
            assertWarning('Value "3" is masked by "0" from locations.conf')
575
 
            set_option(config.STORE_BRANCH, warn_masked=False)
576
 
            assertWarning(None)
577
 
        finally:
578
 
            trace.warning = _warning
579
 
 
580
 
 
581
 
class TestGlobalConfigItems(tests.TestCase):
 
759
        branch = self.make_branch('.')
 
760
        conf = branch.get_config()
 
761
        set_option(config.STORE_GLOBAL)
 
762
        assertWarning(None)
 
763
        set_option(config.STORE_BRANCH)
 
764
        assertWarning(None)
 
765
        set_option(config.STORE_GLOBAL)
 
766
        assertWarning('Value "4" is masked by "3" from branch.conf')
 
767
        set_option(config.STORE_GLOBAL, warn_masked=False)
 
768
        assertWarning(None)
 
769
        set_option(config.STORE_LOCATION)
 
770
        assertWarning(None)
 
771
        set_option(config.STORE_BRANCH)
 
772
        assertWarning('Value "3" is masked by "0" from locations.conf')
 
773
        set_option(config.STORE_BRANCH, warn_masked=False)
 
774
        assertWarning(None)
 
775
 
 
776
 
 
777
class TestGlobalConfigItems(tests.TestCaseInTempDir):
582
778
 
583
779
    def test_user_id(self):
584
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
585
 
        my_config = config.GlobalConfig()
586
 
        my_config._parser = my_config._get_parser(file=config_file)
 
780
        my_config = config.GlobalConfig.from_string(sample_config_text)
587
781
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
588
782
                         my_config._get_user_id())
589
783
 
590
784
    def test_absent_user_id(self):
591
 
        config_file = StringIO("")
592
785
        my_config = config.GlobalConfig()
593
 
        my_config._parser = my_config._get_parser(file=config_file)
594
786
        self.assertEqual(None, my_config._get_user_id())
595
787
 
596
788
    def test_configured_editor(self):
597
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
598
 
        my_config = config.GlobalConfig()
599
 
        my_config._parser = my_config._get_parser(file=config_file)
 
789
        my_config = config.GlobalConfig.from_string(sample_config_text)
600
790
        self.assertEqual("vim", my_config.get_editor())
601
791
 
602
792
    def test_signatures_always(self):
603
 
        config_file = StringIO(sample_always_signatures)
604
 
        my_config = config.GlobalConfig()
605
 
        my_config._parser = my_config._get_parser(file=config_file)
 
793
        my_config = config.GlobalConfig.from_string(sample_always_signatures)
606
794
        self.assertEqual(config.CHECK_NEVER,
607
795
                         my_config.signature_checking())
608
796
        self.assertEqual(config.SIGN_ALWAYS,
610
798
        self.assertEqual(True, my_config.signature_needed())
611
799
 
612
800
    def test_signatures_if_possible(self):
613
 
        config_file = StringIO(sample_maybe_signatures)
614
 
        my_config = config.GlobalConfig()
615
 
        my_config._parser = my_config._get_parser(file=config_file)
 
801
        my_config = config.GlobalConfig.from_string(sample_maybe_signatures)
616
802
        self.assertEqual(config.CHECK_NEVER,
617
803
                         my_config.signature_checking())
618
804
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
620
806
        self.assertEqual(False, my_config.signature_needed())
621
807
 
622
808
    def test_signatures_ignore(self):
623
 
        config_file = StringIO(sample_ignore_signatures)
624
 
        my_config = config.GlobalConfig()
625
 
        my_config._parser = my_config._get_parser(file=config_file)
 
809
        my_config = config.GlobalConfig.from_string(sample_ignore_signatures)
626
810
        self.assertEqual(config.CHECK_ALWAYS,
627
811
                         my_config.signature_checking())
628
812
        self.assertEqual(config.SIGN_NEVER,
630
814
        self.assertEqual(False, my_config.signature_needed())
631
815
 
632
816
    def _get_sample_config(self):
633
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
634
 
        my_config = config.GlobalConfig()
635
 
        my_config._parser = my_config._get_parser(file=config_file)
 
817
        my_config = config.GlobalConfig.from_string(sample_config_text)
636
818
        return my_config
637
819
 
638
820
    def test_gpg_signing_command(self):
641
823
        self.assertEqual(False, my_config.signature_needed())
642
824
 
643
825
    def _get_empty_config(self):
644
 
        config_file = StringIO("")
645
826
        my_config = config.GlobalConfig()
646
 
        my_config._parser = my_config._get_parser(file=config_file)
647
827
        return my_config
648
828
 
649
829
    def test_gpg_signing_command_unset(self):
744
924
        self.assertEqual(parser._calls,
745
925
                         [('__init__', config.locations_config_filename(),
746
926
                           'utf-8')])
747
 
        config.ensure_config_dir_exists()
748
 
        #os.mkdir(config.config_dir())
749
 
        f = file(config.branches_config_filename(), 'wb')
750
 
        f.write('')
751
 
        f.close()
752
 
        oldparserclass = config.ConfigObj
753
 
        config.ConfigObj = InstrumentedConfigObj
754
 
        try:
755
 
            my_config = config.LocationConfig('http://www.example.com')
756
 
            parser = my_config._get_parser()
757
 
        finally:
758
 
            config.ConfigObj = oldparserclass
759
927
 
760
928
    def test_get_global_config(self):
761
929
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
848
1016
            'http://www.example.com', 'appendpath_option'),
849
1017
            config.POLICY_APPENDPATH)
850
1018
 
 
1019
    def test__get_options_with_policy(self):
 
1020
        self.get_branch_config('/dir/subdir',
 
1021
                               location_config="""\
 
1022
[/dir]
 
1023
other_url = /other-dir
 
1024
other_url:policy = appendpath
 
1025
[/dir/subdir]
 
1026
other_url = /other-subdir
 
1027
""")
 
1028
        self.assertEqual(
 
1029
            [(u'other_url', u'/other-subdir', u'/dir/subdir', 'locations'),
 
1030
             (u'other_url', u'/other-dir', u'/dir', 'locations'),
 
1031
             (u'other_url:policy', u'appendpath', u'/dir', 'locations')],
 
1032
            list(self.my_location_config._get_options()))
 
1033
 
851
1034
    def test_location_without_username(self):
852
1035
        self.get_branch_config('http://www.example.com/ignoreparent')
853
1036
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
989
1172
        self.assertEqual('bzrlib.tests.test_config.post_commit',
990
1173
                         self.my_config.post_commit())
991
1174
 
992
 
    def get_branch_config(self, location, global_config=None):
 
1175
    def get_branch_config(self, location, global_config=None,
 
1176
                          location_config=None):
 
1177
        my_branch = FakeBranch(location)
993
1178
        if global_config is None:
994
 
            global_file = StringIO(sample_config_text.encode('utf-8'))
995
 
        else:
996
 
            global_file = StringIO(global_config.encode('utf-8'))
997
 
        branches_file = StringIO(sample_branches_text.encode('utf-8'))
998
 
        self.my_config = config.BranchConfig(FakeBranch(location))
999
 
        # Force location config to use specified file
1000
 
        self.my_location_config = self.my_config._get_location_config()
1001
 
        self.my_location_config._get_parser(branches_file)
1002
 
        # Force global config to use specified file
1003
 
        self.my_config._get_global_config()._get_parser(global_file)
 
1179
            global_config = sample_config_text
 
1180
        if location_config is None:
 
1181
            location_config = sample_branches_text
 
1182
 
 
1183
        my_global_config = config.GlobalConfig.from_string(global_config,
 
1184
                                                           save=True)
 
1185
        my_location_config = config.LocationConfig.from_string(
 
1186
            location_config, my_branch.base, save=True)
 
1187
        my_config = config.BranchConfig(my_branch)
 
1188
        self.my_config = my_config
 
1189
        self.my_location_config = my_config._get_location_config()
1004
1190
 
1005
1191
    def test_set_user_setting_sets_and_saves(self):
1006
1192
        self.get_branch_config('/a/c')
1007
1193
        record = InstrumentedConfigObj("foo")
1008
1194
        self.my_location_config._parser = record
1009
1195
 
1010
 
        real_mkdir = os.mkdir
1011
 
        self.created = False
1012
 
        def checked_mkdir(path, mode=0777):
1013
 
            self.log('making directory: %s', path)
1014
 
            real_mkdir(path, mode)
1015
 
            self.created = True
1016
 
 
1017
 
        os.mkdir = checked_mkdir
1018
 
        try:
1019
 
            self.callDeprecated(['The recurse option is deprecated as of '
1020
 
                                 '0.14.  The section "/a/c" has been '
1021
 
                                 'converted to use policies.'],
1022
 
                                self.my_config.set_user_option,
1023
 
                                'foo', 'bar', store=config.STORE_LOCATION)
1024
 
        finally:
1025
 
            os.mkdir = real_mkdir
1026
 
 
1027
 
        self.failUnless(self.created, 'Failed to create ~/.bazaar')
1028
 
        self.assertEqual([('__contains__', '/a/c'),
 
1196
        self.callDeprecated(['The recurse option is deprecated as of '
 
1197
                             '0.14.  The section "/a/c" has been '
 
1198
                             'converted to use policies.'],
 
1199
                            self.my_config.set_user_option,
 
1200
                            'foo', 'bar', store=config.STORE_LOCATION)
 
1201
        self.assertEqual([('reload',),
 
1202
                          ('__contains__', '/a/c'),
1029
1203
                          ('__contains__', '/a/c/'),
1030
1204
                          ('__setitem__', '/a/c', {}),
1031
1205
                          ('__getitem__', '/a/c'),
1074
1248
option = exact
1075
1249
"""
1076
1250
 
1077
 
 
1078
1251
class TestBranchConfigItems(tests.TestCaseInTempDir):
1079
1252
 
1080
1253
    def get_branch_config(self, global_config=None, location=None,
1081
1254
                          location_config=None, branch_data_config=None):
1082
 
        my_config = config.BranchConfig(FakeBranch(location))
 
1255
        my_branch = FakeBranch(location)
1083
1256
        if global_config is not None:
1084
 
            global_file = StringIO(global_config.encode('utf-8'))
1085
 
            my_config._get_global_config()._get_parser(global_file)
1086
 
        self.my_location_config = my_config._get_location_config()
 
1257
            my_global_config = config.GlobalConfig.from_string(global_config,
 
1258
                                                               save=True)
1087
1259
        if location_config is not None:
1088
 
            location_file = StringIO(location_config.encode('utf-8'))
1089
 
            self.my_location_config._get_parser(location_file)
 
1260
            my_location_config = config.LocationConfig.from_string(
 
1261
                location_config, my_branch.base, save=True)
 
1262
        my_config = config.BranchConfig(my_branch)
1090
1263
        if branch_data_config is not None:
1091
1264
            my_config.branch.control_files.files['branch.conf'] = \
1092
1265
                branch_data_config
1106
1279
                         my_config.username())
1107
1280
 
1108
1281
    def test_not_set_in_branch(self):
1109
 
        my_config = self.get_branch_config(sample_config_text)
 
1282
        my_config = self.get_branch_config(global_config=sample_config_text)
1110
1283
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
1111
1284
                         my_config._get_user_id())
1112
1285
        my_config.branch.control_files.files['email'] = "John"
1136
1309
 
1137
1310
    def test_gpg_signing_command(self):
1138
1311
        my_config = self.get_branch_config(
 
1312
            global_config=sample_config_text,
1139
1313
            # branch data cannot set gpg_signing_command
1140
1314
            branch_data_config="gpg_signing_command=pgp")
1141
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
1142
 
        my_config._get_global_config()._get_parser(config_file)
1143
1315
        self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
1144
1316
 
1145
1317
    def test_get_user_option_global(self):
1146
 
        branch = FakeBranch()
1147
 
        my_config = config.BranchConfig(branch)
1148
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
1149
 
        (my_config._get_global_config()._get_parser(config_file))
 
1318
        my_config = self.get_branch_config(global_config=sample_config_text)
1150
1319
        self.assertEqual('something',
1151
1320
                         my_config.get_user_option('user_global_option'))
1152
1321
 
1153
1322
    def test_post_commit_default(self):
1154
 
        branch = FakeBranch()
1155
 
        my_config = self.get_branch_config(sample_config_text, '/a/c',
1156
 
                                           sample_branches_text)
 
1323
        my_config = self.get_branch_config(global_config=sample_config_text,
 
1324
                                      location='/a/c',
 
1325
                                      location_config=sample_branches_text)
1157
1326
        self.assertEqual(my_config.branch.base, '/a/c')
1158
1327
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1159
1328
                         my_config.post_commit())
1160
1329
        my_config.set_user_option('post_commit', 'rmtree_root')
1161
 
        # post-commit is ignored when bresent in branch data
 
1330
        # post-commit is ignored when present in branch data
1162
1331
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1163
1332
                         my_config.post_commit())
1164
1333
        my_config.set_user_option('post_commit', 'rmtree_root',
1166
1335
        self.assertEqual('rmtree_root', my_config.post_commit())
1167
1336
 
1168
1337
    def test_config_precedence(self):
 
1338
        # FIXME: eager test, luckily no persitent config file makes it fail
 
1339
        # -- vila 20100716
1169
1340
        my_config = self.get_branch_config(global_config=precedence_global)
1170
1341
        self.assertEqual(my_config.get_user_option('option'), 'global')
1171
1342
        my_config = self.get_branch_config(global_config=precedence_global,
1172
 
                                      branch_data_config=precedence_branch)
 
1343
                                           branch_data_config=precedence_branch)
1173
1344
        self.assertEqual(my_config.get_user_option('option'), 'branch')
1174
 
        my_config = self.get_branch_config(global_config=precedence_global,
1175
 
                                      branch_data_config=precedence_branch,
1176
 
                                      location_config=precedence_location)
 
1345
        my_config = self.get_branch_config(
 
1346
            global_config=precedence_global,
 
1347
            branch_data_config=precedence_branch,
 
1348
            location_config=precedence_location)
1177
1349
        self.assertEqual(my_config.get_user_option('option'), 'recurse')
1178
 
        my_config = self.get_branch_config(global_config=precedence_global,
1179
 
                                      branch_data_config=precedence_branch,
1180
 
                                      location_config=precedence_location,
1181
 
                                      location='http://example.com/specific')
 
1350
        my_config = self.get_branch_config(
 
1351
            global_config=precedence_global,
 
1352
            branch_data_config=precedence_branch,
 
1353
            location_config=precedence_location,
 
1354
            location='http://example.com/specific')
1182
1355
        self.assertEqual(my_config.get_user_option('option'), 'exact')
1183
1356
 
1184
1357
    def test_get_mail_client(self):
1312
1485
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1313
1486
 
1314
1487
 
 
1488
def create_configs(test):
 
1489
    """Create configuration files for a given test.
 
1490
 
 
1491
    This requires creating a tree (and populate the ``test.tree`` attribute)
 
1492
    and its associated branch and will populate the following attributes:
 
1493
 
 
1494
    - branch_config: A BranchConfig for the associated branch.
 
1495
 
 
1496
    - locations_config : A LocationConfig for the associated branch
 
1497
 
 
1498
    - bazaar_config: A GlobalConfig.
 
1499
 
 
1500
    The tree and branch are created in a 'tree' subdirectory so the tests can
 
1501
    still use the test directory to stay outside of the branch.
 
1502
    """
 
1503
    tree = test.make_branch_and_tree('tree')
 
1504
    test.tree = tree
 
1505
    test.branch_config = config.BranchConfig(tree.branch)
 
1506
    test.locations_config = config.LocationConfig(tree.basedir)
 
1507
    test.bazaar_config = config.GlobalConfig()
 
1508
 
 
1509
 
 
1510
def create_configs_with_file_option(test):
 
1511
    """Create configuration files with a ``file`` option set in each.
 
1512
 
 
1513
    This builds on ``create_configs`` and add one ``file`` option in each
 
1514
    configuration with a value which allows identifying the configuration file.
 
1515
    """
 
1516
    create_configs(test)
 
1517
    test.bazaar_config.set_user_option('file', 'bazaar')
 
1518
    test.locations_config.set_user_option('file', 'locations')
 
1519
    test.branch_config.set_user_option('file', 'branch')
 
1520
 
 
1521
 
 
1522
class TestConfigGetOptions(tests.TestCaseWithTransport):
 
1523
 
 
1524
    def setUp(self):
 
1525
        super(TestConfigGetOptions, self).setUp()
 
1526
        create_configs(self)
 
1527
 
 
1528
    def assertOptions(self, expected, conf):
 
1529
        actual = list(conf._get_options())
 
1530
        self.assertEqual(expected, actual)
 
1531
 
 
1532
    # One variable in none of the above
 
1533
    def test_no_variable(self):
 
1534
        # Using branch should query branch, locations and bazaar
 
1535
        self.assertOptions([], self.branch_config)
 
1536
 
 
1537
    def test_option_in_bazaar(self):
 
1538
        self.bazaar_config.set_user_option('file', 'bazaar')
 
1539
        self.assertOptions([('file', 'bazaar', 'DEFAULT', 'bazaar')],
 
1540
                           self.bazaar_config)
 
1541
 
 
1542
    def test_option_in_locations(self):
 
1543
        self.locations_config.set_user_option('file', 'locations')
 
1544
        self.assertOptions(
 
1545
            [('file', 'locations', self.tree.basedir, 'locations')],
 
1546
            self.locations_config)
 
1547
 
 
1548
    def test_option_in_branch(self):
 
1549
        self.branch_config.set_user_option('file', 'branch')
 
1550
        self.assertOptions([('file', 'branch', 'DEFAULT', 'branch')],
 
1551
                           self.branch_config)
 
1552
 
 
1553
    def test_option_in_bazaar_and_branch(self):
 
1554
        self.bazaar_config.set_user_option('file', 'bazaar')
 
1555
        self.branch_config.set_user_option('file', 'branch')
 
1556
        self.assertOptions([('file', 'branch', 'DEFAULT', 'branch'),
 
1557
                            ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
 
1558
                           self.branch_config)
 
1559
 
 
1560
    def test_option_in_branch_and_locations(self):
 
1561
        # Hmm, locations override branch :-/
 
1562
        self.locations_config.set_user_option('file', 'locations')
 
1563
        self.branch_config.set_user_option('file', 'branch')
 
1564
        self.assertOptions(
 
1565
            [('file', 'locations', self.tree.basedir, 'locations'),
 
1566
             ('file', 'branch', 'DEFAULT', 'branch'),],
 
1567
            self.branch_config)
 
1568
 
 
1569
    def test_option_in_bazaar_locations_and_branch(self):
 
1570
        self.bazaar_config.set_user_option('file', 'bazaar')
 
1571
        self.locations_config.set_user_option('file', 'locations')
 
1572
        self.branch_config.set_user_option('file', 'branch')
 
1573
        self.assertOptions(
 
1574
            [('file', 'locations', self.tree.basedir, 'locations'),
 
1575
             ('file', 'branch', 'DEFAULT', 'branch'),
 
1576
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
 
1577
            self.branch_config)
 
1578
 
 
1579
 
 
1580
class TestConfigRemoveOption(tests.TestCaseWithTransport):
 
1581
 
 
1582
    def setUp(self):
 
1583
        super(TestConfigRemoveOption, self).setUp()
 
1584
        create_configs_with_file_option(self)
 
1585
 
 
1586
    def assertOptions(self, expected, conf):
 
1587
        actual = list(conf._get_options())
 
1588
        self.assertEqual(expected, actual)
 
1589
 
 
1590
    def test_remove_in_locations(self):
 
1591
        self.locations_config.remove_user_option('file', self.tree.basedir)
 
1592
        self.assertOptions(
 
1593
            [('file', 'branch', 'DEFAULT', 'branch'),
 
1594
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
 
1595
            self.branch_config)
 
1596
 
 
1597
    def test_remove_in_branch(self):
 
1598
        self.branch_config.remove_user_option('file')
 
1599
        self.assertOptions(
 
1600
            [('file', 'locations', self.tree.basedir, 'locations'),
 
1601
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
 
1602
            self.branch_config)
 
1603
 
 
1604
    def test_remove_in_bazaar(self):
 
1605
        self.bazaar_config.remove_user_option('file')
 
1606
        self.assertOptions(
 
1607
            [('file', 'locations', self.tree.basedir, 'locations'),
 
1608
             ('file', 'branch', 'DEFAULT', 'branch'),],
 
1609
            self.branch_config)
 
1610
 
 
1611
 
 
1612
class TestConfigGetSections(tests.TestCaseWithTransport):
 
1613
 
 
1614
    def setUp(self):
 
1615
        super(TestConfigGetSections, self).setUp()
 
1616
        create_configs(self)
 
1617
 
 
1618
    def assertSectionNames(self, expected, conf, name=None):
 
1619
        """Check which sections are returned for a given config.
 
1620
 
 
1621
        If fallback configurations exist their sections can be included.
 
1622
 
 
1623
        :param expected: A list of section names.
 
1624
 
 
1625
        :param conf: The configuration that will be queried.
 
1626
 
 
1627
        :param name: An optional section name that will be passed to
 
1628
            get_sections().
 
1629
        """
 
1630
        sections = list(conf._get_sections(name))
 
1631
        self.assertLength(len(expected), sections)
 
1632
        self.assertEqual(expected, [name for name, _, _ in sections])
 
1633
 
 
1634
    def test_bazaar_default_section(self):
 
1635
        self.assertSectionNames(['DEFAULT'], self.bazaar_config)
 
1636
 
 
1637
    def test_locations_default_section(self):
 
1638
        # No sections are defined in an empty file
 
1639
        self.assertSectionNames([], self.locations_config)
 
1640
 
 
1641
    def test_locations_named_section(self):
 
1642
        self.locations_config.set_user_option('file', 'locations')
 
1643
        self.assertSectionNames([self.tree.basedir], self.locations_config)
 
1644
 
 
1645
    def test_locations_matching_sections(self):
 
1646
        loc_config = self.locations_config
 
1647
        loc_config.set_user_option('file', 'locations')
 
1648
        # We need to cheat a bit here to create an option in sections above and
 
1649
        # below the 'location' one.
 
1650
        parser = loc_config._get_parser()
 
1651
        # locations.cong deals with '/' ignoring native os.sep
 
1652
        location_names = self.tree.basedir.split('/')
 
1653
        parent = '/'.join(location_names[:-1])
 
1654
        child = '/'.join(location_names + ['child'])
 
1655
        parser[parent] = {}
 
1656
        parser[parent]['file'] = 'parent'
 
1657
        parser[child] = {}
 
1658
        parser[child]['file'] = 'child'
 
1659
        self.assertSectionNames([self.tree.basedir, parent], loc_config)
 
1660
 
 
1661
    def test_branch_data_default_section(self):
 
1662
        self.assertSectionNames([None],
 
1663
                                self.branch_config._get_branch_data_config())
 
1664
 
 
1665
    def test_branch_default_sections(self):
 
1666
        # No sections are defined in an empty locations file
 
1667
        self.assertSectionNames([None, 'DEFAULT'],
 
1668
                                self.branch_config)
 
1669
        # Unless we define an option
 
1670
        self.branch_config._get_location_config().set_user_option(
 
1671
            'file', 'locations')
 
1672
        self.assertSectionNames([self.tree.basedir, None, 'DEFAULT'],
 
1673
                                self.branch_config)
 
1674
 
 
1675
    def test_bazaar_named_section(self):
 
1676
        # We need to cheat as the API doesn't give direct access to sections
 
1677
        # other than DEFAULT.
 
1678
        self.bazaar_config.set_alias('bazaar', 'bzr')
 
1679
        self.assertSectionNames(['ALIASES'], self.bazaar_config, 'ALIASES')
 
1680
 
 
1681
 
1315
1682
class TestAuthenticationConfigFile(tests.TestCase):
1316
1683
    """Test the authentication.conf file matching"""
1317
1684