~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Keir Mierle
  • Date: 2006-11-23 18:56:25 UTC
  • mto: (2168.1.1 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 2171.
  • Revision ID: keir@cs.utoronto.ca-20061123185625-ndto53ylcb8zo1y6
Fix spacing error and add tests for status --short command flag.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
2
#   Authors: Robert Collins <robert.collins@canonical.com>
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
"""Tests for finding and reading the bzr config file[s]."""
 
19
# import system imports here
 
20
from bzrlib.util.configobj.configobj import ConfigObj, ConfigObjError
 
21
from cStringIO import StringIO
 
22
import os
 
23
import sys
 
24
 
 
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 = ("[DEFAULT]\n"
 
39
                      u"email=Erik B\u00e5gfors <erik@bagfors.nu>\n"
 
40
                      "editor=vim\n"
 
41
                      "gpg_signing_command=gnome-gpg\n"
 
42
                      "log_format=short\n"
 
43
                      "user_global_option=something\n"
 
44
                      "[ALIASES]\n"
 
45
                      "h=help\n"
 
46
                      "ll=" + sample_long_alias + "\n")
 
47
 
 
48
 
 
49
sample_always_signatures = ("[DEFAULT]\n"
 
50
                            "check_signatures=ignore\n"
 
51
                            "create_signatures=always")
 
52
 
 
53
 
 
54
sample_ignore_signatures = ("[DEFAULT]\n"
 
55
                            "check_signatures=require\n"
 
56
                            "create_signatures=never")
 
57
 
 
58
 
 
59
sample_maybe_signatures = ("[DEFAULT]\n"
 
60
                            "check_signatures=ignore\n"
 
61
                            "create_signatures=when-required")
 
62
 
 
63
 
 
64
sample_branches_text = ("[http://www.example.com]\n"
 
65
                        "# Top level policy\n"
 
66
                        "email=Robert Collins <robertc@example.org>\n"
 
67
                        "[http://www.example.com/ignoreparent]\n"
 
68
                        "# different project: ignore parent dir config\n"
 
69
                        "ignore_parents=true\n"
 
70
                        "[http://www.example.com/norecurse]\n"
 
71
                        "# configuration items that only apply to this dir\n"
 
72
                        "recurse=false\n"
 
73
                        "[/b/]\n"
 
74
                        "check_signatures=require\n"
 
75
                        "# test trailing / matching with no children\n"
 
76
                        "[/a/]\n"
 
77
                        "check_signatures=check-available\n"
 
78
                        "gpg_signing_command=false\n"
 
79
                        "user_local_option=local\n"
 
80
                        "# test trailing / matching\n"
 
81
                        "[/a/*]\n"
 
82
                        "#subdirs will match but not the parent\n"
 
83
                        "[/a/c]\n"
 
84
                        "check_signatures=ignore\n"
 
85
                        "post_commit=bzrlib.tests.test_config.post_commit\n"
 
86
                        "#testing explicit beats globs\n")
 
87
 
 
88
 
 
89
 
 
90
class InstrumentedConfigObj(object):
 
91
    """A config obj look-enough-alike to record calls made to it."""
 
92
 
 
93
    def __contains__(self, thing):
 
94
        self._calls.append(('__contains__', thing))
 
95
        return False
 
96
 
 
97
    def __getitem__(self, key):
 
98
        self._calls.append(('__getitem__', key))
 
99
        return self
 
100
 
 
101
    def __init__(self, input, encoding=None):
 
102
        self._calls = [('__init__', input, encoding)]
 
103
 
 
104
    def __setitem__(self, key, value):
 
105
        self._calls.append(('__setitem__', key, value))
 
106
 
 
107
    def write(self, arg):
 
108
        self._calls.append(('write',))
 
109
 
 
110
 
 
111
class FakeBranch(object):
 
112
 
 
113
    def __init__(self, base=None, user_id=None):
 
114
        if base is None:
 
115
            self.base = "http://example.com/branches/demo"
 
116
        else:
 
117
            self.base = base
 
118
        self.control_files = FakeControlFiles(user_id=user_id)
 
119
 
 
120
    def lock_write(self):
 
121
        pass
 
122
 
 
123
    def unlock(self):
 
124
        pass
 
125
 
 
126
 
 
127
class FakeControlFiles(object):
 
128
 
 
129
    def __init__(self, user_id=None):
 
130
        self.email = user_id
 
131
        self.files = {}
 
132
 
 
133
    def get_utf8(self, filename):
 
134
        if filename != 'email':
 
135
            raise NotImplementedError
 
136
        if self.email is not None:
 
137
            return StringIO(self.email)
 
138
        raise errors.NoSuchFile(filename)
 
139
 
 
140
    def get(self, filename):
 
141
        try:
 
142
            return StringIO(self.files[filename])
 
143
        except KeyError:
 
144
            raise errors.NoSuchFile(filename)
 
145
 
 
146
    def put(self, filename, fileobj):
 
147
        self.files[filename] = fileobj.read()
 
148
 
 
149
 
 
150
class InstrumentedConfig(config.Config):
 
151
    """An instrumented config that supplies stubs for template methods."""
 
152
    
 
153
    def __init__(self):
 
154
        super(InstrumentedConfig, self).__init__()
 
155
        self._calls = []
 
156
        self._signatures = config.CHECK_NEVER
 
157
 
 
158
    def _get_user_id(self):
 
159
        self._calls.append('_get_user_id')
 
160
        return "Robert Collins <robert.collins@example.org>"
 
161
 
 
162
    def _get_signature_checking(self):
 
163
        self._calls.append('_get_signature_checking')
 
164
        return self._signatures
 
165
 
 
166
 
 
167
bool_config = """[DEFAULT]
 
168
active = true
 
169
inactive = false
 
170
[UPPERCASE]
 
171
active = True
 
172
nonactive = False
 
173
"""
 
174
class TestConfigObj(TestCase):
 
175
    def test_get_bool(self):
 
176
        from bzrlib.config import ConfigObj
 
177
        co = ConfigObj(StringIO(bool_config))
 
178
        self.assertIs(co.get_bool('DEFAULT', 'active'), True)
 
179
        self.assertIs(co.get_bool('DEFAULT', 'inactive'), False)
 
180
        self.assertIs(co.get_bool('UPPERCASE', 'active'), True)
 
181
        self.assertIs(co.get_bool('UPPERCASE', 'nonactive'), False)
 
182
 
 
183
 
 
184
class TestConfig(TestCase):
 
185
 
 
186
    def test_constructs(self):
 
187
        config.Config()
 
188
 
 
189
    def test_no_default_editor(self):
 
190
        self.assertRaises(NotImplementedError, config.Config().get_editor)
 
191
 
 
192
    def test_user_email(self):
 
193
        my_config = InstrumentedConfig()
 
194
        self.assertEqual('robert.collins@example.org', my_config.user_email())
 
195
        self.assertEqual(['_get_user_id'], my_config._calls)
 
196
 
 
197
    def test_username(self):
 
198
        my_config = InstrumentedConfig()
 
199
        self.assertEqual('Robert Collins <robert.collins@example.org>',
 
200
                         my_config.username())
 
201
        self.assertEqual(['_get_user_id'], my_config._calls)
 
202
 
 
203
    def test_signatures_default(self):
 
204
        my_config = config.Config()
 
205
        self.assertFalse(my_config.signature_needed())
 
206
        self.assertEqual(config.CHECK_IF_POSSIBLE,
 
207
                         my_config.signature_checking())
 
208
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
 
209
                         my_config.signing_policy())
 
210
 
 
211
    def test_signatures_template_method(self):
 
212
        my_config = InstrumentedConfig()
 
213
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
 
214
        self.assertEqual(['_get_signature_checking'], my_config._calls)
 
215
 
 
216
    def test_signatures_template_method_none(self):
 
217
        my_config = InstrumentedConfig()
 
218
        my_config._signatures = None
 
219
        self.assertEqual(config.CHECK_IF_POSSIBLE,
 
220
                         my_config.signature_checking())
 
221
        self.assertEqual(['_get_signature_checking'], my_config._calls)
 
222
 
 
223
    def test_gpg_signing_command_default(self):
 
224
        my_config = config.Config()
 
225
        self.assertEqual('gpg', my_config.gpg_signing_command())
 
226
 
 
227
    def test_get_user_option_default(self):
 
228
        my_config = config.Config()
 
229
        self.assertEqual(None, my_config.get_user_option('no_option'))
 
230
 
 
231
    def test_post_commit_default(self):
 
232
        my_config = config.Config()
 
233
        self.assertEqual(None, my_config.post_commit())
 
234
 
 
235
    def test_log_format_default(self):
 
236
        my_config = config.Config()
 
237
        self.assertEqual('long', my_config.log_format())
 
238
 
 
239
 
 
240
class TestConfigPath(TestCase):
 
241
 
 
242
    def setUp(self):
 
243
        super(TestConfigPath, self).setUp()
 
244
        self.old_home = os.environ.get('HOME', None)
 
245
        self.old_appdata = os.environ.get('APPDATA', None)
 
246
        os.environ['HOME'] = '/home/bogus'
 
247
        os.environ['APPDATA'] = \
 
248
            r'C:\Documents and Settings\bogus\Application Data'
 
249
 
 
250
    def tearDown(self):
 
251
        if self.old_home is None:
 
252
            del os.environ['HOME']
 
253
        else:
 
254
            os.environ['HOME'] = self.old_home
 
255
        if self.old_appdata is None:
 
256
            del os.environ['APPDATA']
 
257
        else:
 
258
            os.environ['APPDATA'] = self.old_appdata
 
259
        super(TestConfigPath, self).tearDown()
 
260
    
 
261
    def test_config_dir(self):
 
262
        if sys.platform == 'win32':
 
263
            self.assertEqual(config.config_dir(), 
 
264
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0')
 
265
        else:
 
266
            self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
 
267
 
 
268
    def test_config_filename(self):
 
269
        if sys.platform == 'win32':
 
270
            self.assertEqual(config.config_filename(), 
 
271
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/bazaar.conf')
 
272
        else:
 
273
            self.assertEqual(config.config_filename(),
 
274
                             '/home/bogus/.bazaar/bazaar.conf')
 
275
 
 
276
    def test_branches_config_filename(self):
 
277
        if sys.platform == 'win32':
 
278
            self.assertEqual(config.branches_config_filename(), 
 
279
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/branches.conf')
 
280
        else:
 
281
            self.assertEqual(config.branches_config_filename(),
 
282
                             '/home/bogus/.bazaar/branches.conf')
 
283
 
 
284
    def test_locations_config_filename(self):
 
285
        if sys.platform == 'win32':
 
286
            self.assertEqual(config.locations_config_filename(), 
 
287
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/locations.conf')
 
288
        else:
 
289
            self.assertEqual(config.locations_config_filename(),
 
290
                             '/home/bogus/.bazaar/locations.conf')
 
291
 
 
292
class TestIniConfig(TestCase):
 
293
 
 
294
    def test_contructs(self):
 
295
        my_config = config.IniBasedConfig("nothing")
 
296
 
 
297
    def test_from_fp(self):
 
298
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
299
        my_config = config.IniBasedConfig(None)
 
300
        self.failUnless(
 
301
            isinstance(my_config._get_parser(file=config_file),
 
302
                        ConfigObj))
 
303
 
 
304
    def test_cached(self):
 
305
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
306
        my_config = config.IniBasedConfig(None)
 
307
        parser = my_config._get_parser(file=config_file)
 
308
        self.failUnless(my_config._get_parser() is parser)
 
309
 
 
310
 
 
311
class TestGetConfig(TestCase):
 
312
 
 
313
    def test_constructs(self):
 
314
        my_config = config.GlobalConfig()
 
315
 
 
316
    def test_calls_read_filenames(self):
 
317
        # replace the class that is constructured, to check its parameters
 
318
        oldparserclass = config.ConfigObj
 
319
        config.ConfigObj = InstrumentedConfigObj
 
320
        my_config = config.GlobalConfig()
 
321
        try:
 
322
            parser = my_config._get_parser()
 
323
        finally:
 
324
            config.ConfigObj = oldparserclass
 
325
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
 
326
        self.assertEqual(parser._calls, [('__init__', config.config_filename(),
 
327
                                          'utf-8')])
 
328
 
 
329
 
 
330
class TestBranchConfig(TestCaseWithTransport):
 
331
 
 
332
    def test_constructs(self):
 
333
        branch = FakeBranch()
 
334
        my_config = config.BranchConfig(branch)
 
335
        self.assertRaises(TypeError, config.BranchConfig)
 
336
 
 
337
    def test_get_location_config(self):
 
338
        branch = FakeBranch()
 
339
        my_config = config.BranchConfig(branch)
 
340
        location_config = my_config._get_location_config()
 
341
        self.assertEqual(branch.base, location_config.location)
 
342
        self.failUnless(location_config is my_config._get_location_config())
 
343
 
 
344
    def test_get_config(self):
 
345
        """The Branch.get_config method works properly"""
 
346
        b = BzrDir.create_standalone_workingtree('.').branch
 
347
        my_config = b.get_config()
 
348
        self.assertIs(my_config.get_user_option('wacky'), None)
 
349
        my_config.set_user_option('wacky', 'unlikely')
 
350
        self.assertEqual(my_config.get_user_option('wacky'), 'unlikely')
 
351
 
 
352
        # Ensure we get the same thing if we start again
 
353
        b2 = Branch.open('.')
 
354
        my_config2 = b2.get_config()
 
355
        self.assertEqual(my_config2.get_user_option('wacky'), 'unlikely')
 
356
 
 
357
    def test_has_explicit_nickname(self):
 
358
        b = self.make_branch('.')
 
359
        self.assertFalse(b.get_config().has_explicit_nickname())
 
360
        b.nick = 'foo'
 
361
        self.assertTrue(b.get_config().has_explicit_nickname())
 
362
 
 
363
    def test_config_url(self):
 
364
        """The Branch.get_config will use section that uses a local url"""
 
365
        branch = self.make_branch('branch')
 
366
        self.assertEqual('branch', branch.nick)
 
367
 
 
368
        locations = config.locations_config_filename()
 
369
        config.ensure_config_dir_exists()
 
370
        local_url = urlutils.local_path_to_url('branch')
 
371
        open(locations, 'wb').write('[%s]\nnickname = foobar' 
 
372
                                    % (local_url,))
 
373
        self.assertEqual('foobar', branch.nick)
 
374
 
 
375
    def test_config_local_path(self):
 
376
        """The Branch.get_config will use a local system path"""
 
377
        branch = self.make_branch('branch')
 
378
        self.assertEqual('branch', branch.nick)
 
379
 
 
380
        locations = config.locations_config_filename()
 
381
        config.ensure_config_dir_exists()
 
382
        open(locations, 'wb').write('[%s/branch]\nnickname = barry' 
 
383
                                    % (osutils.getcwd().encode('utf8'),))
 
384
        self.assertEqual('barry', branch.nick)
 
385
 
 
386
    def test_config_creates_local(self):
 
387
        """Creating a new entry in config uses a local path."""
 
388
        branch = self.make_branch('branch')
 
389
        branch.set_push_location('http://foobar')
 
390
        locations = config.locations_config_filename()
 
391
        local_path = osutils.getcwd().encode('utf8')
 
392
        # Surprisingly ConfigObj doesn't create a trailing newline
 
393
        self.check_file_contents(locations,
 
394
            '[%s/branch]\npush_location = http://foobar' % (local_path,))
 
395
 
 
396
    def test_autonick_urlencoded(self):
 
397
        b = self.make_branch('!repo')
 
398
        self.assertEqual('!repo', b.get_config().get_nickname())
 
399
 
 
400
 
 
401
class TestGlobalConfigItems(TestCase):
 
402
 
 
403
    def test_user_id(self):
 
404
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
405
        my_config = config.GlobalConfig()
 
406
        my_config._parser = my_config._get_parser(file=config_file)
 
407
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
 
408
                         my_config._get_user_id())
 
409
 
 
410
    def test_absent_user_id(self):
 
411
        config_file = StringIO("")
 
412
        my_config = config.GlobalConfig()
 
413
        my_config._parser = my_config._get_parser(file=config_file)
 
414
        self.assertEqual(None, my_config._get_user_id())
 
415
 
 
416
    def test_configured_editor(self):
 
417
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
418
        my_config = config.GlobalConfig()
 
419
        my_config._parser = my_config._get_parser(file=config_file)
 
420
        self.assertEqual("vim", my_config.get_editor())
 
421
 
 
422
    def test_signatures_always(self):
 
423
        config_file = StringIO(sample_always_signatures)
 
424
        my_config = config.GlobalConfig()
 
425
        my_config._parser = my_config._get_parser(file=config_file)
 
426
        self.assertEqual(config.CHECK_NEVER,
 
427
                         my_config.signature_checking())
 
428
        self.assertEqual(config.SIGN_ALWAYS,
 
429
                         my_config.signing_policy())
 
430
        self.assertEqual(True, my_config.signature_needed())
 
431
 
 
432
    def test_signatures_if_possible(self):
 
433
        config_file = StringIO(sample_maybe_signatures)
 
434
        my_config = config.GlobalConfig()
 
435
        my_config._parser = my_config._get_parser(file=config_file)
 
436
        self.assertEqual(config.CHECK_NEVER,
 
437
                         my_config.signature_checking())
 
438
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
 
439
                         my_config.signing_policy())
 
440
        self.assertEqual(False, my_config.signature_needed())
 
441
 
 
442
    def test_signatures_ignore(self):
 
443
        config_file = StringIO(sample_ignore_signatures)
 
444
        my_config = config.GlobalConfig()
 
445
        my_config._parser = my_config._get_parser(file=config_file)
 
446
        self.assertEqual(config.CHECK_ALWAYS,
 
447
                         my_config.signature_checking())
 
448
        self.assertEqual(config.SIGN_NEVER,
 
449
                         my_config.signing_policy())
 
450
        self.assertEqual(False, my_config.signature_needed())
 
451
 
 
452
    def _get_sample_config(self):
 
453
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
454
        my_config = config.GlobalConfig()
 
455
        my_config._parser = my_config._get_parser(file=config_file)
 
456
        return my_config
 
457
 
 
458
    def test_gpg_signing_command(self):
 
459
        my_config = self._get_sample_config()
 
460
        self.assertEqual("gnome-gpg", my_config.gpg_signing_command())
 
461
        self.assertEqual(False, my_config.signature_needed())
 
462
 
 
463
    def _get_empty_config(self):
 
464
        config_file = StringIO("")
 
465
        my_config = config.GlobalConfig()
 
466
        my_config._parser = my_config._get_parser(file=config_file)
 
467
        return my_config
 
468
 
 
469
    def test_gpg_signing_command_unset(self):
 
470
        my_config = self._get_empty_config()
 
471
        self.assertEqual("gpg", my_config.gpg_signing_command())
 
472
 
 
473
    def test_get_user_option_default(self):
 
474
        my_config = self._get_empty_config()
 
475
        self.assertEqual(None, my_config.get_user_option('no_option'))
 
476
 
 
477
    def test_get_user_option_global(self):
 
478
        my_config = self._get_sample_config()
 
479
        self.assertEqual("something",
 
480
                         my_config.get_user_option('user_global_option'))
 
481
        
 
482
    def test_post_commit_default(self):
 
483
        my_config = self._get_sample_config()
 
484
        self.assertEqual(None, my_config.post_commit())
 
485
 
 
486
    def test_configured_logformat(self):
 
487
        my_config = self._get_sample_config()
 
488
        self.assertEqual("short", my_config.log_format())
 
489
 
 
490
    def test_get_alias(self):
 
491
        my_config = self._get_sample_config()
 
492
        self.assertEqual('help', my_config.get_alias('h'))
 
493
 
 
494
    def test_get_no_alias(self):
 
495
        my_config = self._get_sample_config()
 
496
        self.assertEqual(None, my_config.get_alias('foo'))
 
497
 
 
498
    def test_get_long_alias(self):
 
499
        my_config = self._get_sample_config()
 
500
        self.assertEqual(sample_long_alias, my_config.get_alias('ll'))
 
501
 
 
502
 
 
503
class TestLocationConfig(TestCaseInTempDir):
 
504
 
 
505
    def test_constructs(self):
 
506
        my_config = config.LocationConfig('http://example.com')
 
507
        self.assertRaises(TypeError, config.LocationConfig)
 
508
 
 
509
    def test_branch_calls_read_filenames(self):
 
510
        # This is testing the correct file names are provided.
 
511
        # TODO: consolidate with the test for GlobalConfigs filename checks.
 
512
        #
 
513
        # replace the class that is constructured, to check its parameters
 
514
        oldparserclass = config.ConfigObj
 
515
        config.ConfigObj = InstrumentedConfigObj
 
516
        try:
 
517
            my_config = config.LocationConfig('http://www.example.com')
 
518
            parser = my_config._get_parser()
 
519
        finally:
 
520
            config.ConfigObj = oldparserclass
 
521
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
 
522
        self.assertEqual(parser._calls,
 
523
                         [('__init__', config.locations_config_filename(),
 
524
                           'utf-8')])
 
525
        config.ensure_config_dir_exists()
 
526
        #os.mkdir(config.config_dir())
 
527
        f = file(config.branches_config_filename(), 'wb')
 
528
        f.write('')
 
529
        f.close()
 
530
        oldparserclass = config.ConfigObj
 
531
        config.ConfigObj = InstrumentedConfigObj
 
532
        try:
 
533
            my_config = config.LocationConfig('http://www.example.com')
 
534
            parser = my_config._get_parser()
 
535
        finally:
 
536
            config.ConfigObj = oldparserclass
 
537
 
 
538
    def test_get_global_config(self):
 
539
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
 
540
        global_config = my_config._get_global_config()
 
541
        self.failUnless(isinstance(global_config, config.GlobalConfig))
 
542
        self.failUnless(global_config is my_config._get_global_config())
 
543
 
 
544
    def test__get_matching_sections_no_match(self):
 
545
        self.get_branch_config('/')
 
546
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
547
        
 
548
    def test__get_matching_sections_exact(self):
 
549
        self.get_branch_config('http://www.example.com')
 
550
        self.assertEqual([('http://www.example.com', '')],
 
551
                         self.my_location_config._get_matching_sections())
 
552
   
 
553
    def test__get_matching_sections_suffix_does_not(self):
 
554
        self.get_branch_config('http://www.example.com-com')
 
555
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
556
 
 
557
    def test__get_matching_sections_subdir_recursive(self):
 
558
        self.get_branch_config('http://www.example.com/com')
 
559
        self.assertEqual([('http://www.example.com', 'com')],
 
560
                         self.my_location_config._get_matching_sections())
 
561
 
 
562
    def test__get_matching_sections_ignoreparent(self):
 
563
        self.get_branch_config('http://www.example.com/ignoreparent')
 
564
        self.assertEqual([('http://www.example.com/ignoreparent', '')],
 
565
                         self.my_location_config._get_matching_sections())
 
566
 
 
567
    def test__get_matching_sections_ignoreparent_subdir(self):
 
568
        self.get_branch_config(
 
569
            'http://www.example.com/ignoreparent/childbranch')
 
570
        self.assertEqual([('http://www.example.com/ignoreparent', 'childbranch')],
 
571
                         self.my_location_config._get_matching_sections())
 
572
 
 
573
    def test__get_matching_sections_norecurse(self):
 
574
        self.get_branch_config('http://www.example.com/norecurse')
 
575
        self.assertEqual([('http://www.example.com/norecurse', ''),
 
576
                          ('http://www.example.com', 'norecurse')],
 
577
                         self.my_location_config._get_matching_sections())
 
578
 
 
579
    def test__get_matching_sections_norecurse_subdir(self):
 
580
        self.get_branch_config(
 
581
            'http://www.example.com/norecurse/childbranch')
 
582
        self.assertEqual([('http://www.example.com', 'norecurse/childbranch')],
 
583
                         self.my_location_config._get_matching_sections())
 
584
 
 
585
    def test__get_matching_sections_subdir_trailing_slash(self):
 
586
        self.get_branch_config('/b')
 
587
        self.assertEqual([('/b/', '')],
 
588
                         self.my_location_config._get_matching_sections())
 
589
 
 
590
    def test__get_matching_sections_subdir_child(self):
 
591
        self.get_branch_config('/a/foo')
 
592
        self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
 
593
                         self.my_location_config._get_matching_sections())
 
594
 
 
595
    def test__get_matching_sections_subdir_child_child(self):
 
596
        self.get_branch_config('/a/foo/bar')
 
597
        self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
 
598
                         self.my_location_config._get_matching_sections())
 
599
 
 
600
    def test__get_matching_sections_trailing_slash_with_children(self):
 
601
        self.get_branch_config('/a/')
 
602
        self.assertEqual([('/a/', '')],
 
603
                         self.my_location_config._get_matching_sections())
 
604
 
 
605
    def test__get_matching_sections_explicit_over_glob(self):
 
606
        # XXX: 2006-09-08 jamesh
 
607
        # This test only passes because ord('c') > ord('*').  If there
 
608
        # was a config section for '/a/?', it would get precedence
 
609
        # over '/a/c'.
 
610
        self.get_branch_config('/a/c')
 
611
        self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
 
612
                         self.my_location_config._get_matching_sections())
 
613
 
 
614
    def test_location_without_username(self):
 
615
        self.get_branch_config('http://www.example.com/ignoreparent')
 
616
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
 
617
                         self.my_config.username())
 
618
 
 
619
    def test_location_not_listed(self):
 
620
        """Test that the global username is used when no location matches"""
 
621
        self.get_branch_config('/home/robertc/sources')
 
622
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
 
623
                         self.my_config.username())
 
624
 
 
625
    def test_overriding_location(self):
 
626
        self.get_branch_config('http://www.example.com/foo')
 
627
        self.assertEqual('Robert Collins <robertc@example.org>',
 
628
                         self.my_config.username())
 
629
 
 
630
    def test_signatures_not_set(self):
 
631
        self.get_branch_config('http://www.example.com',
 
632
                                 global_config=sample_ignore_signatures)
 
633
        self.assertEqual(config.CHECK_ALWAYS,
 
634
                         self.my_config.signature_checking())
 
635
        self.assertEqual(config.SIGN_NEVER,
 
636
                         self.my_config.signing_policy())
 
637
 
 
638
    def test_signatures_never(self):
 
639
        self.get_branch_config('/a/c')
 
640
        self.assertEqual(config.CHECK_NEVER,
 
641
                         self.my_config.signature_checking())
 
642
        
 
643
    def test_signatures_when_available(self):
 
644
        self.get_branch_config('/a/', global_config=sample_ignore_signatures)
 
645
        self.assertEqual(config.CHECK_IF_POSSIBLE,
 
646
                         self.my_config.signature_checking())
 
647
        
 
648
    def test_signatures_always(self):
 
649
        self.get_branch_config('/b')
 
650
        self.assertEqual(config.CHECK_ALWAYS,
 
651
                         self.my_config.signature_checking())
 
652
        
 
653
    def test_gpg_signing_command(self):
 
654
        self.get_branch_config('/b')
 
655
        self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
 
656
 
 
657
    def test_gpg_signing_command_missing(self):
 
658
        self.get_branch_config('/a')
 
659
        self.assertEqual("false", self.my_config.gpg_signing_command())
 
660
 
 
661
    def test_get_user_option_global(self):
 
662
        self.get_branch_config('/a')
 
663
        self.assertEqual('something',
 
664
                         self.my_config.get_user_option('user_global_option'))
 
665
 
 
666
    def test_get_user_option_local(self):
 
667
        self.get_branch_config('/a')
 
668
        self.assertEqual('local',
 
669
                         self.my_config.get_user_option('user_local_option'))
 
670
 
 
671
    def test_post_commit_default(self):
 
672
        self.get_branch_config('/a/c')
 
673
        self.assertEqual('bzrlib.tests.test_config.post_commit',
 
674
                         self.my_config.post_commit())
 
675
 
 
676
    def get_branch_config(self, location, global_config=None):
 
677
        if global_config is None:
 
678
            global_file = StringIO(sample_config_text.encode('utf-8'))
 
679
        else:
 
680
            global_file = StringIO(global_config.encode('utf-8'))
 
681
        branches_file = StringIO(sample_branches_text.encode('utf-8'))
 
682
        self.my_config = config.BranchConfig(FakeBranch(location))
 
683
        # Force location config to use specified file
 
684
        self.my_location_config = self.my_config._get_location_config()
 
685
        self.my_location_config._get_parser(branches_file)
 
686
        # Force global config to use specified file
 
687
        self.my_config._get_global_config()._get_parser(global_file)
 
688
 
 
689
    def test_set_user_setting_sets_and_saves(self):
 
690
        self.get_branch_config('/a/c')
 
691
        record = InstrumentedConfigObj("foo")
 
692
        self.my_location_config._parser = record
 
693
 
 
694
        real_mkdir = os.mkdir
 
695
        self.created = False
 
696
        def checked_mkdir(path, mode=0777):
 
697
            self.log('making directory: %s', path)
 
698
            real_mkdir(path, mode)
 
699
            self.created = True
 
700
 
 
701
        os.mkdir = checked_mkdir
 
702
        try:
 
703
            self.my_config.set_user_option('foo', 'bar', local=True)
 
704
        finally:
 
705
            os.mkdir = real_mkdir
 
706
 
 
707
        self.failUnless(self.created, 'Failed to create ~/.bazaar')
 
708
        self.assertEqual([('__contains__', '/a/c'),
 
709
                          ('__contains__', '/a/c/'),
 
710
                          ('__setitem__', '/a/c', {}),
 
711
                          ('__getitem__', '/a/c'),
 
712
                          ('__setitem__', 'foo', 'bar'),
 
713
                          ('write',)],
 
714
                         record._calls[1:])
 
715
 
 
716
    def test_set_user_setting_sets_and_saves2(self):
 
717
        self.get_branch_config('/a/c')
 
718
        self.assertIs(self.my_config.get_user_option('foo'), None)
 
719
        self.my_config.set_user_option('foo', 'bar')
 
720
        self.assertEqual(
 
721
            self.my_config.branch.control_files.files['branch.conf'], 
 
722
            'foo = bar')
 
723
        self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
 
724
        self.my_config.set_user_option('foo', 'baz', local=True)
 
725
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
 
726
        self.my_config.set_user_option('foo', 'qux')
 
727
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
 
728
        
 
729
 
 
730
precedence_global = 'option = global'
 
731
precedence_branch = 'option = branch'
 
732
precedence_location = """
 
733
[http://]
 
734
recurse = true
 
735
option = recurse
 
736
[http://example.com/specific]
 
737
option = exact
 
738
"""
 
739
 
 
740
 
 
741
class TestBranchConfigItems(TestCaseInTempDir):
 
742
 
 
743
    def get_branch_config(self, global_config=None, location=None, 
 
744
                          location_config=None, branch_data_config=None):
 
745
        my_config = config.BranchConfig(FakeBranch(location))
 
746
        if global_config is not None:
 
747
            global_file = StringIO(global_config.encode('utf-8'))
 
748
            my_config._get_global_config()._get_parser(global_file)
 
749
        self.my_location_config = my_config._get_location_config()
 
750
        if location_config is not None:
 
751
            location_file = StringIO(location_config.encode('utf-8'))
 
752
            self.my_location_config._get_parser(location_file)
 
753
        if branch_data_config is not None:
 
754
            my_config.branch.control_files.files['branch.conf'] = \
 
755
                branch_data_config
 
756
        return my_config
 
757
 
 
758
    def test_user_id(self):
 
759
        branch = FakeBranch(user_id='Robert Collins <robertc@example.net>')
 
760
        my_config = config.BranchConfig(branch)
 
761
        self.assertEqual("Robert Collins <robertc@example.net>",
 
762
                         my_config.username())
 
763
        branch.control_files.email = "John"
 
764
        my_config.set_user_option('email', 
 
765
                                  "Robert Collins <robertc@example.org>")
 
766
        self.assertEqual("John", my_config.username())
 
767
        branch.control_files.email = None
 
768
        self.assertEqual("Robert Collins <robertc@example.org>",
 
769
                         my_config.username())
 
770
 
 
771
    def test_not_set_in_branch(self):
 
772
        my_config = self.get_branch_config(sample_config_text)
 
773
        my_config.branch.control_files.email = None
 
774
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
 
775
                         my_config._get_user_id())
 
776
        my_config.branch.control_files.email = "John"
 
777
        self.assertEqual("John", my_config._get_user_id())
 
778
 
 
779
    def test_BZR_EMAIL_OVERRIDES(self):
 
780
        os.environ['BZR_EMAIL'] = "Robert Collins <robertc@example.org>"
 
781
        branch = FakeBranch()
 
782
        my_config = config.BranchConfig(branch)
 
783
        self.assertEqual("Robert Collins <robertc@example.org>",
 
784
                         my_config.username())
 
785
    
 
786
    def test_signatures_forced(self):
 
787
        my_config = self.get_branch_config(
 
788
            global_config=sample_always_signatures)
 
789
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
 
790
        self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
 
791
        self.assertTrue(my_config.signature_needed())
 
792
 
 
793
    def test_signatures_forced_branch(self):
 
794
        my_config = self.get_branch_config(
 
795
            global_config=sample_ignore_signatures,
 
796
            branch_data_config=sample_always_signatures)
 
797
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
 
798
        self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
 
799
        self.assertTrue(my_config.signature_needed())
 
800
 
 
801
    def test_gpg_signing_command(self):
 
802
        my_config = self.get_branch_config(
 
803
            # branch data cannot set gpg_signing_command
 
804
            branch_data_config="gpg_signing_command=pgp")
 
805
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
806
        my_config._get_global_config()._get_parser(config_file)
 
807
        self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
 
808
 
 
809
    def test_get_user_option_global(self):
 
810
        branch = FakeBranch()
 
811
        my_config = config.BranchConfig(branch)
 
812
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
813
        (my_config._get_global_config()._get_parser(config_file))
 
814
        self.assertEqual('something',
 
815
                         my_config.get_user_option('user_global_option'))
 
816
 
 
817
    def test_post_commit_default(self):
 
818
        branch = FakeBranch()
 
819
        my_config = self.get_branch_config(sample_config_text, '/a/c',
 
820
                                           sample_branches_text)
 
821
        self.assertEqual(my_config.branch.base, '/a/c')
 
822
        self.assertEqual('bzrlib.tests.test_config.post_commit',
 
823
                         my_config.post_commit())
 
824
        my_config.set_user_option('post_commit', 'rmtree_root')
 
825
        # post-commit is ignored when bresent in branch data
 
826
        self.assertEqual('bzrlib.tests.test_config.post_commit',
 
827
                         my_config.post_commit())
 
828
        my_config.set_user_option('post_commit', 'rmtree_root', local=True)
 
829
        self.assertEqual('rmtree_root', my_config.post_commit())
 
830
 
 
831
    def test_config_precedence(self):
 
832
        my_config = self.get_branch_config(global_config=precedence_global)
 
833
        self.assertEqual(my_config.get_user_option('option'), 'global')
 
834
        my_config = self.get_branch_config(global_config=precedence_global, 
 
835
                                      branch_data_config=precedence_branch)
 
836
        self.assertEqual(my_config.get_user_option('option'), 'branch')
 
837
        my_config = self.get_branch_config(global_config=precedence_global, 
 
838
                                      branch_data_config=precedence_branch,
 
839
                                      location_config=precedence_location)
 
840
        self.assertEqual(my_config.get_user_option('option'), 'recurse')
 
841
        my_config = self.get_branch_config(global_config=precedence_global, 
 
842
                                      branch_data_config=precedence_branch,
 
843
                                      location_config=precedence_location,
 
844
                                      location='http://example.com/specific')
 
845
        self.assertEqual(my_config.get_user_option('option'), 'exact')
 
846
 
 
847
 
 
848
class TestMailAddressExtraction(TestCase):
 
849
 
 
850
    def test_extract_email_address(self):
 
851
        self.assertEqual('jane@test.com',
 
852
                         config.extract_email_address('Jane <jane@test.com>'))
 
853
        self.assertRaises(errors.NoEmailInUsername,
 
854
                          config.extract_email_address, 'Jane Tester')