~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testconfig.py

  • Committer: Robert Collins
  • Date: 2005-10-18 13:11:57 UTC
  • mfrom: (1185.16.72) (0.2.1)
  • Revision ID: robertc@robertcollins.net-20051018131157-76a9970aa78e927e
Merged Martin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005 by Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
17
17
 
18
18
"""Tests for finding and reading the bzr config file[s]."""
19
19
# import system imports here
20
 
from bzrlib.util.configobj.configobj import ConfigObj, ConfigObjError
 
20
from ConfigParser import ConfigParser
21
21
from cStringIO import StringIO
22
22
import os
23
23
import sys
24
24
 
25
25
#import bzrlib specific imports here
26
 
from bzrlib import (
27
 
    config,
28
 
    errors,
29
 
    osutils,
30
 
    urlutils,
31
 
    )
32
 
from bzrlib.branch import Branch
33
 
from bzrlib.bzrdir import BzrDir
34
 
from bzrlib.tests import TestCase, TestCaseInTempDir, TestCaseWithTransport
35
 
 
36
 
 
37
 
sample_long_alias="log -r-15..-1 --line"
38
 
sample_config_text = u"""
39
 
[DEFAULT]
40
 
email=Erik B\u00e5gfors <erik@bagfors.nu>
41
 
editor=vim
42
 
gpg_signing_command=gnome-gpg
43
 
log_format=short
44
 
user_global_option=something
45
 
[ALIASES]
46
 
h=help
47
 
ll=""" + sample_long_alias + "\n"
48
 
 
49
 
 
50
 
sample_always_signatures = """
51
 
[DEFAULT]
52
 
check_signatures=ignore
53
 
create_signatures=always
54
 
"""
55
 
 
56
 
sample_ignore_signatures = """
57
 
[DEFAULT]
58
 
check_signatures=require
59
 
create_signatures=never
60
 
"""
61
 
 
62
 
sample_maybe_signatures = """
63
 
[DEFAULT]
64
 
check_signatures=ignore
65
 
create_signatures=when-required
66
 
"""
67
 
 
68
 
sample_branches_text = """
69
 
[http://www.example.com]
70
 
# Top level policy
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
79
 
ignore_parents=true
80
 
[http://www.example.com/norecurse]
81
 
# configuration items that only apply to this dir
82
 
recurse=false
83
 
normal_option = norecurse
84
 
[http://www.example.com/dir]
85
 
appendpath_option = normal
86
 
[/b/]
87
 
check_signatures=require
88
 
# test trailing / matching with no children
89
 
[/a/]
90
 
check_signatures=check-available
91
 
gpg_signing_command=false
92
 
user_local_option=local
93
 
# test trailing / matching
94
 
[/a/*]
95
 
#subdirs will match but not the parent
96
 
[/a/c]
97
 
check_signatures=ignore
98
 
post_commit=bzrlib.tests.test_config.post_commit
99
 
#testing explicit beats globs
100
 
"""
101
 
 
102
 
 
103
 
class InstrumentedConfigObj(object):
104
 
    """A config obj look-enough-alike to record calls made to it."""
105
 
 
106
 
    def __contains__(self, thing):
107
 
        self._calls.append(('__contains__', thing))
108
 
        return False
109
 
 
110
 
    def __getitem__(self, key):
111
 
        self._calls.append(('__getitem__', key))
112
 
        return self
113
 
 
114
 
    def __init__(self, input, encoding=None):
115
 
        self._calls = [('__init__', input, encoding)]
116
 
 
117
 
    def __setitem__(self, key, value):
118
 
        self._calls.append(('__setitem__', key, value))
119
 
 
120
 
    def __delitem__(self, key):
121
 
        self._calls.append(('__delitem__', key))
122
 
 
123
 
    def keys(self):
124
 
        self._calls.append(('keys',))
125
 
        return []
126
 
 
127
 
    def write(self, arg):
128
 
        self._calls.append(('write',))
129
 
 
130
 
    def as_bool(self, value):
131
 
        self._calls.append(('as_bool', value))
132
 
        return False
133
 
 
134
 
    def get_value(self, section, name):
135
 
        self._calls.append(('get_value', section, name))
136
 
        return None
 
26
import bzrlib.config as config
 
27
import bzrlib.errors as errors
 
28
from bzrlib.selftest import TestCase, TestCaseInTempDir
 
29
 
 
30
 
 
31
sample_config_text = ("[DEFAULT]\n"
 
32
                      "email=Robert Collins <robertc@example.com>\n"
 
33
                      "editor=vim\n"
 
34
                      "gpg_signing_command=gnome-gpg\n"
 
35
                      "user_global_option=something\n")
 
36
 
 
37
 
 
38
sample_always_signatures = ("[DEFAULT]\n"
 
39
                            "check_signatures=require\n")
 
40
 
 
41
 
 
42
sample_ignore_signatures = ("[DEFAULT]\n"
 
43
                            "check_signatures=ignore\n")
 
44
 
 
45
 
 
46
sample_maybe_signatures = ("[DEFAULT]\n"
 
47
                            "check_signatures=check-available\n")
 
48
 
 
49
 
 
50
sample_branches_text = ("[http://www.example.com]\n"
 
51
                        "# Top level policy\n"
 
52
                        "email=Robert Collins <robertc@example.org>\n"
 
53
                        "[http://www.example.com/useglobal]\n"
 
54
                        "# different project, forces global lookup\n"
 
55
                        "recurse=false\n"
 
56
                        "[/b/]\n"
 
57
                        "check_signatures=require\n"
 
58
                        "# test trailing / matching with no children\n"
 
59
                        "[/a/]\n"
 
60
                        "check_signatures=check-available\n"
 
61
                        "gpg_signing_command=false\n"
 
62
                        "user_local_option=local\n"
 
63
                        "# test trailing / matching\n"
 
64
                        "[/a/*]\n"
 
65
                        "#subdirs will match but not the parent\n"
 
66
                        "recurse=False\n"
 
67
                        "[/a/c]\n"
 
68
                        "check_signatures=ignore\n"
 
69
                        "#testing explicit beats globs\n")
 
70
 
 
71
 
 
72
class InstrumentedConfigParser(object):
 
73
    """A config parser look-enough-alike to record calls made to it."""
 
74
 
 
75
    def __init__(self):
 
76
        self._calls = []
 
77
 
 
78
    def read(self, filenames):
 
79
        self._calls.append(('read', filenames))
137
80
 
138
81
 
139
82
class FakeBranch(object):
140
83
 
141
 
    def __init__(self, base=None, user_id=None):
142
 
        if base is None:
143
 
            self.base = "http://example.com/branches/demo"
144
 
        else:
145
 
            self.base = base
146
 
        self.control_files = FakeControlFiles(user_id=user_id)
147
 
 
148
 
    def lock_write(self):
149
 
        pass
150
 
 
151
 
    def unlock(self):
152
 
        pass
153
 
 
154
 
 
155
 
class FakeControlFiles(object):
156
 
 
157
 
    def __init__(self, user_id=None):
158
 
        self.email = user_id
159
 
        self.files = {}
160
 
 
161
 
    def get_utf8(self, filename):
 
84
    def __init__(self):
 
85
        self.base = "http://example.com/branches/demo"
 
86
        self.email = 'Robert Collins <robertc@example.net>\n'
 
87
 
 
88
    def controlfile(self, filename, mode):
162
89
        if filename != 'email':
163
90
            raise NotImplementedError
164
91
        if self.email is not None:
165
92
            return StringIO(self.email)
166
 
        raise errors.NoSuchFile(filename)
167
 
 
168
 
    def get(self, filename):
169
 
        try:
170
 
            return StringIO(self.files[filename])
171
 
        except KeyError:
172
 
            raise errors.NoSuchFile(filename)
173
 
 
174
 
    def put(self, filename, fileobj):
175
 
        self.files[filename] = fileobj.read()
 
93
        raise errors.NoSuchFile
176
94
 
177
95
 
178
96
class InstrumentedConfig(config.Config):
192
110
        return self._signatures
193
111
 
194
112
 
195
 
bool_config = """[DEFAULT]
196
 
active = true
197
 
inactive = false
198
 
[UPPERCASE]
199
 
active = True
200
 
nonactive = False
201
 
"""
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)
210
 
 
211
 
 
212
113
class TestConfig(TestCase):
213
114
 
214
115
    def test_constructs(self):
230
131
 
231
132
    def test_signatures_default(self):
232
133
        my_config = config.Config()
233
 
        self.assertFalse(my_config.signature_needed())
234
134
        self.assertEqual(config.CHECK_IF_POSSIBLE,
235
135
                         my_config.signature_checking())
236
 
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
237
 
                         my_config.signing_policy())
238
136
 
239
137
    def test_signatures_template_method(self):
240
138
        my_config = InstrumentedConfig()
256
154
        my_config = config.Config()
257
155
        self.assertEqual(None, my_config.get_user_option('no_option'))
258
156
 
259
 
    def test_post_commit_default(self):
260
 
        my_config = config.Config()
261
 
        self.assertEqual(None, my_config.post_commit())
262
 
 
263
 
    def test_log_format_default(self):
264
 
        my_config = config.Config()
265
 
        self.assertEqual('long', my_config.log_format())
266
 
 
267
157
 
268
158
class TestConfigPath(TestCase):
269
159
 
270
160
    def setUp(self):
271
161
        super(TestConfigPath, self).setUp()
272
 
        self.old_home = os.environ.get('HOME', None)
273
 
        self.old_appdata = os.environ.get('APPDATA', None)
 
162
        self.oldenv = os.environ.get('HOME', None)
274
163
        os.environ['HOME'] = '/home/bogus'
275
 
        os.environ['APPDATA'] = \
276
 
            r'C:\Documents and Settings\bogus\Application Data'
277
164
 
278
165
    def tearDown(self):
279
 
        if self.old_home is None:
280
 
            del os.environ['HOME']
281
 
        else:
282
 
            os.environ['HOME'] = self.old_home
283
 
        if self.old_appdata is None:
284
 
            del os.environ['APPDATA']
285
 
        else:
286
 
            os.environ['APPDATA'] = self.old_appdata
 
166
        os.environ['HOME'] = self.oldenv
287
167
        super(TestConfigPath, self).tearDown()
288
168
    
289
169
    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')
293
 
        else:
294
 
            self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
 
170
        self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
295
171
 
296
172
    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')
300
 
        else:
301
 
            self.assertEqual(config.config_filename(),
302
 
                             '/home/bogus/.bazaar/bazaar.conf')
 
173
        self.assertEqual(config.config_filename(),
 
174
                         '/home/bogus/.bazaar/bazaar.conf')
303
175
 
304
176
    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')
308
 
        else:
309
 
            self.assertEqual(config.branches_config_filename(),
310
 
                             '/home/bogus/.bazaar/branches.conf')
311
 
 
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')
316
 
        else:
317
 
            self.assertEqual(config.locations_config_filename(),
318
 
                             '/home/bogus/.bazaar/locations.conf')
 
177
        self.assertEqual(config.branches_config_filename(),
 
178
                         '/home/bogus/.bazaar/branches.conf')
319
179
 
320
180
class TestIniConfig(TestCase):
321
181
 
323
183
        my_config = config.IniBasedConfig("nothing")
324
184
 
325
185
    def test_from_fp(self):
326
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
186
        config_file = StringIO(sample_config_text)
327
187
        my_config = config.IniBasedConfig(None)
328
188
        self.failUnless(
329
189
            isinstance(my_config._get_parser(file=config_file),
330
 
                        ConfigObj))
 
190
                        ConfigParser))
331
191
 
332
192
    def test_cached(self):
333
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
193
        config_file = StringIO(sample_config_text)
334
194
        my_config = config.IniBasedConfig(None)
335
195
        parser = my_config._get_parser(file=config_file)
336
196
        self.failUnless(my_config._get_parser() is parser)
343
203
 
344
204
    def test_calls_read_filenames(self):
345
205
        # replace the class that is constructured, to check its parameters
346
 
        oldparserclass = config.ConfigObj
347
 
        config.ConfigObj = InstrumentedConfigObj
 
206
        oldparserclass = config.ConfigParser
 
207
        config.ConfigParser = InstrumentedConfigParser
348
208
        my_config = config.GlobalConfig()
349
209
        try:
350
210
            parser = my_config._get_parser()
351
211
        finally:
352
 
            config.ConfigObj = oldparserclass
353
 
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
354
 
        self.assertEqual(parser._calls, [('__init__', config.config_filename(),
355
 
                                          'utf-8')])
356
 
 
357
 
 
358
 
class TestBranchConfig(TestCaseWithTransport):
 
212
            config.ConfigParser = oldparserclass
 
213
        self.failUnless(isinstance(parser, InstrumentedConfigParser))
 
214
        self.assertEqual(parser._calls, [('read', [config.config_filename()])])
 
215
 
 
216
 
 
217
class TestBranchConfig(TestCaseInTempDir):
359
218
 
360
219
    def test_constructs(self):
361
220
        branch = FakeBranch()
369
228
        self.assertEqual(branch.base, location_config.location)
370
229
        self.failUnless(location_config is my_config._get_location_config())
371
230
 
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')
379
 
 
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')
384
 
 
385
 
    def test_has_explicit_nickname(self):
386
 
        b = self.make_branch('.')
387
 
        self.assertFalse(b.get_config().has_explicit_nickname())
388
 
        b.nick = 'foo'
389
 
        self.assertTrue(b.get_config().has_explicit_nickname())
390
 
 
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)
395
 
 
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' 
400
 
                                    % (local_url,))
401
 
        self.assertEqual('foobar', branch.nick)
402
 
 
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)
407
 
 
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)
413
 
 
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,))
423
 
 
424
 
    def test_autonick_urlencoded(self):
425
 
        b = self.make_branch('!repo')
426
 
        self.assertEqual('!repo', b.get_config().get_nickname())
427
 
 
428
231
 
429
232
class TestGlobalConfigItems(TestCase):
430
233
 
431
234
    def test_user_id(self):
432
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
235
        config_file = StringIO(sample_config_text)
433
236
        my_config = config.GlobalConfig()
434
237
        my_config._parser = my_config._get_parser(file=config_file)
435
 
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
 
238
        self.assertEqual("Robert Collins <robertc@example.com>",
436
239
                         my_config._get_user_id())
437
240
 
438
241
    def test_absent_user_id(self):
442
245
        self.assertEqual(None, my_config._get_user_id())
443
246
 
444
247
    def test_configured_editor(self):
445
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
248
        config_file = StringIO(sample_config_text)
446
249
        my_config = config.GlobalConfig()
447
250
        my_config._parser = my_config._get_parser(file=config_file)
448
251
        self.assertEqual("vim", my_config.get_editor())
451
254
        config_file = StringIO(sample_always_signatures)
452
255
        my_config = config.GlobalConfig()
453
256
        my_config._parser = my_config._get_parser(file=config_file)
454
 
        self.assertEqual(config.CHECK_NEVER,
 
257
        self.assertEqual(config.CHECK_ALWAYS,
455
258
                         my_config.signature_checking())
456
 
        self.assertEqual(config.SIGN_ALWAYS,
457
 
                         my_config.signing_policy())
458
259
        self.assertEqual(True, my_config.signature_needed())
459
260
 
460
261
    def test_signatures_if_possible(self):
461
262
        config_file = StringIO(sample_maybe_signatures)
462
263
        my_config = config.GlobalConfig()
463
264
        my_config._parser = my_config._get_parser(file=config_file)
464
 
        self.assertEqual(config.CHECK_NEVER,
 
265
        self.assertEqual(config.CHECK_IF_POSSIBLE,
465
266
                         my_config.signature_checking())
466
 
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
467
 
                         my_config.signing_policy())
468
267
        self.assertEqual(False, my_config.signature_needed())
469
268
 
470
269
    def test_signatures_ignore(self):
471
270
        config_file = StringIO(sample_ignore_signatures)
472
271
        my_config = config.GlobalConfig()
473
272
        my_config._parser = my_config._get_parser(file=config_file)
474
 
        self.assertEqual(config.CHECK_ALWAYS,
 
273
        self.assertEqual(config.CHECK_NEVER,
475
274
                         my_config.signature_checking())
476
 
        self.assertEqual(config.SIGN_NEVER,
477
 
                         my_config.signing_policy())
478
275
        self.assertEqual(False, my_config.signature_needed())
479
276
 
480
277
    def _get_sample_config(self):
481
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
278
        config_file = StringIO(sample_config_text)
482
279
        my_config = config.GlobalConfig()
483
280
        my_config._parser = my_config._get_parser(file=config_file)
484
281
        return my_config
506
303
        my_config = self._get_sample_config()
507
304
        self.assertEqual("something",
508
305
                         my_config.get_user_option('user_global_option'))
509
 
        
510
 
    def test_post_commit_default(self):
511
 
        my_config = self._get_sample_config()
512
 
        self.assertEqual(None, my_config.post_commit())
513
 
 
514
 
    def test_configured_logformat(self):
515
 
        my_config = self._get_sample_config()
516
 
        self.assertEqual("short", my_config.log_format())
517
 
 
518
 
    def test_get_alias(self):
519
 
        my_config = self._get_sample_config()
520
 
        self.assertEqual('help', my_config.get_alias('h'))
521
 
 
522
 
    def test_get_no_alias(self):
523
 
        my_config = self._get_sample_config()
524
 
        self.assertEqual(None, my_config.get_alias('foo'))
525
 
 
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'))
529
 
 
530
 
 
531
 
class TestLocationConfig(TestCaseInTempDir):
 
306
 
 
307
 
 
308
class TestLocationConfig(TestCase):
532
309
 
533
310
    def test_constructs(self):
534
311
        my_config = config.LocationConfig('http://example.com')
535
312
        self.assertRaises(TypeError, config.LocationConfig)
536
313
 
537
314
    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.
540
 
        #
541
315
        # replace the class that is constructured, to check its parameters
542
 
        oldparserclass = config.ConfigObj
543
 
        config.ConfigObj = InstrumentedConfigObj
544
 
        try:
545
 
            my_config = config.LocationConfig('http://www.example.com')
546
 
            parser = my_config._get_parser()
547
 
        finally:
548
 
            config.ConfigObj = oldparserclass
549
 
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
550
 
        self.assertEqual(parser._calls,
551
 
                         [('__init__', config.locations_config_filename(),
552
 
                           'utf-8')])
553
 
        config.ensure_config_dir_exists()
554
 
        #os.mkdir(config.config_dir())
555
 
        f = file(config.branches_config_filename(), 'wb')
556
 
        f.write('')
557
 
        f.close()
558
 
        oldparserclass = config.ConfigObj
559
 
        config.ConfigObj = InstrumentedConfigObj
560
 
        try:
561
 
            my_config = config.LocationConfig('http://www.example.com')
562
 
            parser = my_config._get_parser()
563
 
        finally:
564
 
            config.ConfigObj = oldparserclass
 
316
        oldparserclass = config.ConfigParser
 
317
        config.ConfigParser = InstrumentedConfigParser
 
318
        my_config = config.LocationConfig('http://www.example.com')
 
319
        try:
 
320
            parser = my_config._get_parser()
 
321
        finally:
 
322
            config.ConfigParser = oldparserclass
 
323
        self.failUnless(isinstance(parser, InstrumentedConfigParser))
 
324
        self.assertEqual(parser._calls, [('read', [config.branches_config_filename()])])
565
325
 
566
326
    def test_get_global_config(self):
567
 
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
 
327
        my_config = config.LocationConfig('http://example.com')
568
328
        global_config = my_config._get_global_config()
569
329
        self.failUnless(isinstance(global_config, config.GlobalConfig))
570
330
        self.failUnless(global_config is my_config._get_global_config())
571
331
 
572
 
    def test__get_matching_sections_no_match(self):
573
 
        self.get_branch_config('/')
574
 
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
332
    def test__get_section_no_match(self):
 
333
        self.get_location_config('/')
 
334
        self.assertEqual(None, self.my_config._get_section())
575
335
        
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())
 
336
    def test__get_section_exact(self):
 
337
        self.get_location_config('http://www.example.com')
 
338
        self.assertEqual('http://www.example.com',
 
339
                         self.my_config._get_section())
580
340
   
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())
584
 
 
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())
589
 
 
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())
594
 
 
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())
600
 
 
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())
605
 
 
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())
610
 
 
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())
615
 
 
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())
620
 
 
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
625
 
        # over '/a/c'.
626
 
        self.get_branch_config('/a/c')
627
 
        self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
628
 
                         self.my_location_config._get_matching_sections())
629
 
 
630
 
    def test__get_option_policy_normal(self):
631
 
        self.get_branch_config('http://www.example.com')
632
 
        self.assertEqual(
633
 
            self.my_location_config._get_config_policy(
634
 
            'http://www.example.com', 'normal_option'),
635
 
            config.POLICY_NONE)
636
 
 
637
 
    def test__get_option_policy_norecurse(self):
638
 
        self.get_branch_config('http://www.example.com')
639
 
        self.assertEqual(
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:
644
 
        self.assertEqual(
645
 
            self.my_location_config._get_option_policy(
646
 
            'http://www.example.com/norecurse', 'normal_option'),
647
 
            config.POLICY_NORECURSE)
648
 
 
649
 
    def test__get_option_policy_normal(self):
650
 
        self.get_branch_config('http://www.example.com')
651
 
        self.assertEqual(
652
 
            self.my_location_config._get_option_policy(
653
 
            'http://www.example.com', 'appendpath_option'),
654
 
            config.POLICY_APPENDPATH)
 
341
    def test__get_section_suffix_does_not(self):
 
342
        self.get_location_config('http://www.example.com-com')
 
343
        self.assertEqual(None, self.my_config._get_section())
 
344
 
 
345
    def test__get_section_subdir_recursive(self):
 
346
        self.get_location_config('http://www.example.com/com')
 
347
        self.assertEqual('http://www.example.com',
 
348
                         self.my_config._get_section())
 
349
 
 
350
    def test__get_section_subdir_matches(self):
 
351
        self.get_location_config('http://www.example.com/useglobal')
 
352
        self.assertEqual('http://www.example.com/useglobal',
 
353
                         self.my_config._get_section())
 
354
 
 
355
    def test__get_section_subdir_nonrecursive(self):
 
356
        self.get_location_config(
 
357
            'http://www.example.com/useglobal/childbranch')
 
358
        self.assertEqual('http://www.example.com',
 
359
                         self.my_config._get_section())
 
360
 
 
361
    def test__get_section_subdir_trailing_slash(self):
 
362
        self.get_location_config('/b')
 
363
        self.assertEqual('/b/', self.my_config._get_section())
 
364
 
 
365
    def test__get_section_subdir_child(self):
 
366
        self.get_location_config('/a/foo')
 
367
        self.assertEqual('/a/*', self.my_config._get_section())
 
368
 
 
369
    def test__get_section_subdir_child_child(self):
 
370
        self.get_location_config('/a/foo/bar')
 
371
        self.assertEqual('/a/', self.my_config._get_section())
 
372
 
 
373
    def test__get_section_trailing_slash_with_children(self):
 
374
        self.get_location_config('/a/')
 
375
        self.assertEqual('/a/', self.my_config._get_section())
 
376
 
 
377
    def test__get_section_explicit_over_glob(self):
 
378
        self.get_location_config('/a/c')
 
379
        self.assertEqual('/a/c', self.my_config._get_section())
 
380
 
 
381
    def get_location_config(self, location, global_config=None):
 
382
        if global_config is None:
 
383
            global_file = StringIO(sample_config_text)
 
384
        else:
 
385
            global_file = StringIO(global_config)
 
386
        branches_file = StringIO(sample_branches_text)
 
387
        self.my_config = config.LocationConfig(location)
 
388
        self.my_config._get_parser(branches_file)
 
389
        self.my_config._get_global_config()._get_parser(global_file)
655
390
 
656
391
    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>',
 
392
        self.get_location_config('http://www.example.com/useglobal')
 
393
        self.assertEqual('Robert Collins <robertc@example.com>',
659
394
                         self.my_config.username())
660
395
 
661
396
    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>',
 
397
        self.get_location_config('/home/robertc/sources')
 
398
        self.assertEqual('Robert Collins <robertc@example.com>',
665
399
                         self.my_config.username())
666
400
 
667
401
    def test_overriding_location(self):
668
 
        self.get_branch_config('http://www.example.com/foo')
 
402
        self.get_location_config('http://www.example.com/foo')
669
403
        self.assertEqual('Robert Collins <robertc@example.org>',
670
404
                         self.my_config.username())
671
405
 
672
406
    def test_signatures_not_set(self):
673
 
        self.get_branch_config('http://www.example.com',
 
407
        self.get_location_config('http://www.example.com',
674
408
                                 global_config=sample_ignore_signatures)
675
 
        self.assertEqual(config.CHECK_ALWAYS,
 
409
        self.assertEqual(config.CHECK_NEVER,
676
410
                         self.my_config.signature_checking())
677
 
        self.assertEqual(config.SIGN_NEVER,
678
 
                         self.my_config.signing_policy())
679
411
 
680
412
    def test_signatures_never(self):
681
 
        self.get_branch_config('/a/c')
 
413
        self.get_location_config('/a/c')
682
414
        self.assertEqual(config.CHECK_NEVER,
683
415
                         self.my_config.signature_checking())
684
416
        
685
417
    def test_signatures_when_available(self):
686
 
        self.get_branch_config('/a/', global_config=sample_ignore_signatures)
 
418
        self.get_location_config('/a/', global_config=sample_ignore_signatures)
687
419
        self.assertEqual(config.CHECK_IF_POSSIBLE,
688
420
                         self.my_config.signature_checking())
689
421
        
690
422
    def test_signatures_always(self):
691
 
        self.get_branch_config('/b')
 
423
        self.get_location_config('/b')
692
424
        self.assertEqual(config.CHECK_ALWAYS,
693
425
                         self.my_config.signature_checking())
694
426
        
695
427
    def test_gpg_signing_command(self):
696
 
        self.get_branch_config('/b')
 
428
        self.get_location_config('/b')
697
429
        self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
698
430
 
699
431
    def test_gpg_signing_command_missing(self):
700
 
        self.get_branch_config('/a')
 
432
        self.get_location_config('/a')
701
433
        self.assertEqual("false", self.my_config.gpg_signing_command())
702
434
 
703
435
    def test_get_user_option_global(self):
704
 
        self.get_branch_config('/a')
 
436
        self.get_location_config('/a')
705
437
        self.assertEqual('something',
706
438
                         self.my_config.get_user_option('user_global_option'))
707
439
 
708
440
    def test_get_user_option_local(self):
709
 
        self.get_branch_config('/a')
 
441
        self.get_location_config('/a')
710
442
        self.assertEqual('local',
711
443
                         self.my_config.get_user_option('user_local_option'))
712
444
 
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
723
 
        # normal option:
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'))
727
 
 
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
737
 
        # this redefinition.
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'))
744
 
 
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)
749
 
        self.assertEqual(
750
 
            self.my_location_config._get_option_policy(
751
 
            'http://www.example.com', 'foo'),
752
 
            config.POLICY_NORECURSE)
753
 
 
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)
758
 
        self.assertEqual(
759
 
            self.my_location_config._get_option_policy(
760
 
            'http://www.example.com', 'foo'),
761
 
            config.POLICY_APPENDPATH)
762
 
 
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)
767
 
        self.assertEqual(
768
 
            self.my_location_config._get_option_policy(
769
 
            'http://www.example.com', 'norecurse_option'),
770
 
            config.POLICY_NONE)
771
 
 
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)
782
 
        self.assertEqual(
783
 
            self.my_location_config._get_option_policy(
784
 
            'http://www.example.com/norecurse', 'foo'),
785
 
            config.POLICY_NONE)
786
 
        # The previously existing option is still norecurse:
787
 
        self.assertEqual(
788
 
            self.my_location_config._get_option_policy(
789
 
            'http://www.example.com/norecurse', 'normal_option'),
790
 
            config.POLICY_NORECURSE)
791
 
        
792
 
 
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())
797
 
 
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'))
801
 
        else:
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)
810
 
 
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
815
 
 
816
 
        real_mkdir = os.mkdir
817
 
        self.created = False
818
 
        def checked_mkdir(path, mode=0777):
819
 
            self.log('making directory: %s', path)
820
 
            real_mkdir(path, mode)
821
 
            self.created = True
822
 
 
823
 
        os.mkdir = checked_mkdir
824
 
        try:
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)
830
 
        finally:
831
 
            os.mkdir = real_mkdir
832
 
 
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'),
844
 
                          ('keys',),
845
 
                          ('__getitem__', '/a/c'),
846
 
                          ('__contains__', 'foo:policy'),
847
 
                          ('write',)],
848
 
                         record._calls[1:])
849
 
 
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')
854
 
        self.assertEqual(
855
 
            self.my_config.branch.control_files.files['branch.conf'], 
856
 
            'foo = bar')
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')
863
 
        
864
 
 
865
 
precedence_global = 'option = global'
866
 
precedence_branch = 'option = branch'
867
 
precedence_location = """
868
 
[http://]
869
 
recurse = true
870
 
option = recurse
871
 
[http://example.com/specific]
872
 
option = exact
873
 
"""
874
 
 
875
 
 
876
 
class TestBranchConfigItems(TestCaseInTempDir):
877
 
 
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'] = \
890
 
                branch_data_config
891
 
        return my_config
 
445
 
 
446
class TestBranchConfigItems(TestCase):
892
447
 
893
448
    def test_user_id(self):
894
 
        branch = FakeBranch(user_id='Robert Collins <robertc@example.net>')
 
449
        branch = FakeBranch()
895
450
        my_config = config.BranchConfig(branch)
896
451
        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())
 
452
                         my_config._get_user_id())
 
453
        branch.email = "John"
 
454
        self.assertEqual("John", my_config._get_user_id())
905
455
 
906
456
    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>",
 
457
        branch = FakeBranch()
 
458
        my_config = config.BranchConfig(branch)
 
459
        branch.email = None
 
460
        config_file = StringIO(sample_config_text)
 
461
        (my_config._get_location_config().
 
462
            _get_global_config()._get_parser(config_file))
 
463
        self.assertEqual("Robert Collins <robertc@example.com>",
910
464
                         my_config._get_user_id())
911
 
        my_config.branch.control_files.email = "John"
 
465
        branch.email = "John"
912
466
        self.assertEqual("John", my_config._get_user_id())
913
467
 
914
 
    def test_BZR_EMAIL_OVERRIDES(self):
915
 
        os.environ['BZR_EMAIL'] = "Robert Collins <robertc@example.org>"
 
468
    def test_BZREMAIL_OVERRIDES(self):
 
469
        os.environ['BZREMAIL'] = "Robert Collins <robertc@example.org>"
916
470
        branch = FakeBranch()
917
471
        my_config = config.BranchConfig(branch)
918
472
        self.assertEqual("Robert Collins <robertc@example.org>",
919
473
                         my_config.username())
920
474
    
921
475
    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())
927
 
 
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())
 
476
        branch = FakeBranch()
 
477
        my_config = config.BranchConfig(branch)
 
478
        config_file = StringIO(sample_always_signatures)
 
479
        (my_config._get_location_config().
 
480
            _get_global_config()._get_parser(config_file))
 
481
        self.assertEqual(config.CHECK_ALWAYS, my_config.signature_checking())
935
482
 
936
483
    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)
 
484
        branch = FakeBranch()
 
485
        my_config = config.BranchConfig(branch)
 
486
        config_file = StringIO(sample_config_text)
 
487
        (my_config._get_location_config().
 
488
            _get_global_config()._get_parser(config_file))
942
489
        self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
943
490
 
944
491
    def test_get_user_option_global(self):
945
492
        branch = FakeBranch()
946
493
        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))
 
494
        config_file = StringIO(sample_config_text)
 
495
        (my_config._get_location_config().
 
496
            _get_global_config()._get_parser(config_file))
949
497
        self.assertEqual('something',
950
498
                         my_config.get_user_option('user_global_option'))
951
 
 
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())
966
 
 
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')
982
 
 
983
 
 
984
 
class TestMailAddressExtraction(TestCase):
985
 
 
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')