1
# Copyright (C) 2005, 2006 Canonical Ltd
2
# Authors: Robert Collins <robert.collins@canonical.com>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""Tests for finding and reading the bzr config file[s]."""
19
# import system imports here
20
from bzrlib.util.configobj.configobj import ConfigObj, ConfigObjError
21
from cStringIO import StringIO
25
#import bzrlib specific imports here
32
from bzrlib.branch import Branch
33
from bzrlib.bzrdir import BzrDir
34
from bzrlib.tests import TestCase, TestCaseInTempDir, TestCaseWithTransport
37
sample_long_alias="log -r-15..-1 --line"
38
sample_config_text = u"""
40
email=Erik B\u00e5gfors <erik@bagfors.nu>
42
gpg_signing_command=gnome-gpg
44
user_global_option=something
47
ll=""" + sample_long_alias + "\n"
50
sample_always_signatures = """
52
check_signatures=ignore
53
create_signatures=always
56
sample_ignore_signatures = """
58
check_signatures=require
59
create_signatures=never
62
sample_maybe_signatures = """
64
check_signatures=ignore
65
create_signatures=when-required
68
sample_branches_text = """
69
[http://www.example.com]
71
email=Robert Collins <robertc@example.org>
72
normal_option = normal
73
appendpath_option = append
74
appendpath_option:policy = appendpath
75
norecurse_option = norecurse
76
norecurse_option:policy = norecurse
77
[http://www.example.com/ignoreparent]
78
# different project: ignore parent dir config
80
[http://www.example.com/norecurse]
81
# configuration items that only apply to this dir
83
normal_option = norecurse
84
[http://www.example.com/dir]
85
appendpath_option = normal
87
check_signatures=require
88
# test trailing / matching with no children
90
check_signatures=check-available
91
gpg_signing_command=false
92
user_local_option=local
93
# test trailing / matching
95
#subdirs will match but not the parent
97
check_signatures=ignore
98
post_commit=bzrlib.tests.test_config.post_commit
99
#testing explicit beats globs
103
class InstrumentedConfigObj(object):
104
"""A config obj look-enough-alike to record calls made to it."""
106
def __contains__(self, thing):
107
self._calls.append(('__contains__', thing))
110
def __getitem__(self, key):
111
self._calls.append(('__getitem__', key))
114
def __init__(self, input, encoding=None):
115
self._calls = [('__init__', input, encoding)]
117
def __setitem__(self, key, value):
118
self._calls.append(('__setitem__', key, value))
120
def __delitem__(self, key):
121
self._calls.append(('__delitem__', key))
124
self._calls.append(('keys',))
127
def write(self, arg):
128
self._calls.append(('write',))
130
def as_bool(self, value):
131
self._calls.append(('as_bool', value))
134
def get_value(self, section, name):
135
self._calls.append(('get_value', section, name))
139
class FakeBranch(object):
141
def __init__(self, base=None, user_id=None):
143
self.base = "http://example.com/branches/demo"
146
self.control_files = FakeControlFiles(user_id=user_id)
148
def lock_write(self):
155
class FakeControlFiles(object):
157
def __init__(self, user_id=None):
161
def get_utf8(self, filename):
162
if filename != 'email':
163
raise NotImplementedError
164
if self.email is not None:
165
return StringIO(self.email)
166
raise errors.NoSuchFile(filename)
168
def get(self, filename):
170
return StringIO(self.files[filename])
172
raise errors.NoSuchFile(filename)
174
def put(self, filename, fileobj):
175
self.files[filename] = fileobj.read()
178
class InstrumentedConfig(config.Config):
179
"""An instrumented config that supplies stubs for template methods."""
182
super(InstrumentedConfig, self).__init__()
184
self._signatures = config.CHECK_NEVER
186
def _get_user_id(self):
187
self._calls.append('_get_user_id')
188
return "Robert Collins <robert.collins@example.org>"
190
def _get_signature_checking(self):
191
self._calls.append('_get_signature_checking')
192
return self._signatures
195
bool_config = """[DEFAULT]
202
class TestConfigObj(TestCase):
203
def test_get_bool(self):
204
from bzrlib.config import ConfigObj
205
co = ConfigObj(StringIO(bool_config))
206
self.assertIs(co.get_bool('DEFAULT', 'active'), True)
207
self.assertIs(co.get_bool('DEFAULT', 'inactive'), False)
208
self.assertIs(co.get_bool('UPPERCASE', 'active'), True)
209
self.assertIs(co.get_bool('UPPERCASE', 'nonactive'), False)
212
class TestConfig(TestCase):
214
def test_constructs(self):
217
def test_no_default_editor(self):
218
self.assertRaises(NotImplementedError, config.Config().get_editor)
220
def test_user_email(self):
221
my_config = InstrumentedConfig()
222
self.assertEqual('robert.collins@example.org', my_config.user_email())
223
self.assertEqual(['_get_user_id'], my_config._calls)
225
def test_username(self):
226
my_config = InstrumentedConfig()
227
self.assertEqual('Robert Collins <robert.collins@example.org>',
228
my_config.username())
229
self.assertEqual(['_get_user_id'], my_config._calls)
231
def test_signatures_default(self):
232
my_config = config.Config()
233
self.assertFalse(my_config.signature_needed())
234
self.assertEqual(config.CHECK_IF_POSSIBLE,
235
my_config.signature_checking())
236
self.assertEqual(config.SIGN_WHEN_REQUIRED,
237
my_config.signing_policy())
239
def test_signatures_template_method(self):
240
my_config = InstrumentedConfig()
241
self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
242
self.assertEqual(['_get_signature_checking'], my_config._calls)
244
def test_signatures_template_method_none(self):
245
my_config = InstrumentedConfig()
246
my_config._signatures = None
247
self.assertEqual(config.CHECK_IF_POSSIBLE,
248
my_config.signature_checking())
249
self.assertEqual(['_get_signature_checking'], my_config._calls)
251
def test_gpg_signing_command_default(self):
252
my_config = config.Config()
253
self.assertEqual('gpg', my_config.gpg_signing_command())
255
def test_get_user_option_default(self):
256
my_config = config.Config()
257
self.assertEqual(None, my_config.get_user_option('no_option'))
259
def test_post_commit_default(self):
260
my_config = config.Config()
261
self.assertEqual(None, my_config.post_commit())
263
def test_log_format_default(self):
264
my_config = config.Config()
265
self.assertEqual('long', my_config.log_format())
268
class TestConfigPath(TestCase):
271
super(TestConfigPath, self).setUp()
272
self.old_home = os.environ.get('HOME', None)
273
self.old_appdata = os.environ.get('APPDATA', None)
274
os.environ['HOME'] = '/home/bogus'
275
os.environ['APPDATA'] = \
276
r'C:\Documents and Settings\bogus\Application Data'
279
if self.old_home is None:
280
del os.environ['HOME']
282
os.environ['HOME'] = self.old_home
283
if self.old_appdata is None:
284
del os.environ['APPDATA']
286
os.environ['APPDATA'] = self.old_appdata
287
super(TestConfigPath, self).tearDown()
289
def test_config_dir(self):
290
if sys.platform == 'win32':
291
self.assertEqual(config.config_dir(),
292
'C:/Documents and Settings/bogus/Application Data/bazaar/2.0')
294
self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
296
def test_config_filename(self):
297
if sys.platform == 'win32':
298
self.assertEqual(config.config_filename(),
299
'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/bazaar.conf')
301
self.assertEqual(config.config_filename(),
302
'/home/bogus/.bazaar/bazaar.conf')
304
def test_branches_config_filename(self):
305
if sys.platform == 'win32':
306
self.assertEqual(config.branches_config_filename(),
307
'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/branches.conf')
309
self.assertEqual(config.branches_config_filename(),
310
'/home/bogus/.bazaar/branches.conf')
312
def test_locations_config_filename(self):
313
if sys.platform == 'win32':
314
self.assertEqual(config.locations_config_filename(),
315
'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/locations.conf')
317
self.assertEqual(config.locations_config_filename(),
318
'/home/bogus/.bazaar/locations.conf')
320
class TestIniConfig(TestCase):
322
def test_contructs(self):
323
my_config = config.IniBasedConfig("nothing")
325
def test_from_fp(self):
326
config_file = StringIO(sample_config_text.encode('utf-8'))
327
my_config = config.IniBasedConfig(None)
329
isinstance(my_config._get_parser(file=config_file),
332
def test_cached(self):
333
config_file = StringIO(sample_config_text.encode('utf-8'))
334
my_config = config.IniBasedConfig(None)
335
parser = my_config._get_parser(file=config_file)
336
self.failUnless(my_config._get_parser() is parser)
339
class TestGetConfig(TestCase):
341
def test_constructs(self):
342
my_config = config.GlobalConfig()
344
def test_calls_read_filenames(self):
345
# replace the class that is constructured, to check its parameters
346
oldparserclass = config.ConfigObj
347
config.ConfigObj = InstrumentedConfigObj
348
my_config = config.GlobalConfig()
350
parser = my_config._get_parser()
352
config.ConfigObj = oldparserclass
353
self.failUnless(isinstance(parser, InstrumentedConfigObj))
354
self.assertEqual(parser._calls, [('__init__', config.config_filename(),
358
class TestBranchConfig(TestCaseWithTransport):
360
def test_constructs(self):
361
branch = FakeBranch()
362
my_config = config.BranchConfig(branch)
363
self.assertRaises(TypeError, config.BranchConfig)
365
def test_get_location_config(self):
366
branch = FakeBranch()
367
my_config = config.BranchConfig(branch)
368
location_config = my_config._get_location_config()
369
self.assertEqual(branch.base, location_config.location)
370
self.failUnless(location_config is my_config._get_location_config())
372
def test_get_config(self):
373
"""The Branch.get_config method works properly"""
374
b = BzrDir.create_standalone_workingtree('.').branch
375
my_config = b.get_config()
376
self.assertIs(my_config.get_user_option('wacky'), None)
377
my_config.set_user_option('wacky', 'unlikely')
378
self.assertEqual(my_config.get_user_option('wacky'), 'unlikely')
380
# Ensure we get the same thing if we start again
381
b2 = Branch.open('.')
382
my_config2 = b2.get_config()
383
self.assertEqual(my_config2.get_user_option('wacky'), 'unlikely')
385
def test_has_explicit_nickname(self):
386
b = self.make_branch('.')
387
self.assertFalse(b.get_config().has_explicit_nickname())
389
self.assertTrue(b.get_config().has_explicit_nickname())
391
def test_config_url(self):
392
"""The Branch.get_config will use section that uses a local url"""
393
branch = self.make_branch('branch')
394
self.assertEqual('branch', branch.nick)
396
locations = config.locations_config_filename()
397
config.ensure_config_dir_exists()
398
local_url = urlutils.local_path_to_url('branch')
399
open(locations, 'wb').write('[%s]\nnickname = foobar'
401
self.assertEqual('foobar', branch.nick)
403
def test_config_local_path(self):
404
"""The Branch.get_config will use a local system path"""
405
branch = self.make_branch('branch')
406
self.assertEqual('branch', branch.nick)
408
locations = config.locations_config_filename()
409
config.ensure_config_dir_exists()
410
open(locations, 'wb').write('[%s/branch]\nnickname = barry'
411
% (osutils.getcwd().encode('utf8'),))
412
self.assertEqual('barry', branch.nick)
414
def test_config_creates_local(self):
415
"""Creating a new entry in config uses a local path."""
416
branch = self.make_branch('branch')
417
branch.set_push_location('http://foobar')
418
locations = config.locations_config_filename()
419
local_path = osutils.getcwd().encode('utf8')
420
# Surprisingly ConfigObj doesn't create a trailing newline
421
self.check_file_contents(locations,
422
'[%s/branch]\npush_location = http://foobar\npush_location:policy = norecurse' % (local_path,))
424
def test_autonick_urlencoded(self):
425
b = self.make_branch('!repo')
426
self.assertEqual('!repo', b.get_config().get_nickname())
429
class TestGlobalConfigItems(TestCase):
431
def test_user_id(self):
432
config_file = StringIO(sample_config_text.encode('utf-8'))
433
my_config = config.GlobalConfig()
434
my_config._parser = my_config._get_parser(file=config_file)
435
self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
436
my_config._get_user_id())
438
def test_absent_user_id(self):
439
config_file = StringIO("")
440
my_config = config.GlobalConfig()
441
my_config._parser = my_config._get_parser(file=config_file)
442
self.assertEqual(None, my_config._get_user_id())
444
def test_configured_editor(self):
445
config_file = StringIO(sample_config_text.encode('utf-8'))
446
my_config = config.GlobalConfig()
447
my_config._parser = my_config._get_parser(file=config_file)
448
self.assertEqual("vim", my_config.get_editor())
450
def test_signatures_always(self):
451
config_file = StringIO(sample_always_signatures)
452
my_config = config.GlobalConfig()
453
my_config._parser = my_config._get_parser(file=config_file)
454
self.assertEqual(config.CHECK_NEVER,
455
my_config.signature_checking())
456
self.assertEqual(config.SIGN_ALWAYS,
457
my_config.signing_policy())
458
self.assertEqual(True, my_config.signature_needed())
460
def test_signatures_if_possible(self):
461
config_file = StringIO(sample_maybe_signatures)
462
my_config = config.GlobalConfig()
463
my_config._parser = my_config._get_parser(file=config_file)
464
self.assertEqual(config.CHECK_NEVER,
465
my_config.signature_checking())
466
self.assertEqual(config.SIGN_WHEN_REQUIRED,
467
my_config.signing_policy())
468
self.assertEqual(False, my_config.signature_needed())
470
def test_signatures_ignore(self):
471
config_file = StringIO(sample_ignore_signatures)
472
my_config = config.GlobalConfig()
473
my_config._parser = my_config._get_parser(file=config_file)
474
self.assertEqual(config.CHECK_ALWAYS,
475
my_config.signature_checking())
476
self.assertEqual(config.SIGN_NEVER,
477
my_config.signing_policy())
478
self.assertEqual(False, my_config.signature_needed())
480
def _get_sample_config(self):
481
config_file = StringIO(sample_config_text.encode('utf-8'))
482
my_config = config.GlobalConfig()
483
my_config._parser = my_config._get_parser(file=config_file)
486
def test_gpg_signing_command(self):
487
my_config = self._get_sample_config()
488
self.assertEqual("gnome-gpg", my_config.gpg_signing_command())
489
self.assertEqual(False, my_config.signature_needed())
491
def _get_empty_config(self):
492
config_file = StringIO("")
493
my_config = config.GlobalConfig()
494
my_config._parser = my_config._get_parser(file=config_file)
497
def test_gpg_signing_command_unset(self):
498
my_config = self._get_empty_config()
499
self.assertEqual("gpg", my_config.gpg_signing_command())
501
def test_get_user_option_default(self):
502
my_config = self._get_empty_config()
503
self.assertEqual(None, my_config.get_user_option('no_option'))
505
def test_get_user_option_global(self):
506
my_config = self._get_sample_config()
507
self.assertEqual("something",
508
my_config.get_user_option('user_global_option'))
510
def test_post_commit_default(self):
511
my_config = self._get_sample_config()
512
self.assertEqual(None, my_config.post_commit())
514
def test_configured_logformat(self):
515
my_config = self._get_sample_config()
516
self.assertEqual("short", my_config.log_format())
518
def test_get_alias(self):
519
my_config = self._get_sample_config()
520
self.assertEqual('help', my_config.get_alias('h'))
522
def test_get_no_alias(self):
523
my_config = self._get_sample_config()
524
self.assertEqual(None, my_config.get_alias('foo'))
526
def test_get_long_alias(self):
527
my_config = self._get_sample_config()
528
self.assertEqual(sample_long_alias, my_config.get_alias('ll'))
531
class TestLocationConfig(TestCaseInTempDir):
533
def test_constructs(self):
534
my_config = config.LocationConfig('http://example.com')
535
self.assertRaises(TypeError, config.LocationConfig)
537
def test_branch_calls_read_filenames(self):
538
# This is testing the correct file names are provided.
539
# TODO: consolidate with the test for GlobalConfigs filename checks.
541
# replace the class that is constructured, to check its parameters
542
oldparserclass = config.ConfigObj
543
config.ConfigObj = InstrumentedConfigObj
545
my_config = config.LocationConfig('http://www.example.com')
546
parser = my_config._get_parser()
548
config.ConfigObj = oldparserclass
549
self.failUnless(isinstance(parser, InstrumentedConfigObj))
550
self.assertEqual(parser._calls,
551
[('__init__', config.locations_config_filename(),
553
config.ensure_config_dir_exists()
554
#os.mkdir(config.config_dir())
555
f = file(config.branches_config_filename(), 'wb')
558
oldparserclass = config.ConfigObj
559
config.ConfigObj = InstrumentedConfigObj
561
my_config = config.LocationConfig('http://www.example.com')
562
parser = my_config._get_parser()
564
config.ConfigObj = oldparserclass
566
def test_get_global_config(self):
567
my_config = config.BranchConfig(FakeBranch('http://example.com'))
568
global_config = my_config._get_global_config()
569
self.failUnless(isinstance(global_config, config.GlobalConfig))
570
self.failUnless(global_config is my_config._get_global_config())
572
def test__get_matching_sections_no_match(self):
573
self.get_branch_config('/')
574
self.assertEqual([], self.my_location_config._get_matching_sections())
576
def test__get_matching_sections_exact(self):
577
self.get_branch_config('http://www.example.com')
578
self.assertEqual([('http://www.example.com', '')],
579
self.my_location_config._get_matching_sections())
581
def test__get_matching_sections_suffix_does_not(self):
582
self.get_branch_config('http://www.example.com-com')
583
self.assertEqual([], self.my_location_config._get_matching_sections())
585
def test__get_matching_sections_subdir_recursive(self):
586
self.get_branch_config('http://www.example.com/com')
587
self.assertEqual([('http://www.example.com', 'com')],
588
self.my_location_config._get_matching_sections())
590
def test__get_matching_sections_ignoreparent(self):
591
self.get_branch_config('http://www.example.com/ignoreparent')
592
self.assertEqual([('http://www.example.com/ignoreparent', '')],
593
self.my_location_config._get_matching_sections())
595
def test__get_matching_sections_ignoreparent_subdir(self):
596
self.get_branch_config(
597
'http://www.example.com/ignoreparent/childbranch')
598
self.assertEqual([('http://www.example.com/ignoreparent', 'childbranch')],
599
self.my_location_config._get_matching_sections())
601
def test__get_matching_sections_subdir_trailing_slash(self):
602
self.get_branch_config('/b')
603
self.assertEqual([('/b/', '')],
604
self.my_location_config._get_matching_sections())
606
def test__get_matching_sections_subdir_child(self):
607
self.get_branch_config('/a/foo')
608
self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
609
self.my_location_config._get_matching_sections())
611
def test__get_matching_sections_subdir_child_child(self):
612
self.get_branch_config('/a/foo/bar')
613
self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
614
self.my_location_config._get_matching_sections())
616
def test__get_matching_sections_trailing_slash_with_children(self):
617
self.get_branch_config('/a/')
618
self.assertEqual([('/a/', '')],
619
self.my_location_config._get_matching_sections())
621
def test__get_matching_sections_explicit_over_glob(self):
622
# XXX: 2006-09-08 jamesh
623
# This test only passes because ord('c') > ord('*'). If there
624
# was a config section for '/a/?', it would get precedence
626
self.get_branch_config('/a/c')
627
self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
628
self.my_location_config._get_matching_sections())
630
def test__get_option_policy_normal(self):
631
self.get_branch_config('http://www.example.com')
633
self.my_location_config._get_config_policy(
634
'http://www.example.com', 'normal_option'),
637
def test__get_option_policy_norecurse(self):
638
self.get_branch_config('http://www.example.com')
640
self.my_location_config._get_option_policy(
641
'http://www.example.com', 'norecurse_option'),
642
config.POLICY_NORECURSE)
643
# Test old recurse=False setting:
645
self.my_location_config._get_option_policy(
646
'http://www.example.com/norecurse', 'normal_option'),
647
config.POLICY_NORECURSE)
649
def test__get_option_policy_normal(self):
650
self.get_branch_config('http://www.example.com')
652
self.my_location_config._get_option_policy(
653
'http://www.example.com', 'appendpath_option'),
654
config.POLICY_APPENDPATH)
656
def test_location_without_username(self):
657
self.get_branch_config('http://www.example.com/ignoreparent')
658
self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
659
self.my_config.username())
661
def test_location_not_listed(self):
662
"""Test that the global username is used when no location matches"""
663
self.get_branch_config('/home/robertc/sources')
664
self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
665
self.my_config.username())
667
def test_overriding_location(self):
668
self.get_branch_config('http://www.example.com/foo')
669
self.assertEqual('Robert Collins <robertc@example.org>',
670
self.my_config.username())
672
def test_signatures_not_set(self):
673
self.get_branch_config('http://www.example.com',
674
global_config=sample_ignore_signatures)
675
self.assertEqual(config.CHECK_ALWAYS,
676
self.my_config.signature_checking())
677
self.assertEqual(config.SIGN_NEVER,
678
self.my_config.signing_policy())
680
def test_signatures_never(self):
681
self.get_branch_config('/a/c')
682
self.assertEqual(config.CHECK_NEVER,
683
self.my_config.signature_checking())
685
def test_signatures_when_available(self):
686
self.get_branch_config('/a/', global_config=sample_ignore_signatures)
687
self.assertEqual(config.CHECK_IF_POSSIBLE,
688
self.my_config.signature_checking())
690
def test_signatures_always(self):
691
self.get_branch_config('/b')
692
self.assertEqual(config.CHECK_ALWAYS,
693
self.my_config.signature_checking())
695
def test_gpg_signing_command(self):
696
self.get_branch_config('/b')
697
self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
699
def test_gpg_signing_command_missing(self):
700
self.get_branch_config('/a')
701
self.assertEqual("false", self.my_config.gpg_signing_command())
703
def test_get_user_option_global(self):
704
self.get_branch_config('/a')
705
self.assertEqual('something',
706
self.my_config.get_user_option('user_global_option'))
708
def test_get_user_option_local(self):
709
self.get_branch_config('/a')
710
self.assertEqual('local',
711
self.my_config.get_user_option('user_local_option'))
713
def test_get_user_option_appendpath(self):
714
# returned as is for the base path:
715
self.get_branch_config('http://www.example.com')
716
self.assertEqual('append',
717
self.my_config.get_user_option('appendpath_option'))
718
# Extra path components get appended:
719
self.get_branch_config('http://www.example.com/a/b/c')
720
self.assertEqual('append/a/b/c',
721
self.my_config.get_user_option('appendpath_option'))
722
# Overriden for http://www.example.com/dir, where it is a
724
self.get_branch_config('http://www.example.com/dir/a/b/c')
725
self.assertEqual('normal',
726
self.my_config.get_user_option('appendpath_option'))
728
def test_get_user_option_norecurse(self):
729
self.get_branch_config('http://www.example.com')
730
self.assertEqual('norecurse',
731
self.my_config.get_user_option('norecurse_option'))
732
self.get_branch_config('http://www.example.com/dir')
733
self.assertEqual(None,
734
self.my_config.get_user_option('norecurse_option'))
735
# http://www.example.com/norecurse is a recurse=False section
736
# that redefines normal_option. Subdirectories do not pick up
738
self.get_branch_config('http://www.example.com/norecurse')
739
self.assertEqual('norecurse',
740
self.my_config.get_user_option('normal_option'))
741
self.get_branch_config('http://www.example.com/norecurse/subdir')
742
self.assertEqual('normal',
743
self.my_config.get_user_option('normal_option'))
745
def test_set_user_option_norecurse(self):
746
self.get_branch_config('http://www.example.com')
747
self.my_config.set_user_option('foo', 'bar',
748
store=config.STORE_LOCATION_NORECURSE)
750
self.my_location_config._get_option_policy(
751
'http://www.example.com', 'foo'),
752
config.POLICY_NORECURSE)
754
def test_set_user_option_appendpath(self):
755
self.get_branch_config('http://www.example.com')
756
self.my_config.set_user_option('foo', 'bar',
757
store=config.STORE_LOCATION_APPENDPATH)
759
self.my_location_config._get_option_policy(
760
'http://www.example.com', 'foo'),
761
config.POLICY_APPENDPATH)
763
def test_set_user_option_change_policy(self):
764
self.get_branch_config('http://www.example.com')
765
self.my_config.set_user_option('norecurse_option', 'normal',
766
store=config.STORE_LOCATION)
768
self.my_location_config._get_option_policy(
769
'http://www.example.com', 'norecurse_option'),
772
def test_set_user_option_recurse_false_section(self):
773
# The following section has recurse=False set. The test is to
774
# make sure that a normal option can be added to the section,
775
# converting recurse=False to the norecurse policy.
776
self.get_branch_config('http://www.example.com/norecurse')
777
self.callDeprecated(['The recurse option is deprecated as of 0.14. '
778
'The section "http://www.example.com/norecurse" '
779
'has been converted to use policies.'],
780
self.my_config.set_user_option,
781
'foo', 'bar', store=config.STORE_LOCATION)
783
self.my_location_config._get_option_policy(
784
'http://www.example.com/norecurse', 'foo'),
786
# The previously existing option is still norecurse:
788
self.my_location_config._get_option_policy(
789
'http://www.example.com/norecurse', 'normal_option'),
790
config.POLICY_NORECURSE)
793
def test_post_commit_default(self):
794
self.get_branch_config('/a/c')
795
self.assertEqual('bzrlib.tests.test_config.post_commit',
796
self.my_config.post_commit())
798
def get_branch_config(self, location, global_config=None):
799
if global_config is None:
800
global_file = StringIO(sample_config_text.encode('utf-8'))
802
global_file = StringIO(global_config.encode('utf-8'))
803
branches_file = StringIO(sample_branches_text.encode('utf-8'))
804
self.my_config = config.BranchConfig(FakeBranch(location))
805
# Force location config to use specified file
806
self.my_location_config = self.my_config._get_location_config()
807
self.my_location_config._get_parser(branches_file)
808
# Force global config to use specified file
809
self.my_config._get_global_config()._get_parser(global_file)
811
def test_set_user_setting_sets_and_saves(self):
812
self.get_branch_config('/a/c')
813
record = InstrumentedConfigObj("foo")
814
self.my_location_config._parser = record
816
real_mkdir = os.mkdir
818
def checked_mkdir(path, mode=0777):
819
self.log('making directory: %s', path)
820
real_mkdir(path, mode)
823
os.mkdir = checked_mkdir
825
self.callDeprecated(['The recurse option is deprecated as of '
826
'0.14. The section "/a/c" has been '
827
'converted to use policies.'],
828
self.my_config.set_user_option,
829
'foo', 'bar', store=config.STORE_LOCATION)
831
os.mkdir = real_mkdir
833
self.failUnless(self.created, 'Failed to create ~/.bazaar')
834
self.assertEqual([('__contains__', '/a/c'),
835
('__contains__', '/a/c/'),
836
('__setitem__', '/a/c', {}),
837
('__getitem__', '/a/c'),
838
('__setitem__', 'foo', 'bar'),
839
('__getitem__', '/a/c'),
840
('as_bool', 'recurse'),
841
('__getitem__', '/a/c'),
842
('__delitem__', 'recurse'),
843
('__getitem__', '/a/c'),
845
('__getitem__', '/a/c'),
846
('__contains__', 'foo:policy'),
850
def test_set_user_setting_sets_and_saves2(self):
851
self.get_branch_config('/a/c')
852
self.assertIs(self.my_config.get_user_option('foo'), None)
853
self.my_config.set_user_option('foo', 'bar')
855
self.my_config.branch.control_files.files['branch.conf'],
857
self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
858
self.my_config.set_user_option('foo', 'baz',
859
store=config.STORE_LOCATION)
860
self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
861
self.my_config.set_user_option('foo', 'qux')
862
self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
865
precedence_global = 'option = global'
866
precedence_branch = 'option = branch'
867
precedence_location = """
871
[http://example.com/specific]
876
class TestBranchConfigItems(TestCaseInTempDir):
878
def get_branch_config(self, global_config=None, location=None,
879
location_config=None, branch_data_config=None):
880
my_config = config.BranchConfig(FakeBranch(location))
881
if global_config is not None:
882
global_file = StringIO(global_config.encode('utf-8'))
883
my_config._get_global_config()._get_parser(global_file)
884
self.my_location_config = my_config._get_location_config()
885
if location_config is not None:
886
location_file = StringIO(location_config.encode('utf-8'))
887
self.my_location_config._get_parser(location_file)
888
if branch_data_config is not None:
889
my_config.branch.control_files.files['branch.conf'] = \
893
def test_user_id(self):
894
branch = FakeBranch(user_id='Robert Collins <robertc@example.net>')
895
my_config = config.BranchConfig(branch)
896
self.assertEqual("Robert Collins <robertc@example.net>",
897
my_config.username())
898
branch.control_files.email = "John"
899
my_config.set_user_option('email',
900
"Robert Collins <robertc@example.org>")
901
self.assertEqual("John", my_config.username())
902
branch.control_files.email = None
903
self.assertEqual("Robert Collins <robertc@example.org>",
904
my_config.username())
906
def test_not_set_in_branch(self):
907
my_config = self.get_branch_config(sample_config_text)
908
my_config.branch.control_files.email = None
909
self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
910
my_config._get_user_id())
911
my_config.branch.control_files.email = "John"
912
self.assertEqual("John", my_config._get_user_id())
914
def test_BZR_EMAIL_OVERRIDES(self):
915
os.environ['BZR_EMAIL'] = "Robert Collins <robertc@example.org>"
916
branch = FakeBranch()
917
my_config = config.BranchConfig(branch)
918
self.assertEqual("Robert Collins <robertc@example.org>",
919
my_config.username())
921
def test_signatures_forced(self):
922
my_config = self.get_branch_config(
923
global_config=sample_always_signatures)
924
self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
925
self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
926
self.assertTrue(my_config.signature_needed())
928
def test_signatures_forced_branch(self):
929
my_config = self.get_branch_config(
930
global_config=sample_ignore_signatures,
931
branch_data_config=sample_always_signatures)
932
self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
933
self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
934
self.assertTrue(my_config.signature_needed())
936
def test_gpg_signing_command(self):
937
my_config = self.get_branch_config(
938
# branch data cannot set gpg_signing_command
939
branch_data_config="gpg_signing_command=pgp")
940
config_file = StringIO(sample_config_text.encode('utf-8'))
941
my_config._get_global_config()._get_parser(config_file)
942
self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
944
def test_get_user_option_global(self):
945
branch = FakeBranch()
946
my_config = config.BranchConfig(branch)
947
config_file = StringIO(sample_config_text.encode('utf-8'))
948
(my_config._get_global_config()._get_parser(config_file))
949
self.assertEqual('something',
950
my_config.get_user_option('user_global_option'))
952
def test_post_commit_default(self):
953
branch = FakeBranch()
954
my_config = self.get_branch_config(sample_config_text, '/a/c',
955
sample_branches_text)
956
self.assertEqual(my_config.branch.base, '/a/c')
957
self.assertEqual('bzrlib.tests.test_config.post_commit',
958
my_config.post_commit())
959
my_config.set_user_option('post_commit', 'rmtree_root')
960
# post-commit is ignored when bresent in branch data
961
self.assertEqual('bzrlib.tests.test_config.post_commit',
962
my_config.post_commit())
963
my_config.set_user_option('post_commit', 'rmtree_root',
964
store=config.STORE_LOCATION)
965
self.assertEqual('rmtree_root', my_config.post_commit())
967
def test_config_precedence(self):
968
my_config = self.get_branch_config(global_config=precedence_global)
969
self.assertEqual(my_config.get_user_option('option'), 'global')
970
my_config = self.get_branch_config(global_config=precedence_global,
971
branch_data_config=precedence_branch)
972
self.assertEqual(my_config.get_user_option('option'), 'branch')
973
my_config = self.get_branch_config(global_config=precedence_global,
974
branch_data_config=precedence_branch,
975
location_config=precedence_location)
976
self.assertEqual(my_config.get_user_option('option'), 'recurse')
977
my_config = self.get_branch_config(global_config=precedence_global,
978
branch_data_config=precedence_branch,
979
location_config=precedence_location,
980
location='http://example.com/specific')
981
self.assertEqual(my_config.get_user_option('option'), 'exact')
984
class TestMailAddressExtraction(TestCase):
986
def test_extract_email_address(self):
987
self.assertEqual('jane@test.com',
988
config.extract_email_address('Jane <jane@test.com>'))
989
self.assertRaises(errors.NoEmailInUsername,
990
config.extract_email_address, 'Jane Tester')