~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Vincent Ladeuil
  • Date: 2008-08-26 08:25:27 UTC
  • mto: (3668.1.1 trunk) (3703.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 3669.
  • Revision ID: v.ladeuil+lp@free.fr-20080826082527-109yyxzc0u24oeel
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.

* bzrlib/transform.py:
(TransformPreview.__init__): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/tests/test_whitebox.py:
(MoreTests.test_relpath): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/tests/test_setup.py:
(TestSetup.test_build_and_install): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/tests/test_bundle.py:
(BundleTester.get_checkout): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/tests/blackbox/test_outside_wt.py:
(TestOutsideWT.test_cwd_log,
TestOutsideWT.test_diff_outside_tree): Use osutils.mkdtemp instead
of tempfile.mkdtemp.

* bzrlib/smart/repository.py:
(SmartServerRepositoryTarball._copy_to_tempdir): Use
osutils.mkdtemp instead of tempfile.mkdtemp.
(SmartServerRepositoryTarball._tarfile_response): Line too long.

* bzrlib/remote.py:
(RemoteRepository._copy_repository_tarball): Use osutils.mkdtemp
instead of tempfile.mkdtemp.

* bzrlib/osutils.py:
(_mac_mkdtemp): Add docstring.

* bzrlib/mail_client.py:
(ExternalMailClient.compose): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

* bzrlib/diff.py:
(DiffFromTool.__init__): Use osutils.mkdtemp instead of
tempfile.mkdtemp.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 by Canonical Ltd
 
1
# Copyright (C) 2005, 2006 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
21
20
from cStringIO import StringIO
22
21
import os
23
22
import sys
24
23
 
25
24
#import bzrlib specific imports here
26
 
import bzrlib.config as config
27
 
from bzrlib.branch import Branch
28
 
from bzrlib.bzrdir import BzrDir
29
 
import bzrlib.errors as errors
30
 
from bzrlib.tests import TestCase, TestCaseInTempDir, TestCaseWithTransport
 
25
from bzrlib import (
 
26
    branch,
 
27
    bzrdir,
 
28
    config,
 
29
    errors,
 
30
    osutils,
 
31
    mail_client,
 
32
    ui,
 
33
    urlutils,
 
34
    tests,
 
35
    trace,
 
36
    transport,
 
37
    )
 
38
from bzrlib.util.configobj import configobj
31
39
 
32
40
 
33
41
sample_long_alias="log -r-15..-1 --line"
34
 
sample_config_text = ("[DEFAULT]\n"
35
 
                      u"email=Erik B\u00e5gfors <erik@bagfors.nu>\n"
36
 
                      "editor=vim\n"
37
 
                      "gpg_signing_command=gnome-gpg\n"
38
 
                      "log_format=short\n"
39
 
                      "user_global_option=something\n"
40
 
                      "[ALIASES]\n"
41
 
                      "h=help\n"
42
 
                      "ll=" + sample_long_alias + "\n")
43
 
 
44
 
 
45
 
sample_always_signatures = ("[DEFAULT]\n"
46
 
                            "check_signatures=ignore\n"
47
 
                            "create_signatures=always")
48
 
 
49
 
 
50
 
sample_ignore_signatures = ("[DEFAULT]\n"
51
 
                            "check_signatures=require\n"
52
 
                            "create_signatures=never")
53
 
 
54
 
 
55
 
sample_maybe_signatures = ("[DEFAULT]\n"
56
 
                            "check_signatures=ignore\n"
57
 
                            "create_signatures=when-required")
58
 
 
59
 
 
60
 
sample_branches_text = ("[http://www.example.com]\n"
61
 
                        "# Top level policy\n"
62
 
                        "email=Robert Collins <robertc@example.org>\n"
63
 
                        "[http://www.example.com/useglobal]\n"
64
 
                        "# different project, forces global lookup\n"
65
 
                        "recurse=false\n"
66
 
                        "[/b/]\n"
67
 
                        "check_signatures=require\n"
68
 
                        "# test trailing / matching with no children\n"
69
 
                        "[/a/]\n"
70
 
                        "check_signatures=check-available\n"
71
 
                        "gpg_signing_command=false\n"
72
 
                        "user_local_option=local\n"
73
 
                        "# test trailing / matching\n"
74
 
                        "[/a/*]\n"
75
 
                        "#subdirs will match but not the parent\n"
76
 
                        "recurse=False\n"
77
 
                        "[/a/c]\n"
78
 
                        "check_signatures=ignore\n"
79
 
                        "post_commit=bzrlib.tests.test_config.post_commit\n"
80
 
                        "#testing explicit beats globs\n")
81
 
 
 
42
sample_config_text = u"""
 
43
[DEFAULT]
 
44
email=Erik B\u00e5gfors <erik@bagfors.nu>
 
45
editor=vim
 
46
gpg_signing_command=gnome-gpg
 
47
log_format=short
 
48
user_global_option=something
 
49
[ALIASES]
 
50
h=help
 
51
ll=""" + sample_long_alias + "\n"
 
52
 
 
53
 
 
54
sample_always_signatures = """
 
55
[DEFAULT]
 
56
check_signatures=ignore
 
57
create_signatures=always
 
58
"""
 
59
 
 
60
sample_ignore_signatures = """
 
61
[DEFAULT]
 
62
check_signatures=require
 
63
create_signatures=never
 
64
"""
 
65
 
 
66
sample_maybe_signatures = """
 
67
[DEFAULT]
 
68
check_signatures=ignore
 
69
create_signatures=when-required
 
70
"""
 
71
 
 
72
sample_branches_text = """
 
73
[http://www.example.com]
 
74
# Top level policy
 
75
email=Robert Collins <robertc@example.org>
 
76
normal_option = normal
 
77
appendpath_option = append
 
78
appendpath_option:policy = appendpath
 
79
norecurse_option = norecurse
 
80
norecurse_option:policy = norecurse
 
81
[http://www.example.com/ignoreparent]
 
82
# different project: ignore parent dir config
 
83
ignore_parents=true
 
84
[http://www.example.com/norecurse]
 
85
# configuration items that only apply to this dir
 
86
recurse=false
 
87
normal_option = norecurse
 
88
[http://www.example.com/dir]
 
89
appendpath_option = normal
 
90
[/b/]
 
91
check_signatures=require
 
92
# test trailing / matching with no children
 
93
[/a/]
 
94
check_signatures=check-available
 
95
gpg_signing_command=false
 
96
user_local_option=local
 
97
# test trailing / matching
 
98
[/a/*]
 
99
#subdirs will match but not the parent
 
100
[/a/c]
 
101
check_signatures=ignore
 
102
post_commit=bzrlib.tests.test_config.post_commit
 
103
#testing explicit beats globs
 
104
"""
82
105
 
83
106
 
84
107
class InstrumentedConfigObj(object):
98
121
    def __setitem__(self, key, value):
99
122
        self._calls.append(('__setitem__', key, value))
100
123
 
 
124
    def __delitem__(self, key):
 
125
        self._calls.append(('__delitem__', key))
 
126
 
 
127
    def keys(self):
 
128
        self._calls.append(('keys',))
 
129
        return []
 
130
 
101
131
    def write(self, arg):
102
132
        self._calls.append(('write',))
103
133
 
 
134
    def as_bool(self, value):
 
135
        self._calls.append(('as_bool', value))
 
136
        return False
 
137
 
 
138
    def get_value(self, section, name):
 
139
        self._calls.append(('get_value', section, name))
 
140
        return None
 
141
 
104
142
 
105
143
class FakeBranch(object):
106
144
 
109
147
            self.base = "http://example.com/branches/demo"
110
148
        else:
111
149
            self.base = base
112
 
        self.control_files = FakeControlFiles(user_id=user_id)
 
150
        self._transport = self.control_files = \
 
151
            FakeControlFilesAndTransport(user_id=user_id)
113
152
 
114
153
    def lock_write(self):
115
154
        pass
118
157
        pass
119
158
 
120
159
 
121
 
class FakeControlFiles(object):
 
160
class FakeControlFilesAndTransport(object):
122
161
 
123
162
    def __init__(self, user_id=None):
124
 
        self.email = user_id
125
163
        self.files = {}
 
164
        if user_id:
 
165
            self.files['email'] = user_id
 
166
        self._transport = self
126
167
 
127
168
    def get_utf8(self, filename):
128
 
        if filename != 'email':
129
 
            raise NotImplementedError
130
 
        if self.email is not None:
131
 
            return StringIO(self.email)
132
 
        raise errors.NoSuchFile(filename)
 
169
        # from LockableFiles
 
170
        raise AssertionError("get_utf8 should no longer be used")
133
171
 
134
172
    def get(self, filename):
 
173
        # from Transport
135
174
        try:
136
175
            return StringIO(self.files[filename])
137
176
        except KeyError:
138
177
            raise errors.NoSuchFile(filename)
139
178
 
 
179
    def get_bytes(self, filename):
 
180
        # from Transport
 
181
        try:
 
182
            return self.files[filename]
 
183
        except KeyError:
 
184
            raise errors.NoSuchFile(filename)
 
185
 
140
186
    def put(self, filename, fileobj):
141
187
        self.files[filename] = fileobj.read()
142
188
 
 
189
    def put_file(self, filename, fileobj):
 
190
        return self.put(filename, fileobj)
 
191
 
143
192
 
144
193
class InstrumentedConfig(config.Config):
145
194
    """An instrumented config that supplies stubs for template methods."""
146
 
    
 
195
 
147
196
    def __init__(self):
148
197
        super(InstrumentedConfig, self).__init__()
149
198
        self._calls = []
165
214
active = True
166
215
nonactive = False
167
216
"""
168
 
class TestConfigObj(TestCase):
 
217
 
 
218
 
 
219
class TestConfigObj(tests.TestCase):
 
220
 
169
221
    def test_get_bool(self):
170
 
        from bzrlib.config import ConfigObj
171
 
        co = ConfigObj(StringIO(bool_config))
 
222
        co = config.ConfigObj(StringIO(bool_config))
172
223
        self.assertIs(co.get_bool('DEFAULT', 'active'), True)
173
224
        self.assertIs(co.get_bool('DEFAULT', 'inactive'), False)
174
225
        self.assertIs(co.get_bool('UPPERCASE', 'active'), True)
175
226
        self.assertIs(co.get_bool('UPPERCASE', 'nonactive'), False)
176
227
 
177
 
 
178
 
class TestConfig(TestCase):
 
228
    def test_hash_sign_in_value(self):
 
229
        """
 
230
        Before 4.5.0, ConfigObj did not quote # signs in values, so they'd be
 
231
        treated as comments when read in again. (#86838)
 
232
        """
 
233
        co = config.ConfigObj()
 
234
        co['test'] = 'foo#bar'
 
235
        lines = co.write()
 
236
        self.assertEqual(lines, ['test = "foo#bar"'])
 
237
        co2 = config.ConfigObj(lines)
 
238
        self.assertEqual(co2['test'], 'foo#bar')
 
239
 
 
240
 
 
241
erroneous_config = """[section] # line 1
 
242
good=good # line 2
 
243
[section] # line 3
 
244
whocares=notme # line 4
 
245
"""
 
246
 
 
247
 
 
248
class TestConfigObjErrors(tests.TestCase):
 
249
 
 
250
    def test_duplicate_section_name_error_line(self):
 
251
        try:
 
252
            co = configobj.ConfigObj(StringIO(erroneous_config),
 
253
                                     raise_errors=True)
 
254
        except config.configobj.DuplicateError, e:
 
255
            self.assertEqual(3, e.line_number)
 
256
        else:
 
257
            self.fail('Error in config file not detected')
 
258
 
 
259
 
 
260
class TestConfig(tests.TestCase):
179
261
 
180
262
    def test_constructs(self):
181
263
        config.Config()
182
 
 
 
264
 
183
265
    def test_no_default_editor(self):
184
266
        self.assertRaises(NotImplementedError, config.Config().get_editor)
185
267
 
231
313
        self.assertEqual('long', my_config.log_format())
232
314
 
233
315
 
234
 
class TestConfigPath(TestCase):
 
316
class TestConfigPath(tests.TestCase):
235
317
 
236
318
    def setUp(self):
237
319
        super(TestConfigPath, self).setUp()
238
 
        self.old_home = os.environ.get('HOME', None)
239
 
        self.old_appdata = os.environ.get('APPDATA', None)
240
320
        os.environ['HOME'] = '/home/bogus'
241
 
        os.environ['APPDATA'] = \
242
 
            r'C:\Documents and Settings\bogus\Application Data'
 
321
        if sys.platform == 'win32':
 
322
            os.environ['BZR_HOME'] = \
 
323
                r'C:\Documents and Settings\bogus\Application Data'
 
324
            self.bzr_home = \
 
325
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0'
 
326
        else:
 
327
            self.bzr_home = '/home/bogus/.bazaar'
243
328
 
244
 
    def tearDown(self):
245
 
        if self.old_home is None:
246
 
            del os.environ['HOME']
247
 
        else:
248
 
            os.environ['HOME'] = self.old_home
249
 
        if self.old_appdata is None:
250
 
            del os.environ['APPDATA']
251
 
        else:
252
 
            os.environ['APPDATA'] = self.old_appdata
253
 
        super(TestConfigPath, self).tearDown()
254
 
    
255
329
    def test_config_dir(self):
256
 
        if sys.platform == 'win32':
257
 
            self.assertEqual(config.config_dir(), 
258
 
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0')
259
 
        else:
260
 
            self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
 
330
        self.assertEqual(config.config_dir(), self.bzr_home)
261
331
 
262
332
    def test_config_filename(self):
263
 
        if sys.platform == 'win32':
264
 
            self.assertEqual(config.config_filename(), 
265
 
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/bazaar.conf')
266
 
        else:
267
 
            self.assertEqual(config.config_filename(),
268
 
                             '/home/bogus/.bazaar/bazaar.conf')
 
333
        self.assertEqual(config.config_filename(),
 
334
                         self.bzr_home + '/bazaar.conf')
269
335
 
270
336
    def test_branches_config_filename(self):
271
 
        if sys.platform == 'win32':
272
 
            self.assertEqual(config.branches_config_filename(), 
273
 
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/branches.conf')
274
 
        else:
275
 
            self.assertEqual(config.branches_config_filename(),
276
 
                             '/home/bogus/.bazaar/branches.conf')
 
337
        self.assertEqual(config.branches_config_filename(),
 
338
                         self.bzr_home + '/branches.conf')
277
339
 
278
340
    def test_locations_config_filename(self):
279
 
        if sys.platform == 'win32':
280
 
            self.assertEqual(config.locations_config_filename(), 
281
 
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/locations.conf')
282
 
        else:
283
 
            self.assertEqual(config.locations_config_filename(),
284
 
                             '/home/bogus/.bazaar/locations.conf')
285
 
 
286
 
class TestIniConfig(TestCase):
 
341
        self.assertEqual(config.locations_config_filename(),
 
342
                         self.bzr_home + '/locations.conf')
 
343
 
 
344
    def test_authentication_config_filename(self):
 
345
        self.assertEqual(config.authentication_config_filename(),
 
346
                         self.bzr_home + '/authentication.conf')
 
347
 
 
348
 
 
349
class TestIniConfig(tests.TestCase):
287
350
 
288
351
    def test_contructs(self):
289
352
        my_config = config.IniBasedConfig("nothing")
293
356
        my_config = config.IniBasedConfig(None)
294
357
        self.failUnless(
295
358
            isinstance(my_config._get_parser(file=config_file),
296
 
                        ConfigObj))
 
359
                        configobj.ConfigObj))
297
360
 
298
361
    def test_cached(self):
299
362
        config_file = StringIO(sample_config_text.encode('utf-8'))
302
365
        self.failUnless(my_config._get_parser() is parser)
303
366
 
304
367
 
305
 
class TestGetConfig(TestCase):
 
368
class TestGetConfig(tests.TestCase):
306
369
 
307
370
    def test_constructs(self):
308
371
        my_config = config.GlobalConfig()
309
372
 
310
373
    def test_calls_read_filenames(self):
311
 
        # replace the class that is constructured, to check its parameters
 
374
        # replace the class that is constructed, to check its parameters
312
375
        oldparserclass = config.ConfigObj
313
376
        config.ConfigObj = InstrumentedConfigObj
314
377
        my_config = config.GlobalConfig()
321
384
                                          'utf-8')])
322
385
 
323
386
 
324
 
class TestBranchConfig(TestCaseWithTransport):
 
387
class TestBranchConfig(tests.TestCaseWithTransport):
325
388
 
326
389
    def test_constructs(self):
327
390
        branch = FakeBranch()
337
400
 
338
401
    def test_get_config(self):
339
402
        """The Branch.get_config method works properly"""
340
 
        b = BzrDir.create_standalone_workingtree('.').branch
 
403
        b = bzrdir.BzrDir.create_standalone_workingtree('.').branch
341
404
        my_config = b.get_config()
342
405
        self.assertIs(my_config.get_user_option('wacky'), None)
343
406
        my_config.set_user_option('wacky', 'unlikely')
344
407
        self.assertEqual(my_config.get_user_option('wacky'), 'unlikely')
345
408
 
346
409
        # Ensure we get the same thing if we start again
347
 
        b2 = Branch.open('.')
 
410
        b2 = branch.Branch.open('.')
348
411
        my_config2 = b2.get_config()
349
412
        self.assertEqual(my_config2.get_user_option('wacky'), 'unlikely')
350
413
 
354
417
        b.nick = 'foo'
355
418
        self.assertTrue(b.get_config().has_explicit_nickname())
356
419
 
357
 
 
358
 
class TestGlobalConfigItems(TestCase):
 
420
    def test_config_url(self):
 
421
        """The Branch.get_config will use section that uses a local url"""
 
422
        branch = self.make_branch('branch')
 
423
        self.assertEqual('branch', branch.nick)
 
424
 
 
425
        locations = config.locations_config_filename()
 
426
        config.ensure_config_dir_exists()
 
427
        local_url = urlutils.local_path_to_url('branch')
 
428
        open(locations, 'wb').write('[%s]\nnickname = foobar' 
 
429
                                    % (local_url,))
 
430
        self.assertEqual('foobar', branch.nick)
 
431
 
 
432
    def test_config_local_path(self):
 
433
        """The Branch.get_config will use a local system path"""
 
434
        branch = self.make_branch('branch')
 
435
        self.assertEqual('branch', branch.nick)
 
436
 
 
437
        locations = config.locations_config_filename()
 
438
        config.ensure_config_dir_exists()
 
439
        open(locations, 'wb').write('[%s/branch]\nnickname = barry' 
 
440
                                    % (osutils.getcwd().encode('utf8'),))
 
441
        self.assertEqual('barry', branch.nick)
 
442
 
 
443
    def test_config_creates_local(self):
 
444
        """Creating a new entry in config uses a local path."""
 
445
        branch = self.make_branch('branch', format='knit')
 
446
        branch.set_push_location('http://foobar')
 
447
        locations = config.locations_config_filename()
 
448
        local_path = osutils.getcwd().encode('utf8')
 
449
        # Surprisingly ConfigObj doesn't create a trailing newline
 
450
        self.check_file_contents(locations,
 
451
                                 '[%s/branch]\n'
 
452
                                 'push_location = http://foobar\n'
 
453
                                 'push_location:policy = norecurse\n'
 
454
                                 % (local_path,))
 
455
 
 
456
    def test_autonick_urlencoded(self):
 
457
        b = self.make_branch('!repo')
 
458
        self.assertEqual('!repo', b.get_config().get_nickname())
 
459
 
 
460
    def test_warn_if_masked(self):
 
461
        _warning = trace.warning
 
462
        warnings = []
 
463
        def warning(*args):
 
464
            warnings.append(args[0] % args[1:])
 
465
 
 
466
        def set_option(store, warn_masked=True):
 
467
            warnings[:] = []
 
468
            conf.set_user_option('example_option', repr(store), store=store,
 
469
                                 warn_masked=warn_masked)
 
470
        def assertWarning(warning):
 
471
            if warning is None:
 
472
                self.assertEqual(0, len(warnings))
 
473
            else:
 
474
                self.assertEqual(1, len(warnings))
 
475
                self.assertEqual(warning, warnings[0])
 
476
        trace.warning = warning
 
477
        try:
 
478
            branch = self.make_branch('.')
 
479
            conf = branch.get_config()
 
480
            set_option(config.STORE_GLOBAL)
 
481
            assertWarning(None)
 
482
            set_option(config.STORE_BRANCH)
 
483
            assertWarning(None)
 
484
            set_option(config.STORE_GLOBAL)
 
485
            assertWarning('Value "4" is masked by "3" from branch.conf')
 
486
            set_option(config.STORE_GLOBAL, warn_masked=False)
 
487
            assertWarning(None)
 
488
            set_option(config.STORE_LOCATION)
 
489
            assertWarning(None)
 
490
            set_option(config.STORE_BRANCH)
 
491
            assertWarning('Value "3" is masked by "0" from locations.conf')
 
492
            set_option(config.STORE_BRANCH, warn_masked=False)
 
493
            assertWarning(None)
 
494
        finally:
 
495
            trace.warning = _warning
 
496
 
 
497
 
 
498
class TestGlobalConfigItems(tests.TestCase):
359
499
 
360
500
    def test_user_id(self):
361
501
        config_file = StringIO(sample_config_text.encode('utf-8'))
435
575
        my_config = self._get_sample_config()
436
576
        self.assertEqual("something",
437
577
                         my_config.get_user_option('user_global_option'))
438
 
        
 
578
 
439
579
    def test_post_commit_default(self):
440
580
        my_config = self._get_sample_config()
441
581
        self.assertEqual(None, my_config.post_commit())
448
588
        my_config = self._get_sample_config()
449
589
        self.assertEqual('help', my_config.get_alias('h'))
450
590
 
 
591
    def test_get_aliases(self):
 
592
        my_config = self._get_sample_config()
 
593
        aliases = my_config.get_aliases()
 
594
        self.assertEqual(2, len(aliases))
 
595
        sorted_keys = sorted(aliases)
 
596
        self.assertEqual('help', aliases[sorted_keys[0]])
 
597
        self.assertEqual(sample_long_alias, aliases[sorted_keys[1]])
 
598
 
451
599
    def test_get_no_alias(self):
452
600
        my_config = self._get_sample_config()
453
601
        self.assertEqual(None, my_config.get_alias('foo'))
457
605
        self.assertEqual(sample_long_alias, my_config.get_alias('ll'))
458
606
 
459
607
 
460
 
class TestLocationConfig(TestCaseInTempDir):
 
608
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
 
609
 
 
610
    def test_empty(self):
 
611
        my_config = config.GlobalConfig()
 
612
        self.assertEqual(0, len(my_config.get_aliases()))
 
613
 
 
614
    def test_set_alias(self):
 
615
        my_config = config.GlobalConfig()
 
616
        alias_value = 'commit --strict'
 
617
        my_config.set_alias('commit', alias_value)
 
618
        new_config = config.GlobalConfig()
 
619
        self.assertEqual(alias_value, new_config.get_alias('commit'))
 
620
 
 
621
    def test_remove_alias(self):
 
622
        my_config = config.GlobalConfig()
 
623
        my_config.set_alias('commit', 'commit --strict')
 
624
        # Now remove the alias again.
 
625
        my_config.unset_alias('commit')
 
626
        new_config = config.GlobalConfig()
 
627
        self.assertIs(None, new_config.get_alias('commit'))
 
628
 
 
629
 
 
630
class TestLocationConfig(tests.TestCaseInTempDir):
461
631
 
462
632
    def test_constructs(self):
463
633
        my_config = config.LocationConfig('http://example.com')
467
637
        # This is testing the correct file names are provided.
468
638
        # TODO: consolidate with the test for GlobalConfigs filename checks.
469
639
        #
470
 
        # replace the class that is constructured, to check its parameters
 
640
        # replace the class that is constructed, to check its parameters
471
641
        oldparserclass = config.ConfigObj
472
642
        config.ConfigObj = InstrumentedConfigObj
473
643
        try:
498
668
        self.failUnless(isinstance(global_config, config.GlobalConfig))
499
669
        self.failUnless(global_config is my_config._get_global_config())
500
670
 
501
 
    def test__get_section_no_match(self):
 
671
    def test__get_matching_sections_no_match(self):
502
672
        self.get_branch_config('/')
503
 
        self.assertEqual(None, self.my_location_config._get_section())
504
 
        
505
 
    def test__get_section_exact(self):
 
673
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
674
 
 
675
    def test__get_matching_sections_exact(self):
506
676
        self.get_branch_config('http://www.example.com')
507
 
        self.assertEqual('http://www.example.com',
508
 
                         self.my_location_config._get_section())
509
 
   
510
 
    def test__get_section_suffix_does_not(self):
 
677
        self.assertEqual([('http://www.example.com', '')],
 
678
                         self.my_location_config._get_matching_sections())
 
679
 
 
680
    def test__get_matching_sections_suffix_does_not(self):
511
681
        self.get_branch_config('http://www.example.com-com')
512
 
        self.assertEqual(None, self.my_location_config._get_section())
 
682
        self.assertEqual([], self.my_location_config._get_matching_sections())
513
683
 
514
 
    def test__get_section_subdir_recursive(self):
 
684
    def test__get_matching_sections_subdir_recursive(self):
515
685
        self.get_branch_config('http://www.example.com/com')
516
 
        self.assertEqual('http://www.example.com',
517
 
                         self.my_location_config._get_section())
518
 
 
519
 
    def test__get_section_subdir_matches(self):
520
 
        self.get_branch_config('http://www.example.com/useglobal')
521
 
        self.assertEqual('http://www.example.com/useglobal',
522
 
                         self.my_location_config._get_section())
523
 
 
524
 
    def test__get_section_subdir_nonrecursive(self):
 
686
        self.assertEqual([('http://www.example.com', 'com')],
 
687
                         self.my_location_config._get_matching_sections())
 
688
 
 
689
    def test__get_matching_sections_ignoreparent(self):
 
690
        self.get_branch_config('http://www.example.com/ignoreparent')
 
691
        self.assertEqual([('http://www.example.com/ignoreparent', '')],
 
692
                         self.my_location_config._get_matching_sections())
 
693
 
 
694
    def test__get_matching_sections_ignoreparent_subdir(self):
525
695
        self.get_branch_config(
526
 
            'http://www.example.com/useglobal/childbranch')
527
 
        self.assertEqual('http://www.example.com',
528
 
                         self.my_location_config._get_section())
 
696
            'http://www.example.com/ignoreparent/childbranch')
 
697
        self.assertEqual([('http://www.example.com/ignoreparent',
 
698
                           'childbranch')],
 
699
                         self.my_location_config._get_matching_sections())
529
700
 
530
 
    def test__get_section_subdir_trailing_slash(self):
 
701
    def test__get_matching_sections_subdir_trailing_slash(self):
531
702
        self.get_branch_config('/b')
532
 
        self.assertEqual('/b/', self.my_location_config._get_section())
 
703
        self.assertEqual([('/b/', '')],
 
704
                         self.my_location_config._get_matching_sections())
533
705
 
534
 
    def test__get_section_subdir_child(self):
 
706
    def test__get_matching_sections_subdir_child(self):
535
707
        self.get_branch_config('/a/foo')
536
 
        self.assertEqual('/a/*', self.my_location_config._get_section())
 
708
        self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
 
709
                         self.my_location_config._get_matching_sections())
537
710
 
538
 
    def test__get_section_subdir_child_child(self):
 
711
    def test__get_matching_sections_subdir_child_child(self):
539
712
        self.get_branch_config('/a/foo/bar')
540
 
        self.assertEqual('/a/', self.my_location_config._get_section())
 
713
        self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
 
714
                         self.my_location_config._get_matching_sections())
541
715
 
542
 
    def test__get_section_trailing_slash_with_children(self):
 
716
    def test__get_matching_sections_trailing_slash_with_children(self):
543
717
        self.get_branch_config('/a/')
544
 
        self.assertEqual('/a/', self.my_location_config._get_section())
 
718
        self.assertEqual([('/a/', '')],
 
719
                         self.my_location_config._get_matching_sections())
545
720
 
546
 
    def test__get_section_explicit_over_glob(self):
 
721
    def test__get_matching_sections_explicit_over_glob(self):
 
722
        # XXX: 2006-09-08 jamesh
 
723
        # This test only passes because ord('c') > ord('*').  If there
 
724
        # was a config section for '/a/?', it would get precedence
 
725
        # over '/a/c'.
547
726
        self.get_branch_config('/a/c')
548
 
        self.assertEqual('/a/c', self.my_location_config._get_section())
549
 
 
 
727
        self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
 
728
                         self.my_location_config._get_matching_sections())
 
729
 
 
730
    def test__get_option_policy_normal(self):
 
731
        self.get_branch_config('http://www.example.com')
 
732
        self.assertEqual(
 
733
            self.my_location_config._get_config_policy(
 
734
            'http://www.example.com', 'normal_option'),
 
735
            config.POLICY_NONE)
 
736
 
 
737
    def test__get_option_policy_norecurse(self):
 
738
        self.get_branch_config('http://www.example.com')
 
739
        self.assertEqual(
 
740
            self.my_location_config._get_option_policy(
 
741
            'http://www.example.com', 'norecurse_option'),
 
742
            config.POLICY_NORECURSE)
 
743
        # Test old recurse=False setting:
 
744
        self.assertEqual(
 
745
            self.my_location_config._get_option_policy(
 
746
            'http://www.example.com/norecurse', 'normal_option'),
 
747
            config.POLICY_NORECURSE)
 
748
 
 
749
    def test__get_option_policy_normal(self):
 
750
        self.get_branch_config('http://www.example.com')
 
751
        self.assertEqual(
 
752
            self.my_location_config._get_option_policy(
 
753
            'http://www.example.com', 'appendpath_option'),
 
754
            config.POLICY_APPENDPATH)
550
755
 
551
756
    def test_location_without_username(self):
552
 
        self.get_branch_config('http://www.example.com/useglobal')
 
757
        self.get_branch_config('http://www.example.com/ignoreparent')
553
758
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
554
759
                         self.my_config.username())
555
760
 
576
781
        self.get_branch_config('/a/c')
577
782
        self.assertEqual(config.CHECK_NEVER,
578
783
                         self.my_config.signature_checking())
579
 
        
 
784
 
580
785
    def test_signatures_when_available(self):
581
786
        self.get_branch_config('/a/', global_config=sample_ignore_signatures)
582
787
        self.assertEqual(config.CHECK_IF_POSSIBLE,
583
788
                         self.my_config.signature_checking())
584
 
        
 
789
 
585
790
    def test_signatures_always(self):
586
791
        self.get_branch_config('/b')
587
792
        self.assertEqual(config.CHECK_ALWAYS,
588
793
                         self.my_config.signature_checking())
589
 
        
 
794
 
590
795
    def test_gpg_signing_command(self):
591
796
        self.get_branch_config('/b')
592
797
        self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
604
809
        self.get_branch_config('/a')
605
810
        self.assertEqual('local',
606
811
                         self.my_config.get_user_option('user_local_option'))
607
 
        
 
812
 
 
813
    def test_get_user_option_appendpath(self):
 
814
        # returned as is for the base path:
 
815
        self.get_branch_config('http://www.example.com')
 
816
        self.assertEqual('append',
 
817
                         self.my_config.get_user_option('appendpath_option'))
 
818
        # Extra path components get appended:
 
819
        self.get_branch_config('http://www.example.com/a/b/c')
 
820
        self.assertEqual('append/a/b/c',
 
821
                         self.my_config.get_user_option('appendpath_option'))
 
822
        # Overriden for http://www.example.com/dir, where it is a
 
823
        # normal option:
 
824
        self.get_branch_config('http://www.example.com/dir/a/b/c')
 
825
        self.assertEqual('normal',
 
826
                         self.my_config.get_user_option('appendpath_option'))
 
827
 
 
828
    def test_get_user_option_norecurse(self):
 
829
        self.get_branch_config('http://www.example.com')
 
830
        self.assertEqual('norecurse',
 
831
                         self.my_config.get_user_option('norecurse_option'))
 
832
        self.get_branch_config('http://www.example.com/dir')
 
833
        self.assertEqual(None,
 
834
                         self.my_config.get_user_option('norecurse_option'))
 
835
        # http://www.example.com/norecurse is a recurse=False section
 
836
        # that redefines normal_option.  Subdirectories do not pick up
 
837
        # this redefinition.
 
838
        self.get_branch_config('http://www.example.com/norecurse')
 
839
        self.assertEqual('norecurse',
 
840
                         self.my_config.get_user_option('normal_option'))
 
841
        self.get_branch_config('http://www.example.com/norecurse/subdir')
 
842
        self.assertEqual('normal',
 
843
                         self.my_config.get_user_option('normal_option'))
 
844
 
 
845
    def test_set_user_option_norecurse(self):
 
846
        self.get_branch_config('http://www.example.com')
 
847
        self.my_config.set_user_option('foo', 'bar',
 
848
                                       store=config.STORE_LOCATION_NORECURSE)
 
849
        self.assertEqual(
 
850
            self.my_location_config._get_option_policy(
 
851
            'http://www.example.com', 'foo'),
 
852
            config.POLICY_NORECURSE)
 
853
 
 
854
    def test_set_user_option_appendpath(self):
 
855
        self.get_branch_config('http://www.example.com')
 
856
        self.my_config.set_user_option('foo', 'bar',
 
857
                                       store=config.STORE_LOCATION_APPENDPATH)
 
858
        self.assertEqual(
 
859
            self.my_location_config._get_option_policy(
 
860
            'http://www.example.com', 'foo'),
 
861
            config.POLICY_APPENDPATH)
 
862
 
 
863
    def test_set_user_option_change_policy(self):
 
864
        self.get_branch_config('http://www.example.com')
 
865
        self.my_config.set_user_option('norecurse_option', 'normal',
 
866
                                       store=config.STORE_LOCATION)
 
867
        self.assertEqual(
 
868
            self.my_location_config._get_option_policy(
 
869
            'http://www.example.com', 'norecurse_option'),
 
870
            config.POLICY_NONE)
 
871
 
 
872
    def test_set_user_option_recurse_false_section(self):
 
873
        # The following section has recurse=False set.  The test is to
 
874
        # make sure that a normal option can be added to the section,
 
875
        # converting recurse=False to the norecurse policy.
 
876
        self.get_branch_config('http://www.example.com/norecurse')
 
877
        self.callDeprecated(['The recurse option is deprecated as of 0.14.  '
 
878
                             'The section "http://www.example.com/norecurse" '
 
879
                             'has been converted to use policies.'],
 
880
                            self.my_config.set_user_option,
 
881
                            'foo', 'bar', store=config.STORE_LOCATION)
 
882
        self.assertEqual(
 
883
            self.my_location_config._get_option_policy(
 
884
            'http://www.example.com/norecurse', 'foo'),
 
885
            config.POLICY_NONE)
 
886
        # The previously existing option is still norecurse:
 
887
        self.assertEqual(
 
888
            self.my_location_config._get_option_policy(
 
889
            'http://www.example.com/norecurse', 'normal_option'),
 
890
            config.POLICY_NORECURSE)
 
891
 
608
892
    def test_post_commit_default(self):
609
893
        self.get_branch_config('/a/c')
610
894
        self.assertEqual('bzrlib.tests.test_config.post_commit',
637
921
 
638
922
        os.mkdir = checked_mkdir
639
923
        try:
640
 
            self.my_config.set_user_option('foo', 'bar', local=True)
 
924
            self.callDeprecated(['The recurse option is deprecated as of '
 
925
                                 '0.14.  The section "/a/c" has been '
 
926
                                 'converted to use policies.'],
 
927
                                self.my_config.set_user_option,
 
928
                                'foo', 'bar', store=config.STORE_LOCATION)
641
929
        finally:
642
930
            os.mkdir = real_mkdir
643
931
 
647
935
                          ('__setitem__', '/a/c', {}),
648
936
                          ('__getitem__', '/a/c'),
649
937
                          ('__setitem__', 'foo', 'bar'),
 
938
                          ('__getitem__', '/a/c'),
 
939
                          ('as_bool', 'recurse'),
 
940
                          ('__getitem__', '/a/c'),
 
941
                          ('__delitem__', 'recurse'),
 
942
                          ('__getitem__', '/a/c'),
 
943
                          ('keys',),
 
944
                          ('__getitem__', '/a/c'),
 
945
                          ('__contains__', 'foo:policy'),
650
946
                          ('write',)],
651
947
                         record._calls[1:])
652
948
 
655
951
        self.assertIs(self.my_config.get_user_option('foo'), None)
656
952
        self.my_config.set_user_option('foo', 'bar')
657
953
        self.assertEqual(
658
 
            self.my_config.branch.control_files.files['branch.conf'], 
 
954
            self.my_config.branch.control_files.files['branch.conf'].strip(),
659
955
            'foo = bar')
660
956
        self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
661
 
        self.my_config.set_user_option('foo', 'baz', local=True)
 
957
        self.my_config.set_user_option('foo', 'baz',
 
958
                                       store=config.STORE_LOCATION)
662
959
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
663
960
        self.my_config.set_user_option('foo', 'qux')
664
961
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
665
 
        
 
962
 
 
963
    def test_get_bzr_remote_path(self):
 
964
        my_config = config.LocationConfig('/a/c')
 
965
        self.assertEqual('bzr', my_config.get_bzr_remote_path())
 
966
        my_config.set_user_option('bzr_remote_path', '/path-bzr')
 
967
        self.assertEqual('/path-bzr', my_config.get_bzr_remote_path())
 
968
        os.environ['BZR_REMOTE_PATH'] = '/environ-bzr'
 
969
        self.assertEqual('/environ-bzr', my_config.get_bzr_remote_path())
 
970
 
666
971
 
667
972
precedence_global = 'option = global'
668
973
precedence_branch = 'option = branch'
675
980
"""
676
981
 
677
982
 
678
 
class TestBranchConfigItems(TestCaseInTempDir):
 
983
class TestBranchConfigItems(tests.TestCaseInTempDir):
679
984
 
680
 
    def get_branch_config(self, global_config=None, location=None, 
 
985
    def get_branch_config(self, global_config=None, location=None,
681
986
                          location_config=None, branch_data_config=None):
682
987
        my_config = config.BranchConfig(FakeBranch(location))
683
988
        if global_config is not None:
697
1002
        my_config = config.BranchConfig(branch)
698
1003
        self.assertEqual("Robert Collins <robertc@example.net>",
699
1004
                         my_config.username())
700
 
        branch.control_files.email = "John"
701
 
        my_config.set_user_option('email', 
 
1005
        my_config.branch.control_files.files['email'] = "John"
 
1006
        my_config.set_user_option('email',
702
1007
                                  "Robert Collins <robertc@example.org>")
703
1008
        self.assertEqual("John", my_config.username())
704
 
        branch.control_files.email = None
 
1009
        del my_config.branch.control_files.files['email']
705
1010
        self.assertEqual("Robert Collins <robertc@example.org>",
706
1011
                         my_config.username())
707
1012
 
708
1013
    def test_not_set_in_branch(self):
709
1014
        my_config = self.get_branch_config(sample_config_text)
710
 
        my_config.branch.control_files.email = None
711
1015
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
712
1016
                         my_config._get_user_id())
713
 
        my_config.branch.control_files.email = "John"
 
1017
        my_config.branch.control_files.files['email'] = "John"
714
1018
        self.assertEqual("John", my_config._get_user_id())
715
1019
 
716
 
    def test_BZREMAIL_OVERRIDES(self):
717
 
        os.environ['BZREMAIL'] = "Robert Collins <robertc@example.org>"
 
1020
    def test_BZR_EMAIL_OVERRIDES(self):
 
1021
        os.environ['BZR_EMAIL'] = "Robert Collins <robertc@example.org>"
718
1022
        branch = FakeBranch()
719
1023
        my_config = config.BranchConfig(branch)
720
1024
        self.assertEqual("Robert Collins <robertc@example.org>",
721
1025
                         my_config.username())
722
 
    
 
1026
 
723
1027
    def test_signatures_forced(self):
724
1028
        my_config = self.get_branch_config(
725
1029
            global_config=sample_always_signatures)
762
1066
        # post-commit is ignored when bresent in branch data
763
1067
        self.assertEqual('bzrlib.tests.test_config.post_commit',
764
1068
                         my_config.post_commit())
765
 
        my_config.set_user_option('post_commit', 'rmtree_root', local=True)
 
1069
        my_config.set_user_option('post_commit', 'rmtree_root',
 
1070
                                  store=config.STORE_LOCATION)
766
1071
        self.assertEqual('rmtree_root', my_config.post_commit())
767
1072
 
768
1073
    def test_config_precedence(self):
769
1074
        my_config = self.get_branch_config(global_config=precedence_global)
770
1075
        self.assertEqual(my_config.get_user_option('option'), 'global')
771
 
        my_config = self.get_branch_config(global_config=precedence_global, 
 
1076
        my_config = self.get_branch_config(global_config=precedence_global,
772
1077
                                      branch_data_config=precedence_branch)
773
1078
        self.assertEqual(my_config.get_user_option('option'), 'branch')
774
 
        my_config = self.get_branch_config(global_config=precedence_global, 
 
1079
        my_config = self.get_branch_config(global_config=precedence_global,
775
1080
                                      branch_data_config=precedence_branch,
776
1081
                                      location_config=precedence_location)
777
1082
        self.assertEqual(my_config.get_user_option('option'), 'recurse')
778
 
        my_config = self.get_branch_config(global_config=precedence_global, 
 
1083
        my_config = self.get_branch_config(global_config=precedence_global,
779
1084
                                      branch_data_config=precedence_branch,
780
1085
                                      location_config=precedence_location,
781
1086
                                      location='http://example.com/specific')
782
1087
        self.assertEqual(my_config.get_user_option('option'), 'exact')
783
1088
 
784
 
 
785
 
class TestMailAddressExtraction(TestCase):
 
1089
    def test_get_mail_client(self):
 
1090
        config = self.get_branch_config()
 
1091
        client = config.get_mail_client()
 
1092
        self.assertIsInstance(client, mail_client.DefaultMail)
 
1093
 
 
1094
        # Specific clients
 
1095
        config.set_user_option('mail_client', 'evolution')
 
1096
        client = config.get_mail_client()
 
1097
        self.assertIsInstance(client, mail_client.Evolution)
 
1098
 
 
1099
        config.set_user_option('mail_client', 'kmail')
 
1100
        client = config.get_mail_client()
 
1101
        self.assertIsInstance(client, mail_client.KMail)
 
1102
 
 
1103
        config.set_user_option('mail_client', 'mutt')
 
1104
        client = config.get_mail_client()
 
1105
        self.assertIsInstance(client, mail_client.Mutt)
 
1106
 
 
1107
        config.set_user_option('mail_client', 'thunderbird')
 
1108
        client = config.get_mail_client()
 
1109
        self.assertIsInstance(client, mail_client.Thunderbird)
 
1110
 
 
1111
        # Generic options
 
1112
        config.set_user_option('mail_client', 'default')
 
1113
        client = config.get_mail_client()
 
1114
        self.assertIsInstance(client, mail_client.DefaultMail)
 
1115
 
 
1116
        config.set_user_option('mail_client', 'editor')
 
1117
        client = config.get_mail_client()
 
1118
        self.assertIsInstance(client, mail_client.Editor)
 
1119
 
 
1120
        config.set_user_option('mail_client', 'mapi')
 
1121
        client = config.get_mail_client()
 
1122
        self.assertIsInstance(client, mail_client.MAPIClient)
 
1123
 
 
1124
        config.set_user_option('mail_client', 'xdg-email')
 
1125
        client = config.get_mail_client()
 
1126
        self.assertIsInstance(client, mail_client.XDGEmail)
 
1127
 
 
1128
        config.set_user_option('mail_client', 'firebird')
 
1129
        self.assertRaises(errors.UnknownMailClient, config.get_mail_client)
 
1130
 
 
1131
 
 
1132
class TestMailAddressExtraction(tests.TestCase):
786
1133
 
787
1134
    def test_extract_email_address(self):
788
1135
        self.assertEqual('jane@test.com',
789
1136
                         config.extract_email_address('Jane <jane@test.com>'))
790
 
        self.assertRaises(errors.BzrError,
 
1137
        self.assertRaises(errors.NoEmailInUsername,
791
1138
                          config.extract_email_address, 'Jane Tester')
 
1139
 
 
1140
    def test_parse_username(self):
 
1141
        self.assertEqual(('', 'jdoe@example.com'),
 
1142
                         config.parse_username('jdoe@example.com'))
 
1143
        self.assertEqual(('', 'jdoe@example.com'),
 
1144
                         config.parse_username('<jdoe@example.com>'))
 
1145
        self.assertEqual(('John Doe', 'jdoe@example.com'),
 
1146
                         config.parse_username('John Doe <jdoe@example.com>'))
 
1147
        self.assertEqual(('John Doe', ''),
 
1148
                         config.parse_username('John Doe'))
 
1149
        self.assertEqual(('John Doe', 'jdoe@example.com'),
 
1150
                         config.parse_username('John Doe jdoe@example.com'))
 
1151
 
 
1152
class TestTreeConfig(tests.TestCaseWithTransport):
 
1153
 
 
1154
    def test_get_value(self):
 
1155
        """Test that retreiving a value from a section is possible"""
 
1156
        branch = self.make_branch('.')
 
1157
        tree_config = config.TreeConfig(branch)
 
1158
        tree_config.set_option('value', 'key', 'SECTION')
 
1159
        tree_config.set_option('value2', 'key2')
 
1160
        tree_config.set_option('value3-top', 'key3')
 
1161
        tree_config.set_option('value3-section', 'key3', 'SECTION')
 
1162
        value = tree_config.get_option('key', 'SECTION')
 
1163
        self.assertEqual(value, 'value')
 
1164
        value = tree_config.get_option('key2')
 
1165
        self.assertEqual(value, 'value2')
 
1166
        self.assertEqual(tree_config.get_option('non-existant'), None)
 
1167
        value = tree_config.get_option('non-existant', 'SECTION')
 
1168
        self.assertEqual(value, None)
 
1169
        value = tree_config.get_option('non-existant', default='default')
 
1170
        self.assertEqual(value, 'default')
 
1171
        self.assertEqual(tree_config.get_option('key2', 'NOSECTION'), None)
 
1172
        value = tree_config.get_option('key2', 'NOSECTION', default='default')
 
1173
        self.assertEqual(value, 'default')
 
1174
        value = tree_config.get_option('key3')
 
1175
        self.assertEqual(value, 'value3-top')
 
1176
        value = tree_config.get_option('key3', 'SECTION')
 
1177
        self.assertEqual(value, 'value3-section')
 
1178
 
 
1179
 
 
1180
class TestTransportConfig(tests.TestCaseWithTransport):
 
1181
 
 
1182
    def test_get_value(self):
 
1183
        """Test that retreiving a value from a section is possible"""
 
1184
        bzrdir_config = config.TransportConfig(transport.get_transport('.'),
 
1185
                                               'control.conf')
 
1186
        bzrdir_config.set_option('value', 'key', 'SECTION')
 
1187
        bzrdir_config.set_option('value2', 'key2')
 
1188
        bzrdir_config.set_option('value3-top', 'key3')
 
1189
        bzrdir_config.set_option('value3-section', 'key3', 'SECTION')
 
1190
        value = bzrdir_config.get_option('key', 'SECTION')
 
1191
        self.assertEqual(value, 'value')
 
1192
        value = bzrdir_config.get_option('key2')
 
1193
        self.assertEqual(value, 'value2')
 
1194
        self.assertEqual(bzrdir_config.get_option('non-existant'), None)
 
1195
        value = bzrdir_config.get_option('non-existant', 'SECTION')
 
1196
        self.assertEqual(value, None)
 
1197
        value = bzrdir_config.get_option('non-existant', default='default')
 
1198
        self.assertEqual(value, 'default')
 
1199
        self.assertEqual(bzrdir_config.get_option('key2', 'NOSECTION'), None)
 
1200
        value = bzrdir_config.get_option('key2', 'NOSECTION',
 
1201
                                         default='default')
 
1202
        self.assertEqual(value, 'default')
 
1203
        value = bzrdir_config.get_option('key3')
 
1204
        self.assertEqual(value, 'value3-top')
 
1205
        value = bzrdir_config.get_option('key3', 'SECTION')
 
1206
        self.assertEqual(value, 'value3-section')
 
1207
 
 
1208
    def test_set_unset_default_stack_on(self):
 
1209
        my_dir = self.make_bzrdir('.')
 
1210
        bzrdir_config = config.BzrDirConfig(my_dir.transport)
 
1211
        self.assertIs(None, bzrdir_config.get_default_stack_on())
 
1212
        bzrdir_config.set_default_stack_on('Foo')
 
1213
        self.assertEqual('Foo', bzrdir_config._config.get_option(
 
1214
                         'default_stack_on'))
 
1215
        self.assertEqual('Foo', bzrdir_config.get_default_stack_on())
 
1216
        bzrdir_config.set_default_stack_on(None)
 
1217
        self.assertIs(None, bzrdir_config.get_default_stack_on())
 
1218
 
 
1219
 
 
1220
class TestAuthenticationConfigFile(tests.TestCase):
 
1221
    """Test the authentication.conf file matching"""
 
1222
 
 
1223
    def _got_user_passwd(self, expected_user, expected_password,
 
1224
                         config, *args, **kwargs):
 
1225
        credentials = config.get_credentials(*args, **kwargs)
 
1226
        if credentials is None:
 
1227
            user = None
 
1228
            password = None
 
1229
        else:
 
1230
            user = credentials['user']
 
1231
            password = credentials['password']
 
1232
        self.assertEquals(expected_user, user)
 
1233
        self.assertEquals(expected_password, password)
 
1234
 
 
1235
    def test_empty_config(self):
 
1236
        conf = config.AuthenticationConfig(_file=StringIO())
 
1237
        self.assertEquals({}, conf._get_config())
 
1238
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
 
1239
 
 
1240
    def test_missing_auth_section_header(self):
 
1241
        conf = config.AuthenticationConfig(_file=StringIO('foo = bar'))
 
1242
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
 
1243
 
 
1244
    def test_auth_section_header_not_closed(self):
 
1245
        conf = config.AuthenticationConfig(_file=StringIO('[DEF'))
 
1246
        self.assertRaises(errors.ParseConfigError, conf._get_config)
 
1247
 
 
1248
    def test_auth_value_not_boolean(self):
 
1249
        conf = config.AuthenticationConfig(_file=StringIO(
 
1250
                """[broken]
 
1251
scheme=ftp
 
1252
user=joe
 
1253
verify_certificates=askme # Error: Not a boolean
 
1254
"""))
 
1255
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
 
1256
 
 
1257
    def test_auth_value_not_int(self):
 
1258
        conf = config.AuthenticationConfig(_file=StringIO(
 
1259
                """[broken]
 
1260
scheme=ftp
 
1261
user=joe
 
1262
port=port # Error: Not an int
 
1263
"""))
 
1264
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
 
1265
 
 
1266
    def test_credentials_for_scheme_host(self):
 
1267
        conf = config.AuthenticationConfig(_file=StringIO(
 
1268
                """# Identity on foo.net
 
1269
[ftp definition]
 
1270
scheme=ftp
 
1271
host=foo.net
 
1272
user=joe
 
1273
password=secret-pass
 
1274
"""))
 
1275
        # Basic matching
 
1276
        self._got_user_passwd('joe', 'secret-pass', conf, 'ftp', 'foo.net')
 
1277
        # different scheme
 
1278
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
 
1279
        # different host
 
1280
        self._got_user_passwd(None, None, conf, 'ftp', 'bar.net')
 
1281
 
 
1282
    def test_credentials_for_host_port(self):
 
1283
        conf = config.AuthenticationConfig(_file=StringIO(
 
1284
                """# Identity on foo.net
 
1285
[ftp definition]
 
1286
scheme=ftp
 
1287
port=10021
 
1288
host=foo.net
 
1289
user=joe
 
1290
password=secret-pass
 
1291
"""))
 
1292
        # No port
 
1293
        self._got_user_passwd('joe', 'secret-pass',
 
1294
                              conf, 'ftp', 'foo.net', port=10021)
 
1295
        # different port
 
1296
        self._got_user_passwd(None, None, conf, 'ftp', 'foo.net')
 
1297
 
 
1298
    def test_for_matching_host(self):
 
1299
        conf = config.AuthenticationConfig(_file=StringIO(
 
1300
                """# Identity on foo.net
 
1301
[sourceforge]
 
1302
scheme=bzr
 
1303
host=bzr.sf.net
 
1304
user=joe
 
1305
password=joepass
 
1306
[sourceforge domain]
 
1307
scheme=bzr
 
1308
host=.bzr.sf.net
 
1309
user=georges
 
1310
password=bendover
 
1311
"""))
 
1312
        # matching domain
 
1313
        self._got_user_passwd('georges', 'bendover',
 
1314
                              conf, 'bzr', 'foo.bzr.sf.net')
 
1315
        # phishing attempt
 
1316
        self._got_user_passwd(None, None,
 
1317
                              conf, 'bzr', 'bbzr.sf.net')
 
1318
 
 
1319
    def test_for_matching_host_None(self):
 
1320
        conf = config.AuthenticationConfig(_file=StringIO(
 
1321
                """# Identity on foo.net
 
1322
[catchup bzr]
 
1323
scheme=bzr
 
1324
user=joe
 
1325
password=joepass
 
1326
[DEFAULT]
 
1327
user=georges
 
1328
password=bendover
 
1329
"""))
 
1330
        # match no host
 
1331
        self._got_user_passwd('joe', 'joepass',
 
1332
                              conf, 'bzr', 'quux.net')
 
1333
        # no host but different scheme
 
1334
        self._got_user_passwd('georges', 'bendover',
 
1335
                              conf, 'ftp', 'quux.net')
 
1336
 
 
1337
    def test_credentials_for_path(self):
 
1338
        conf = config.AuthenticationConfig(_file=StringIO(
 
1339
                """
 
1340
[http dir1]
 
1341
scheme=http
 
1342
host=bar.org
 
1343
path=/dir1
 
1344
user=jim
 
1345
password=jimpass
 
1346
[http dir2]
 
1347
scheme=http
 
1348
host=bar.org
 
1349
path=/dir2
 
1350
user=georges
 
1351
password=bendover
 
1352
"""))
 
1353
        # no path no dice
 
1354
        self._got_user_passwd(None, None,
 
1355
                              conf, 'http', host='bar.org', path='/dir3')
 
1356
        # matching path
 
1357
        self._got_user_passwd('georges', 'bendover',
 
1358
                              conf, 'http', host='bar.org', path='/dir2')
 
1359
        # matching subdir
 
1360
        self._got_user_passwd('jim', 'jimpass',
 
1361
                              conf, 'http', host='bar.org',path='/dir1/subdir')
 
1362
 
 
1363
    def test_credentials_for_user(self):
 
1364
        conf = config.AuthenticationConfig(_file=StringIO(
 
1365
                """
 
1366
[with user]
 
1367
scheme=http
 
1368
host=bar.org
 
1369
user=jim
 
1370
password=jimpass
 
1371
"""))
 
1372
        # Get user
 
1373
        self._got_user_passwd('jim', 'jimpass',
 
1374
                              conf, 'http', 'bar.org')
 
1375
        # Get same user
 
1376
        self._got_user_passwd('jim', 'jimpass',
 
1377
                              conf, 'http', 'bar.org', user='jim')
 
1378
        # Don't get a different user if one is specified
 
1379
        self._got_user_passwd(None, None,
 
1380
                              conf, 'http', 'bar.org', user='georges')
 
1381
 
 
1382
    def test_credentials_for_user_without_password(self):
 
1383
        conf = config.AuthenticationConfig(_file=StringIO(
 
1384
                """
 
1385
[without password]
 
1386
scheme=http
 
1387
host=bar.org
 
1388
user=jim
 
1389
"""))
 
1390
        # Get user but no password
 
1391
        self._got_user_passwd('jim', None,
 
1392
                              conf, 'http', 'bar.org')
 
1393
 
 
1394
    def test_verify_certificates(self):
 
1395
        conf = config.AuthenticationConfig(_file=StringIO(
 
1396
                """
 
1397
[self-signed]
 
1398
scheme=https
 
1399
host=bar.org
 
1400
user=jim
 
1401
password=jimpass
 
1402
verify_certificates=False
 
1403
[normal]
 
1404
scheme=https
 
1405
host=foo.net
 
1406
user=georges
 
1407
password=bendover
 
1408
"""))
 
1409
        credentials = conf.get_credentials('https', 'bar.org')
 
1410
        self.assertEquals(False, credentials.get('verify_certificates'))
 
1411
        credentials = conf.get_credentials('https', 'foo.net')
 
1412
        self.assertEquals(True, credentials.get('verify_certificates'))
 
1413
 
 
1414
 
 
1415
class TestAuthenticationConfig(tests.TestCase):
 
1416
    """Test AuthenticationConfig behaviour"""
 
1417
 
 
1418
    def _check_default_prompt(self, expected_prompt_format, scheme,
 
1419
                              host=None, port=None, realm=None, path=None):
 
1420
        if host is None:
 
1421
            host = 'bar.org'
 
1422
        user, password = 'jim', 'precious'
 
1423
        expected_prompt = expected_prompt_format % {
 
1424
            'scheme': scheme, 'host': host, 'port': port,
 
1425
            'user': user, 'realm': realm}
 
1426
 
 
1427
        stdout = tests.StringIOWrapper()
 
1428
        ui.ui_factory = tests.TestUIFactory(stdin=password + '\n',
 
1429
                                            stdout=stdout)
 
1430
        # We use an empty conf so that the user is always prompted
 
1431
        conf = config.AuthenticationConfig()
 
1432
        self.assertEquals(password,
 
1433
                          conf.get_password(scheme, host, user, port=port,
 
1434
                                            realm=realm, path=path))
 
1435
        self.assertEquals(stdout.getvalue(), expected_prompt)
 
1436
 
 
1437
    def test_default_prompts(self):
 
1438
        # HTTP prompts can't be tested here, see test_http.py
 
1439
        self._check_default_prompt('FTP %(user)s@%(host)s password: ', 'ftp')
 
1440
        self._check_default_prompt('FTP %(user)s@%(host)s:%(port)d password: ',
 
1441
                                   'ftp', port=10020)
 
1442
 
 
1443
        self._check_default_prompt('SSH %(user)s@%(host)s:%(port)d password: ',
 
1444
                                   'ssh', port=12345)
 
1445
        # SMTP port handling is a bit special (it's handled if embedded in the
 
1446
        # host too)
 
1447
        # FIXME: should we: forbid that, extend it to other schemes, leave
 
1448
        # things as they are that's fine thank you ?
 
1449
        self._check_default_prompt('SMTP %(user)s@%(host)s password: ',
 
1450
                                   'smtp')
 
1451
        self._check_default_prompt('SMTP %(user)s@%(host)s password: ',
 
1452
                                   'smtp', host='bar.org:10025')
 
1453
        self._check_default_prompt(
 
1454
            'SMTP %(user)s@%(host)s:%(port)d password: ',
 
1455
            'smtp', port=10025)
 
1456
 
 
1457
    def test_ssh_password_emits_warning(self):
 
1458
        conf = config.AuthenticationConfig(_file=StringIO(
 
1459
                """
 
1460
[ssh with password]
 
1461
scheme=ssh
 
1462
host=bar.org
 
1463
user=jim
 
1464
password=jimpass
 
1465
"""))
 
1466
        entered_password = 'typed-by-hand'
 
1467
        stdout = tests.StringIOWrapper()
 
1468
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
 
1469
                                            stdout=stdout)
 
1470
 
 
1471
        # Since the password defined in the authentication config is ignored,
 
1472
        # the user is prompted
 
1473
        self.assertEquals(entered_password,
 
1474
                          conf.get_password('ssh', 'bar.org', user='jim'))
 
1475
        self.assertContainsRe(
 
1476
            self._get_log(keep_log_file=True),
 
1477
            'password ignored in section \[ssh with password\]')
 
1478
 
 
1479
    def test_ssh_without_password_doesnt_emit_warning(self):
 
1480
        conf = config.AuthenticationConfig(_file=StringIO(
 
1481
                """
 
1482
[ssh with password]
 
1483
scheme=ssh
 
1484
host=bar.org
 
1485
user=jim
 
1486
"""))
 
1487
        entered_password = 'typed-by-hand'
 
1488
        stdout = tests.StringIOWrapper()
 
1489
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
 
1490
                                            stdout=stdout)
 
1491
 
 
1492
        # Since the password defined in the authentication config is ignored,
 
1493
        # the user is prompted
 
1494
        self.assertEquals(entered_password,
 
1495
                          conf.get_password('ssh', 'bar.org', user='jim'))
 
1496
        # No warning shoud be emitted since there is no password. We are only
 
1497
        # providing "user".
 
1498
        self.assertNotContainsRe(
 
1499
            self._get_log(keep_log_file=True),
 
1500
            'password ignored in section \[ssh with password\]')
 
1501
 
 
1502
 
 
1503
# FIXME: Once we have a way to declare authentication to all test servers, we
 
1504
# can implement generic tests.
 
1505
# test_user_password_in_url
 
1506
# test_user_in_url_password_from_config
 
1507
# test_user_in_url_password_prompted
 
1508
# test_user_in_config
 
1509
# test_user_getpass.getuser
 
1510
# test_user_prompted ?
 
1511
class TestAuthenticationRing(tests.TestCaseWithTransport):
 
1512
    pass