/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testworkingtree.py

[merge] robertc's integration, updated tests to check for retcode=3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2012, 2016 Canonical Ltd
 
1
# (C) 2005 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
13
13
#
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
17
 
18
 
from io import BytesIO
19
18
import os
20
 
 
21
 
from .. import (
22
 
    conflicts,
23
 
    errors,
24
 
    symbol_versioning,
25
 
    trace,
26
 
    transport,
27
 
    workingtree,
28
 
    )
29
 
from ..bzr import (
30
 
    bzrdir,
31
 
    workingtree as bzrworkingtree,
32
 
    workingtree_3,
33
 
    workingtree_4,
34
 
    )
35
 
from ..lock import write_locked
36
 
from ..lockdir import LockDir
37
 
from . import TestCase, TestCaseWithTransport, TestSkipped
38
 
from ..tree import (
39
 
    TreeEntry,
40
 
    TreeDirectory,
41
 
    TreeFile,
42
 
    TreeLink,
43
 
    )
44
 
 
45
 
from .features import SymlinkFeature
46
 
 
47
 
class TestTreeDirectory(TestCaseWithTransport):
 
19
from bzrlib.branch import Branch
 
20
from bzrlib.errors import NotVersionedError
 
21
from bzrlib.selftest import TestCaseInTempDir
 
22
from bzrlib.trace import mutter
 
23
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
 
24
                                WorkingTree)
 
25
 
 
26
class TestTreeDirectory(TestCaseInTempDir):
48
27
 
49
28
    def test_kind_character(self):
50
29
        self.assertEqual(TreeDirectory().kind_character(), '/')
51
30
 
52
31
 
53
 
class TestTreeEntry(TestCaseWithTransport):
 
32
class TestTreeEntry(TestCaseInTempDir):
54
33
 
55
34
    def test_kind_character(self):
56
35
        self.assertEqual(TreeEntry().kind_character(), '???')
57
36
 
58
37
 
59
 
class TestTreeFile(TestCaseWithTransport):
 
38
class TestTreeFile(TestCaseInTempDir):
60
39
 
61
40
    def test_kind_character(self):
62
41
        self.assertEqual(TreeFile().kind_character(), '')
63
42
 
64
43
 
65
 
class TestTreeLink(TestCaseWithTransport):
 
44
class TestTreeLink(TestCaseInTempDir):
66
45
 
67
46
    def test_kind_character(self):
68
47
        self.assertEqual(TreeLink().kind_character(), '')
69
48
 
70
49
 
71
 
class TestDefaultFormat(TestCaseWithTransport):
72
 
 
73
 
    def test_get_set_default_format(self):
74
 
        old_format = workingtree.format_registry.get_default()
75
 
        # default is 6
76
 
        self.assertTrue(isinstance(
77
 
            old_format, workingtree_4.WorkingTreeFormat6))
78
 
        workingtree.format_registry.set_default(SampleTreeFormat())
79
 
        try:
80
 
            # the default branch format is used by the meta dir format
81
 
            # which is not the default bzrdir format at this point
82
 
            dir = bzrdir.BzrDirMetaFormat1().initialize('.')
83
 
            dir.create_repository()
84
 
            dir.create_branch()
85
 
            result = dir.create_workingtree()
86
 
            self.assertEqual(result, 'A tree')
87
 
        finally:
88
 
            workingtree.format_registry.set_default(old_format)
89
 
        self.assertEqual(old_format, workingtree.format_registry.get_default())
90
 
 
91
 
    def test_from_string(self):
92
 
        self.assertIsInstance(
93
 
            SampleTreeFormat.from_string(b"Sample tree format."),
94
 
            SampleTreeFormat)
95
 
        self.assertRaises(
96
 
            AssertionError, SampleTreeFormat.from_string,
97
 
            b"Different format string.")
98
 
 
99
 
    def test_get_set_default_format_by_key(self):
100
 
        old_format = workingtree.format_registry.get_default()
101
 
        # default is 6
102
 
        format = SampleTreeFormat()
103
 
        workingtree.format_registry.register(format)
104
 
        self.addCleanup(workingtree.format_registry.remove, format)
105
 
        self.assertTrue(isinstance(
106
 
            old_format, workingtree_4.WorkingTreeFormat6))
107
 
        workingtree.format_registry.set_default_key(format.get_format_string())
108
 
        try:
109
 
            # the default branch format is used by the meta dir format
110
 
            # which is not the default bzrdir format at this point
111
 
            dir = bzrdir.BzrDirMetaFormat1().initialize('.')
112
 
            dir.create_repository()
113
 
            dir.create_branch()
114
 
            result = dir.create_workingtree()
115
 
            self.assertEqual(result, 'A tree')
116
 
        finally:
117
 
            workingtree.format_registry.set_default_key(
118
 
                old_format.get_format_string())
119
 
        self.assertEqual(old_format, workingtree.format_registry.get_default())
120
 
 
121
 
    def test_open(self):
122
 
        tree = self.make_branch_and_tree('.')
123
 
        open_direct = workingtree.WorkingTree.open('.')
124
 
        self.assertEqual(tree.basedir, open_direct.basedir)
125
 
        open_no_args = workingtree.WorkingTree.open()
126
 
        self.assertEqual(tree.basedir, open_no_args.basedir)
127
 
 
128
 
    def test_open_containing(self):
129
 
        tree = self.make_branch_and_tree('.')
130
 
        open_direct, relpath = workingtree.WorkingTree.open_containing('.')
131
 
        self.assertEqual(tree.basedir, open_direct.basedir)
132
 
        self.assertEqual('', relpath)
133
 
        open_no_args, relpath = workingtree.WorkingTree.open_containing()
134
 
        self.assertEqual(tree.basedir, open_no_args.basedir)
135
 
        self.assertEqual('', relpath)
136
 
        open_subdir, relpath = workingtree.WorkingTree.open_containing(
137
 
            'subdir')
138
 
        self.assertEqual(tree.basedir, open_subdir.basedir)
139
 
        self.assertEqual('subdir', relpath)
140
 
 
141
 
 
142
 
class SampleTreeFormat(bzrworkingtree.WorkingTreeFormatMetaDir):
143
 
    """A sample format
144
 
 
145
 
    this format is initializable, unsupported to aid in testing the
146
 
    open and open_downlevel routines.
147
 
    """
148
 
 
149
 
    @classmethod
150
 
    def get_format_string(cls):
151
 
        """See WorkingTreeFormat.get_format_string()."""
152
 
        return b"Sample tree format."
153
 
 
154
 
    def initialize(self, a_controldir, revision_id=None, from_branch=None,
155
 
                   accelerator_tree=None, hardlink=False):
156
 
        """Sample branches cannot be created."""
157
 
        t = a_controldir.get_workingtree_transport(self)
158
 
        t.put_bytes('format', self.get_format_string())
159
 
        return 'A tree'
160
 
 
161
 
    def is_supported(self):
162
 
        return False
163
 
 
164
 
    def open(self, transport, _found=False):
165
 
        return "opened tree."
166
 
 
167
 
 
168
 
class SampleExtraTreeFormat(workingtree.WorkingTreeFormat):
169
 
    """A sample format that does not support use in a metadir.
170
 
 
171
 
    """
172
 
 
173
 
    def get_format_string(self):
174
 
        # Not usable in a metadir, so no format string
175
 
        return None
176
 
 
177
 
    def initialize(self, a_controldir, revision_id=None, from_branch=None,
178
 
                   accelerator_tree=None, hardlink=False):
179
 
        raise NotImplementedError(self.initialize)
180
 
 
181
 
    def is_supported(self):
182
 
        return False
183
 
 
184
 
    def open(self, transport, _found=False):
185
 
        raise NotImplementedError(self.open)
186
 
 
187
 
 
188
 
class TestWorkingTreeFormat(TestCaseWithTransport):
189
 
    """Tests for the WorkingTreeFormat facility."""
190
 
 
191
 
    def test_find_format_string(self):
192
 
        # is the right format object found for a working tree?
193
 
        branch = self.make_branch('branch')
194
 
        self.assertRaises(
195
 
            errors.NoWorkingTree,
196
 
            bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string,
197
 
            branch.controldir)
198
 
        transport = branch.controldir.get_workingtree_transport(None)
199
 
        transport.mkdir('.')
200
 
        transport.put_bytes("format", b"some format name")
201
 
        # The format does not have to be known by Bazaar,
202
 
        # find_format_string just retrieves the name
203
 
        self.assertEqual(
204
 
            b"some format name",
205
 
            bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string(
206
 
                branch.controldir))
207
 
 
208
 
    def test_find_format(self):
209
 
        # is the right format object found for a working tree?
210
 
        # create a branch with a few known format objects.
211
 
        self.build_tree(["foo/", "bar/"])
212
 
 
213
 
        def check_format(format, url):
214
 
            dir = format._matchingcontroldir.initialize(url)
215
 
            dir.create_repository()
216
 
            dir.create_branch()
217
 
            format.initialize(dir)
218
 
            found_format = bzrworkingtree.WorkingTreeFormatMetaDir.find_format(
219
 
                dir)
220
 
            self.assertIsInstance(found_format, format.__class__)
221
 
        check_format(workingtree_3.WorkingTreeFormat3(), "bar")
222
 
 
223
 
    def test_find_format_no_tree(self):
224
 
        dir = bzrdir.BzrDirMetaFormat1().initialize('.')
225
 
        self.assertRaises(errors.NoWorkingTree,
226
 
                          bzrworkingtree.WorkingTreeFormatMetaDir.find_format,
227
 
                          dir)
228
 
 
229
 
    def test_find_format_unknown_format(self):
230
 
        dir = bzrdir.BzrDirMetaFormat1().initialize('.')
231
 
        dir.create_repository()
232
 
        dir.create_branch()
233
 
        SampleTreeFormat().initialize(dir)
234
 
        self.assertRaises(errors.UnknownFormatError,
235
 
                          bzrworkingtree.WorkingTreeFormatMetaDir.find_format,
236
 
                          dir)
237
 
 
238
 
    def test_find_format_with_features(self):
239
 
        tree = self.make_branch_and_tree('.', format='2a')
240
 
        tree.update_feature_flags({b"name": b"necessity"})
241
 
        found_format = bzrworkingtree.WorkingTreeFormatMetaDir.find_format(
242
 
            tree.controldir)
243
 
        self.assertIsInstance(found_format, workingtree.WorkingTreeFormat)
244
 
        self.assertEqual(found_format.features.get(b"name"), b"necessity")
245
 
        self.assertRaises(
246
 
            bzrdir.MissingFeature, found_format.check_support_status, True)
247
 
        self.addCleanup(
248
 
            bzrworkingtree.WorkingTreeFormatMetaDir.unregister_feature,
249
 
            b"name")
250
 
        bzrworkingtree.WorkingTreeFormatMetaDir.register_feature(b"name")
251
 
        found_format.check_support_status(True)
252
 
 
253
 
 
254
 
class TestWorkingTreeIterEntriesByDir_wSubtrees(TestCaseWithTransport):
255
 
 
256
 
    def make_simple_tree(self):
257
 
        tree = self.make_branch_and_tree('tree', format='development-subtree')
258
 
        self.build_tree(['tree/a/', 'tree/a/b/', 'tree/a/b/c'])
259
 
        tree.set_root_id(b'root-id')
260
 
        tree.add(['a', 'a/b', 'a/b/c'], [b'a-id', b'b-id', b'c-id'])
261
 
        tree.commit('initial')
262
 
        return tree
263
 
 
264
 
    def test_just_directory(self):
265
 
        tree = self.make_simple_tree()
266
 
        self.assertEqual([('directory', b'root-id'),
267
 
                          ('directory', b'a-id'),
268
 
                          ('directory', b'b-id'),
269
 
                          ('file', b'c-id')],
270
 
                         [(ie.kind, ie.file_id)
271
 
                          for path, ie in tree.iter_entries_by_dir()])
272
 
        self.make_branch_and_tree('tree/a/b')
273
 
        self.assertEqual([('tree-reference', b'b-id')],
274
 
                         [(ie.kind, ie.file_id)
275
 
                          for path, ie in tree.iter_entries_by_dir(
276
 
                              specific_files=['a/b'])])
277
 
 
278
 
    def test_direct_subtree(self):
279
 
        tree = self.make_simple_tree()
280
 
        self.make_branch_and_tree('tree/a/b')
281
 
        self.assertEqual([('directory', b'root-id'),
282
 
                          ('directory', b'a-id'),
283
 
                          ('tree-reference', b'b-id')],
284
 
                         [(ie.kind, ie.file_id)
285
 
                          for path, ie in tree.iter_entries_by_dir()])
286
 
 
287
 
    def test_indirect_subtree(self):
288
 
        tree = self.make_simple_tree()
289
 
        self.make_branch_and_tree('tree/a')
290
 
        self.assertEqual([('directory', b'root-id'),
291
 
                          ('tree-reference', b'a-id')],
292
 
                         [(ie.kind, ie.file_id)
293
 
                          for path, ie in tree.iter_entries_by_dir()])
294
 
 
295
 
 
296
 
class TestWorkingTreeFormatRegistry(TestCase):
297
 
 
298
 
    def setUp(self):
299
 
        super(TestWorkingTreeFormatRegistry, self).setUp()
300
 
        self.registry = workingtree.WorkingTreeFormatRegistry()
301
 
 
302
 
    def test_register_unregister_format(self):
303
 
        format = SampleTreeFormat()
304
 
        self.registry.register(format)
305
 
        self.assertEqual(format, self.registry.get(b"Sample tree format."))
306
 
        self.registry.remove(format)
307
 
        self.assertRaises(KeyError, self.registry.get, b"Sample tree format.")
308
 
 
309
 
    def test_get_all(self):
310
 
        format = SampleTreeFormat()
311
 
        self.assertEqual([], self.registry._get_all())
312
 
        self.registry.register(format)
313
 
        self.assertEqual([format], self.registry._get_all())
314
 
 
315
 
    def test_register_extra(self):
316
 
        format = SampleExtraTreeFormat()
317
 
        self.assertEqual([], self.registry._get_all())
318
 
        self.registry.register_extra(format)
319
 
        self.assertEqual([format], self.registry._get_all())
320
 
 
321
 
    def test_register_extra_lazy(self):
322
 
        self.assertEqual([], self.registry._get_all())
323
 
        self.registry.register_extra_lazy("breezy.tests.test_workingtree",
324
 
                                          "SampleExtraTreeFormat")
325
 
        formats = self.registry._get_all()
326
 
        self.assertEqual(1, len(formats))
327
 
        self.assertIsInstance(formats[0], SampleExtraTreeFormat)
328
 
 
329
 
 
330
 
class TestWorkingTreeFormat3(TestCaseWithTransport):
331
 
    """Tests specific to WorkingTreeFormat3."""
332
 
 
333
 
    def test_disk_layout(self):
334
 
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
335
 
        control.create_repository()
336
 
        control.create_branch()
337
 
        workingtree_3.WorkingTreeFormat3().initialize(control)
338
 
        # we want:
339
 
        # format 'Bazaar-NG Working Tree format 3'
340
 
        # inventory = blank inventory
341
 
        # pending-merges = ''
342
 
        # stat-cache = ??
343
 
        # no inventory.basis yet
344
 
        t = control.get_workingtree_transport(None)
345
 
        self.assertEqualDiff(b'Bazaar-NG Working Tree format 3',
346
 
                             t.get('format').read())
347
 
        self.assertEqualDiff(t.get('inventory').read(),
348
 
                             b'<inventory format="5">\n'
349
 
                             b'</inventory>\n',
350
 
                             )
351
 
        self.assertEqualDiff(b'### bzr hashcache v5\n',
352
 
                             t.get('stat-cache').read())
353
 
        self.assertFalse(t.has('inventory.basis'))
354
 
        # no last-revision file means 'None' or 'NULLREVISION'
355
 
        self.assertFalse(t.has('last-revision'))
356
 
        # TODO RBC 20060210 do a commit, check the inventory.basis is created
357
 
        # correctly and last-revision file becomes present.
358
 
 
359
 
    def test_uses_lockdir(self):
360
 
        """WorkingTreeFormat3 uses its own LockDir:
361
 
 
362
 
            - lock is a directory
363
 
            - when the WorkingTree is locked, LockDir can see that
364
 
        """
365
 
        t = self.get_transport()
366
 
        url = self.get_url()
367
 
        dir = bzrdir.BzrDirMetaFormat1().initialize(url)
368
 
        dir.create_repository()
369
 
        dir.create_branch()
370
 
        try:
371
 
            tree = workingtree_3.WorkingTreeFormat3().initialize(dir)
372
 
        except errors.NotLocalUrl:
373
 
            raise TestSkipped('Not a local URL')
374
 
        self.assertIsDirectory('.bzr', t)
375
 
        self.assertIsDirectory('.bzr/checkout', t)
376
 
        self.assertIsDirectory('.bzr/checkout/lock', t)
377
 
        our_lock = LockDir(t, '.bzr/checkout/lock')
378
 
        self.assertEqual(our_lock.peek(), None)
379
 
        with tree.lock_write():
380
 
            self.assertTrue(our_lock.peek())
381
 
        self.assertEqual(our_lock.peek(), None)
382
 
 
383
 
    def test_missing_pending_merges(self):
384
 
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
385
 
        control.create_repository()
386
 
        control.create_branch()
387
 
        tree = workingtree_3.WorkingTreeFormat3().initialize(control)
388
 
        tree._transport.delete("pending-merges")
389
 
        self.assertEqual([], tree.get_parent_ids())
390
 
 
391
 
 
392
 
class TestRevert(TestCaseWithTransport):
393
 
 
394
 
    def test_revert_conflicts_recursive(self):
395
 
        this_tree = self.make_branch_and_tree('this-tree')
396
 
        self.build_tree_contents([('this-tree/foo/',),
397
 
                                  ('this-tree/foo/bar', b'bar')])
398
 
        this_tree.add(['foo', 'foo/bar'])
399
 
        this_tree.commit('created foo/bar')
400
 
        other_tree = this_tree.controldir.sprout(
401
 
            'other-tree').open_workingtree()
402
 
        self.build_tree_contents([('other-tree/foo/bar', b'baz')])
403
 
        other_tree.commit('changed bar')
404
 
        self.build_tree_contents([('this-tree/foo/bar', b'qux')])
405
 
        this_tree.commit('changed qux')
406
 
        this_tree.merge_from_branch(other_tree.branch)
407
 
        self.assertEqual(1, len(this_tree.conflicts()))
408
 
        this_tree.revert(['foo'])
409
 
        self.assertEqual(0, len(this_tree.conflicts()))
410
 
 
411
 
 
412
 
class TestAutoResolve(TestCaseWithTransport):
413
 
 
414
 
    def _auto_resolve(self, tree):
415
 
        """Call auto_resolve on tree expecting deprecation"""
416
 
        return self.applyDeprecated(
417
 
            symbol_versioning.deprecated_in((3, 0, 1)),
418
 
            tree.auto_resolve,)
419
 
 
420
 
    def test_auto_resolve(self):
421
 
        base = self.make_branch_and_tree('base')
422
 
        self.build_tree_contents([('base/hello', b'Hello')])
423
 
        base.add('hello', b'hello_id')
424
 
        base.commit('Hello')
425
 
        other = base.controldir.sprout('other').open_workingtree()
426
 
        self.build_tree_contents([('other/hello', b'hELLO')])
427
 
        other.commit('Case switch')
428
 
        this = base.controldir.sprout('this').open_workingtree()
429
 
        self.assertPathExists('this/hello')
430
 
        self.build_tree_contents([('this/hello', b'Hello World')])
431
 
        this.commit('Add World')
432
 
        this.merge_from_branch(other.branch)
433
 
        self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
434
 
                         this.conflicts())
435
 
        self._auto_resolve(this)
436
 
        self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
437
 
                         this.conflicts())
438
 
        self.build_tree_contents([('this/hello', '<<<<<<<')])
439
 
        self._auto_resolve(this)
440
 
        self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
441
 
                         this.conflicts())
442
 
        self.build_tree_contents([('this/hello', '=======')])
443
 
        self._auto_resolve(this)
444
 
        self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
445
 
                         this.conflicts())
446
 
        self.build_tree_contents([('this/hello', '\n>>>>>>>')])
447
 
        remaining, resolved = self._auto_resolve(this)
448
 
        self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
449
 
                         this.conflicts())
450
 
        self.assertEqual([], resolved)
451
 
        self.build_tree_contents([('this/hello', b'hELLO wORLD')])
452
 
        remaining, resolved = self._auto_resolve(this)
453
 
        self.assertEqual([], this.conflicts())
454
 
        self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
455
 
                         resolved)
456
 
        self.assertPathDoesNotExist('this/hello.BASE')
457
 
 
458
 
    def test_unsupported_symlink_auto_resolve(self):
459
 
        self.requireFeature(SymlinkFeature)
460
 
        base = self.make_branch_and_tree('base')
461
 
        self.build_tree_contents([('base/hello', 'Hello')])
462
 
        base.add('hello', b'hello_id')
463
 
        base.commit('commit 0')
464
 
        other = base.controldir.sprout('other').open_workingtree()
465
 
        self.build_tree_contents([('other/hello', 'Hello')])
466
 
        os.symlink('other/hello', 'other/foo')
467
 
        other.add('foo', b'foo_id')
468
 
        other.commit('commit symlink')
469
 
        this = base.controldir.sprout('this').open_workingtree()
470
 
        self.assertPathExists('this/hello')
471
 
        self.build_tree_contents([('this/hello', 'Hello')])
472
 
        this.commit('commit 2')
473
 
        log = BytesIO()
474
 
        trace.push_log_file(log)
475
 
        os_symlink = getattr(os, 'symlink', None)
476
 
        os.symlink = None
477
 
        try:
478
 
            this.merge_from_branch(other.branch)
479
 
        finally:
480
 
            if os_symlink:
481
 
                os.symlink = os_symlink
482
 
        self.assertContainsRe(
483
 
            log.getvalue(),
484
 
            b'Unable to create symlink "foo" on this filesystem')
485
 
 
486
 
    def test_auto_resolve_dir(self):
487
 
        tree = self.make_branch_and_tree('tree')
488
 
        self.build_tree(['tree/hello/'])
489
 
        tree.add('hello', b'hello-id')
490
 
        file_conflict = conflicts.TextConflict('hello', b'hello-id')
491
 
        tree.set_conflicts(conflicts.ConflictList([file_conflict]))
492
 
        remaining, resolved = self._auto_resolve(tree)
493
 
        self.assertEqual(
494
 
            remaining,
495
 
            conflicts.ConflictList([conflicts.TextConflict(u'hello', 'hello-id')]))
496
 
        self.assertEqual(resolved, [])
497
 
 
498
 
    def test_auto_resolve_missing(self):
499
 
        tree = self.make_branch_and_tree('tree')
500
 
        file_conflict = conflicts.TextConflict('hello', b'hello-id')
501
 
        tree.set_conflicts(conflicts.ConflictList([file_conflict]))
502
 
        remaining, resolved = self._auto_resolve(tree)
503
 
        self.assertEqual(remaining, [])
504
 
        self.assertEqual(
505
 
            resolved,
506
 
            conflicts.ConflictList([conflicts.TextConflict(u'hello', 'hello-id')]))
507
 
 
508
 
 
509
 
class TestStoredUncommitted(TestCaseWithTransport):
510
 
 
511
 
    def store_uncommitted(self):
512
 
        tree = self.make_branch_and_tree('tree')
513
 
        tree.commit('get root in there')
514
 
        self.build_tree_contents([('tree/file', b'content')])
515
 
        tree.add('file', b'file-id')
516
 
        tree.store_uncommitted()
517
 
        return tree
518
 
 
519
 
    def test_store_uncommitted(self):
520
 
        self.store_uncommitted()
521
 
        self.assertPathDoesNotExist('tree/file')
522
 
 
523
 
    def test_store_uncommitted_no_change(self):
524
 
        tree = self.make_branch_and_tree('tree')
525
 
        tree.commit('get root in there')
526
 
        tree.store_uncommitted()
527
 
        self.assertIs(None, tree.branch.get_unshelver(tree))
528
 
 
529
 
    def test_restore_uncommitted(self):
530
 
        with write_locked(self.store_uncommitted()) as tree:
531
 
            tree.restore_uncommitted()
532
 
            self.assertPathExists('tree/file')
533
 
            self.assertIs(None, tree.branch.get_unshelver(tree))
534
 
 
535
 
    def test_restore_uncommitted_none(self):
536
 
        tree = self.make_branch_and_tree('tree')
537
 
        tree.restore_uncommitted()
 
50
class TestWorkingTree(TestCaseInTempDir):
 
51
 
 
52
    def test_listfiles(self):
 
53
        branch = Branch.initialize('.')
 
54
        os.mkdir('dir')
 
55
        print >> open('file', 'w'), "content"
 
56
        os.symlink('target', 'symlink')
 
57
        tree = branch.working_tree()
 
58
        files = list(tree.list_files())
 
59
        self.assertEqual(files[0], ('dir', '?', 'directory', None, TreeDirectory()))
 
60
        self.assertEqual(files[1], ('file', '?', 'file', None, TreeFile()))
 
61
        self.assertEqual(files[2], ('symlink', '?', 'symlink', None, TreeLink()))
 
62
 
 
63
    def test_construct_with_branch(self):
 
64
        branch = Branch.initialize('.')
 
65
        tree = WorkingTree(branch.base, branch)
 
66
        self.assertEqual(branch, tree.branch)
 
67
        self.assertEqual(branch.base, tree.basedir)
 
68
    
 
69
    def test_construct_without_branch(self):
 
70
        branch = Branch.initialize('.')
 
71
        tree = WorkingTree(branch.base)
 
72
        self.assertEqual(branch.base, tree.branch.base)
 
73
        self.assertEqual(branch.base, tree.basedir)
 
74
 
 
75
    def test_basic_relpath(self):
 
76
        # for comprehensive relpath tests, see whitebox.py.
 
77
        branch = Branch.initialize('.')
 
78
        tree = WorkingTree(branch.base)
 
79
        self.assertEqual('child',
 
80
                         tree.relpath(os.path.join(os.getcwd(), 'child')))
 
81
 
 
82
    def test_lock_locks_branch(self):
 
83
        branch = Branch.initialize('.')
 
84
        tree = WorkingTree(branch.base)
 
85
        tree.lock_read()
 
86
        self.assertEqual(1, tree.branch._lock_count)
 
87
        self.assertEqual('r', tree.branch._lock_mode)
 
88
        tree.unlock()
 
89
        self.assertEqual(None, tree.branch._lock_count)
 
90
        tree.lock_write()
 
91
        self.assertEqual(1, tree.branch._lock_count)
 
92
        self.assertEqual('w', tree.branch._lock_mode)
 
93
        tree.unlock()
 
94
        self.assertEqual(None, tree.branch._lock_count)
 
95
 
 
96
    def get_pullable_branches(self):
 
97
        self.build_tree(['from/', 'from/file', 'to/'])
 
98
        br_a = Branch.initialize('from')
 
99
        br_a.add('file')
 
100
        br_a.working_tree().commit('foo', rev_id='A')
 
101
        br_b = Branch.initialize('to')
 
102
        return br_a, br_b
 
103
 
 
104
    def test_pull(self):
 
105
        br_a, br_b = self.get_pullable_branches()
 
106
        br_b.working_tree().pull(br_a)
 
107
        self.failUnless(br_b.has_revision('A'))
 
108
        self.assertEqual(['A'], br_b.revision_history())
 
109
 
 
110
    def test_pull_overwrites(self):
 
111
        br_a, br_b = self.get_pullable_branches()
 
112
        br_b.working_tree().commit('foo', rev_id='B')
 
113
        self.assertEqual(['B'], br_b.revision_history())
 
114
        br_b.working_tree().pull(br_a, overwrite=True)
 
115
        self.failUnless(br_b.has_revision('A'))
 
116
        self.failUnless(br_b.has_revision('B'))
 
117
        self.assertEqual(['A'], br_b.revision_history())
 
118
 
 
119
    def test_revert(self):
 
120
        """Test selected-file revert"""
 
121
        b = Branch.initialize('.')
 
122
 
 
123
        self.build_tree(['hello.txt'])
 
124
        file('hello.txt', 'w').write('initial hello')
 
125
 
 
126
        self.assertRaises(NotVersionedError,
 
127
                          b.working_tree().revert, ['hello.txt'])
 
128
        
 
129
        b.add(['hello.txt'])
 
130
        b.working_tree().commit('create initial hello.txt')
 
131
 
 
132
        self.check_file_contents('hello.txt', 'initial hello')
 
133
        file('hello.txt', 'w').write('new hello')
 
134
        self.check_file_contents('hello.txt', 'new hello')
 
135
 
 
136
        wt = b.working_tree()
 
137
 
 
138
        # revert file modified since last revision
 
139
        wt.revert(['hello.txt'])
 
140
        self.check_file_contents('hello.txt', 'initial hello')
 
141
        self.check_file_contents('hello.txt~', 'new hello')
 
142
 
 
143
        # reverting again does not clobber the backup
 
144
        wt.revert(['hello.txt'])
 
145
        self.check_file_contents('hello.txt', 'initial hello')
 
146
        self.check_file_contents('hello.txt~', 'new hello')