/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
1
# (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
from cStringIO import StringIO
19
import os
20
21
import bzrlib
1508.1.25 by Robert Collins
Update per review comments.
22
import bzrlib.branch
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
23
from bzrlib.branch import Branch
24
import bzrlib.bzrdir as bzrdir
25
from bzrlib.bzrdir import BzrDir
26
import bzrlib.errors as errors
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
27
from bzrlib.errors import (NotBranchError, NotVersionedError, 
28
                           UnsupportedOperation)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
29
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
1534.5.5 by Robert Collins
Move is_control_file into WorkingTree.is_control_filename and test.
30
from bzrlib.tests import TestSkipped
31
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
32
from bzrlib.trace import mutter
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
33
import bzrlib.urlutils as urlutils
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
34
import bzrlib.workingtree as workingtree
35
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
36
                                WorkingTree)
37
38
39
class TestWorkingTree(TestCaseWithWorkingTree):
40
1732.1.8 by John Arbash Meinel
Adding a test for list_files
41
    def test_list_files(self):
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
42
        tree = self.make_branch_and_tree('.')
1732.1.8 by John Arbash Meinel
Adding a test for list_files
43
        self.build_tree(['dir/', 'file'])
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
44
        if has_symlinks():
45
            os.symlink('target', 'symlink')
46
        files = list(tree.list_files())
47
        self.assertEqual(files[0], ('dir', '?', 'directory', None, TreeDirectory()))
48
        self.assertEqual(files[1], ('file', '?', 'file', None, TreeFile()))
49
        if has_symlinks():
50
            self.assertEqual(files[2], ('symlink', '?', 'symlink', None, TreeLink()))
51
1732.1.8 by John Arbash Meinel
Adding a test for list_files
52
    def test_list_files_sorted(self):
53
        tree = self.make_branch_and_tree('.')
1732.1.22 by John Arbash Meinel
Bug in list_files if the last entry in a directory is another directory
54
        self.build_tree(['dir/', 'file', 'dir/file', 'dir/b', 'dir/subdir/', 'a', 'dir/subfile',
55
                'zz_dir/', 'zz_dir/subfile'])
1732.1.8 by John Arbash Meinel
Adding a test for list_files
56
        files = [(path, kind) for (path, versioned, kind, file_id, entry) in tree.list_files()]
57
        self.assertEqual([
58
            ('a', 'file'),
59
            ('dir', 'directory'),
60
            ('file', 'file'),
1732.1.25 by John Arbash Meinel
Fix list_files test, we don't need to check if children are empty if we fall off the loop.
61
            ('zz_dir', 'directory'),
1732.1.8 by John Arbash Meinel
Adding a test for list_files
62
            ], files)
63
1732.1.25 by John Arbash Meinel
Fix list_files test, we don't need to check if children are empty if we fall off the loop.
64
        tree.add(['dir', 'zz_dir'])
1732.1.8 by John Arbash Meinel
Adding a test for list_files
65
        files = [(path, kind) for (path, versioned, kind, file_id, entry) in tree.list_files()]
66
        self.assertEqual([
67
            ('a', 'file'),
68
            ('dir', 'directory'),
69
            ('dir/b', 'file'),
70
            ('dir/file', 'file'),
71
            ('dir/subdir', 'directory'),
72
            ('dir/subfile', 'file'),
73
            ('file', 'file'),
1732.1.22 by John Arbash Meinel
Bug in list_files if the last entry in a directory is another directory
74
            ('zz_dir', 'directory'),
75
            ('zz_dir/subfile', 'file'),
1732.1.8 by John Arbash Meinel
Adding a test for list_files
76
            ], files)
77
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
78
    def test_open_containing(self):
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
79
        branch = self.make_branch_and_tree('.').branch
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
80
        wt, relpath = WorkingTree.open_containing()
81
        self.assertEqual('', relpath)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
82
        self.assertEqual(wt.basedir + '/', urlutils.local_path_from_url(branch.base))
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
83
        wt, relpath = WorkingTree.open_containing(u'.')
84
        self.assertEqual('', relpath)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
85
        self.assertEqual(wt.basedir + '/', urlutils.local_path_from_url(branch.base))
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
86
        wt, relpath = WorkingTree.open_containing('./foo')
87
        self.assertEqual('foo', relpath)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
88
        self.assertEqual(wt.basedir + '/', urlutils.local_path_from_url(branch.base))
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
89
        wt, relpath = WorkingTree.open_containing('file://' + getcwd() + '/foo')
90
        self.assertEqual('foo', relpath)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
91
        self.assertEqual(wt.basedir + '/', urlutils.local_path_from_url(branch.base))
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
92
93
    def test_basic_relpath(self):
94
        # for comprehensive relpath tests, see whitebox.py.
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
95
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
96
        self.assertEqual('child',
97
                         tree.relpath(pathjoin(getcwd(), 'child')))
98
99
    def test_lock_locks_branch(self):
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
100
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
101
        tree.lock_read()
102
        self.assertEqual('r', tree.branch.peek_lock_mode())
103
        tree.unlock()
104
        self.assertEqual(None, tree.branch.peek_lock_mode())
105
        tree.lock_write()
106
        self.assertEqual('w', tree.branch.peek_lock_mode())
107
        tree.unlock()
108
        self.assertEqual(None, tree.branch.peek_lock_mode())
109
 
110
    def test_revert(self):
111
        """Test selected-file revert"""
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
112
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
113
114
        self.build_tree(['hello.txt'])
115
        file('hello.txt', 'w').write('initial hello')
116
117
        self.assertRaises(NotVersionedError,
118
                          tree.revert, ['hello.txt'])
119
        tree.add(['hello.txt'])
120
        tree.commit('create initial hello.txt')
121
122
        self.check_file_contents('hello.txt', 'initial hello')
123
        file('hello.txt', 'w').write('new hello')
124
        self.check_file_contents('hello.txt', 'new hello')
125
126
        # revert file modified since last revision
127
        tree.revert(['hello.txt'])
128
        self.check_file_contents('hello.txt', 'initial hello')
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
129
        self.check_file_contents('hello.txt.~1~', 'new hello')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
130
131
        # reverting again does not clobber the backup
132
        tree.revert(['hello.txt'])
133
        self.check_file_contents('hello.txt', 'initial hello')
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
134
        self.check_file_contents('hello.txt.~1~', 'new hello')
1534.10.28 by Aaron Bentley
Use numbered backup files
135
        
136
        # backup files are numbered
137
        file('hello.txt', 'w').write('new hello2')
138
        tree.revert(['hello.txt'])
139
        self.check_file_contents('hello.txt', 'initial hello')
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
140
        self.check_file_contents('hello.txt.~1~', 'new hello')
141
        self.check_file_contents('hello.txt.~2~', 'new hello2')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
142
1558.12.7 by Aaron Bentley
Fixed revert with missing files
143
    def test_revert_missing(self):
144
        # Revert a file that has been deleted since last commit
145
        tree = self.make_branch_and_tree('.')
146
        file('hello.txt', 'w').write('initial hello')
147
        tree.add('hello.txt')
148
        tree.commit('added hello.txt')
149
        os.unlink('hello.txt')
150
        tree.remove('hello.txt')
151
        tree.revert(['hello.txt'])
152
        self.failUnlessExists('hello.txt')
153
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
154
    def test_unknowns(self):
155
        tree = self.make_branch_and_tree('.')
156
        self.build_tree(['hello.txt',
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
157
                         'hello.txt.~1~'])
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
158
        self.assertEquals(list(tree.unknowns()),
159
                          ['hello.txt'])
160
161
    def test_hashcache(self):
162
        from bzrlib.tests.test_hashcache import pause
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
163
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
164
        self.build_tree(['hello.txt',
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
165
                         'hello.txt.~1~'])
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
166
        tree.add('hello.txt')
167
        pause()
168
        sha = tree.get_file_sha1(tree.path2id('hello.txt'))
169
        self.assertEqual(1, tree._hashcache.miss_count)
1534.5.3 by Robert Collins
Make format 4/5/6 branches share a single LockableFiles instance across wt/branch/repository.
170
        tree2 = WorkingTree.open('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
171
        sha2 = tree2.get_file_sha1(tree2.path2id('hello.txt'))
172
        self.assertEqual(0, tree2._hashcache.miss_count)
173
        self.assertEqual(1, tree2._hashcache.hit_count)
174
175
    def test_initialize(self):
176
        # initialize should create a working tree and branch in an existing dir
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
177
        t = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
178
        b = Branch.open('.')
179
        self.assertEqual(t.branch.base, b.base)
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
180
        t2 = WorkingTree.open('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
181
        self.assertEqual(t.basedir, t2.basedir)
182
        self.assertEqual(b.base, t2.branch.base)
183
        # TODO maybe we should check the branch format? not sure if its
184
        # appropriate here.
185
186
    def test_rename_dirs(self):
187
        """Test renaming directories and the files within them."""
188
        wt = self.make_branch_and_tree('.')
189
        b = wt.branch
190
        self.build_tree(['dir/', 'dir/sub/', 'dir/sub/file'])
191
        wt.add(['dir', 'dir/sub', 'dir/sub/file'])
192
193
        wt.commit('create initial state')
194
195
        revid = b.revision_history()[0]
196
        self.log('first revision_id is {%s}' % revid)
197
        
198
        inv = b.repository.get_revision_inventory(revid)
199
        self.log('contents of inventory: %r' % inv.entries())
200
201
        self.check_inventory_shape(inv,
202
                                   ['dir', 'dir/sub', 'dir/sub/file'])
203
204
        wt.rename_one('dir', 'newdir')
205
206
        self.check_inventory_shape(wt.read_working_inventory(),
207
                                   ['newdir', 'newdir/sub', 'newdir/sub/file'])
208
209
        wt.rename_one('newdir/sub', 'newdir/newsub')
210
        self.check_inventory_shape(wt.read_working_inventory(),
211
                                   ['newdir', 'newdir/newsub',
212
                                    'newdir/newsub/file'])
213
214
    def test_add_in_unversioned(self):
215
        """Try to add a file in an unversioned directory.
216
217
        "bzr add" adds the parent as necessary, but simple working tree add
218
        doesn't do that.
219
        """
220
        from bzrlib.errors import NotVersionedError
221
        wt = self.make_branch_and_tree('.')
222
        self.build_tree(['foo/',
223
                         'foo/hello'])
224
        self.assertRaises(NotVersionedError,
225
                          wt.add,
226
                          'foo/hello')
227
228
    def test_add_missing(self):
229
        # adding a msising file -> NoSuchFile
230
        wt = self.make_branch_and_tree('.')
231
        self.assertRaises(errors.NoSuchFile, wt.add, 'fpp')
232
233
    def test_remove_verbose(self):
234
        #FIXME the remove api should not print or otherwise depend on the
235
        # text UI - RBC 20060124
236
        wt = self.make_branch_and_tree('.')
237
        self.build_tree(['hello'])
238
        wt.add(['hello'])
239
        wt.commit(message='add hello')
240
        stdout = StringIO()
241
        stderr = StringIO()
242
        self.assertEqual(None, self.apply_redirected(None, stdout, stderr,
243
                                                     wt.remove,
244
                                                     ['hello'],
245
                                                     verbose=True))
246
        self.assertEqual('?       hello\n', stdout.getvalue())
247
        self.assertEqual('', stderr.getvalue())
248
249
    def test_clone_trivial(self):
250
        wt = self.make_branch_and_tree('source')
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
251
        cloned_dir = wt.bzrdir.clone('target')
252
        cloned = cloned_dir.open_workingtree()
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
253
        self.assertEqual(cloned.last_revision(), wt.last_revision())
254
255
    def test_last_revision(self):
256
        wt = self.make_branch_and_tree('source')
257
        self.assertEqual(None, wt.last_revision())
258
        wt.commit('A', allow_pointless=True, rev_id='A')
259
        self.assertEqual('A', wt.last_revision())
260
261
    def test_set_last_revision(self):
262
        wt = self.make_branch_and_tree('source')
263
        self.assertEqual(None, wt.last_revision())
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
264
        # cannot set the last revision to one not in the branch history.
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
265
        self.assertRaises(errors.NoSuchRevision, wt.set_last_revision, 'A')
266
        wt.commit('A', allow_pointless=True, rev_id='A')
267
        self.assertEqual('A', wt.last_revision())
268
        # None is aways in the branch
269
        wt.set_last_revision(None)
270
        self.assertEqual(None, wt.last_revision())
271
        # and now we can set it to 'A'
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
272
        # because some formats mutate the branch to set it on the tree
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
273
        # we need to alter the branch to let this pass.
274
        wt.branch.set_revision_history(['A', 'B'])
275
        wt.set_last_revision('A')
276
        self.assertEqual('A', wt.last_revision())
277
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
278
    def test_set_last_revision_different_to_branch(self):
279
        # working tree formats from the meta-dir format and newer support
280
        # setting the last revision on a tree independently of that on the 
281
        # branch. Its concievable that some future formats may want to 
282
        # couple them again (i.e. because its really a smart server and
283
        # the working tree will always match the branch). So we test
284
        # that formats where initialising a branch does not initialise a 
285
        # tree - and thus have separable entities - support skewing the 
286
        # two things.
287
        branch = self.make_branch('tree')
288
        try:
289
            # if there is a working tree now, this is not supported.
290
            branch.bzrdir.open_workingtree()
291
            return
292
        except errors.NoWorkingTree:
293
            pass
294
        wt = branch.bzrdir.create_workingtree()
295
        wt.commit('A', allow_pointless=True, rev_id='A')
296
        wt.set_last_revision(None)
297
        self.assertEqual(None, wt.last_revision())
298
        self.assertEqual('A', wt.branch.last_revision())
299
        # and now we can set it back to 'A'
300
        wt.set_last_revision('A')
301
        self.assertEqual('A', wt.last_revision())
302
        self.assertEqual('A', wt.branch.last_revision())
303
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
304
    def test_clone_and_commit_preserves_last_revision(self):
305
        wt = self.make_branch_and_tree('source')
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
306
        cloned_dir = wt.bzrdir.clone('target')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
307
        wt.commit('A', allow_pointless=True, rev_id='A')
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
308
        self.assertNotEqual(cloned_dir.open_workingtree().last_revision(),
309
                            wt.last_revision())
310
311
    def test_clone_preserves_content(self):
312
        wt = self.make_branch_and_tree('source')
313
        self.build_tree(['added', 'deleted', 'notadded'], transport=wt.bzrdir.transport.clone('..'))
314
        wt.add('deleted', 'deleted')
315
        wt.commit('add deleted')
316
        wt.remove('deleted')
317
        wt.add('added', 'added')
318
        cloned_dir = wt.bzrdir.clone('target')
319
        cloned = cloned_dir.open_workingtree()
320
        cloned_transport = cloned.bzrdir.transport.clone('..')
321
        self.assertFalse(cloned_transport.has('deleted'))
322
        self.assertTrue(cloned_transport.has('added'))
323
        self.assertFalse(cloned_transport.has('notadded'))
324
        self.assertEqual('added', cloned.path2id('added'))
325
        self.assertEqual(None, cloned.path2id('deleted'))
326
        self.assertEqual(None, cloned.path2id('notadded'))
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
327
        
328
    def test_basis_tree_returns_last_revision(self):
329
        wt = self.make_branch_and_tree('.')
330
        self.build_tree(['foo'])
331
        wt.add('foo', 'foo-id')
332
        wt.commit('A', rev_id='A')
333
        wt.rename_one('foo', 'bar')
334
        wt.commit('B', rev_id='B')
335
        wt.set_last_revision('B')
336
        tree = wt.basis_tree()
337
        self.failUnless(tree.has_filename('bar'))
338
        wt.set_last_revision('A')
339
        tree = wt.basis_tree()
340
        self.failUnless(tree.has_filename('foo'))
341
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
342
    def test_clone_tree_revision(self):
343
        # make a tree with a last-revision,
344
        # and clone it with a different last-revision, this should switch
345
        # do it.
346
        #
347
        # also test that the content is merged
348
        # and conflicts recorded.
349
        # This should merge between the trees - local edits should be preserved
350
        # but other changes occured.
351
        # we test this by having one file that does
352
        # not change between two revisions, and another that does -
353
        # if the changed one is not changed, fail,
354
        # if the one that did not change has lost a local change, fail.
355
        # 
356
        raise TestSkipped('revision limiting is not implemented yet.')
1508.1.21 by Robert Collins
Implement -r limit for checkout command.
357
358
    def test_initialize_with_revision_id(self):
359
        # a bzrdir can construct a working tree for itself @ a specific revision.
360
        source = self.make_branch_and_tree('source')
361
        source.commit('a', rev_id='a', allow_pointless=True)
362
        source.commit('b', rev_id='b', allow_pointless=True)
363
        self.build_tree(['new/'])
364
        made_control = self.bzrdir_format.initialize('new')
365
        source.branch.repository.clone(made_control)
366
        source.branch.clone(made_control)
367
        made_tree = self.workingtree_format.initialize(made_control, revision_id='a')
368
        self.assertEqual('a', made_tree.last_revision())
1508.1.23 by Robert Collins
Test that the working tree last revision is indeed set during commit.
369
1508.1.24 by Robert Collins
Add update command for use with checkouts.
370
    def test_update_sets_last_revision(self):
371
        # working tree formats from the meta-dir format and newer support
372
        # setting the last revision on a tree independently of that on the 
373
        # branch. Its concievable that some future formats may want to 
374
        # couple them again (i.e. because its really a smart server and
375
        # the working tree will always match the branch). So we test
376
        # that formats where initialising a branch does not initialise a 
377
        # tree - and thus have separable entities - support skewing the 
378
        # two things.
379
        main_branch = self.make_branch('tree')
380
        try:
381
            # if there is a working tree now, this is not supported.
382
            main_branch.bzrdir.open_workingtree()
383
            return
384
        except errors.NoWorkingTree:
385
            pass
386
        wt = main_branch.bzrdir.create_workingtree()
387
        # create an out of date working tree by making a checkout in this
388
        # current format
389
        self.build_tree(['checkout/', 'tree/file'])
390
        checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
1508.1.25 by Robert Collins
Update per review comments.
391
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, main_branch)
1508.1.24 by Robert Collins
Add update command for use with checkouts.
392
        old_tree = self.workingtree_format.initialize(checkout)
393
        # now commit to 'tree'
394
        wt.add('file')
395
        wt.commit('A', rev_id='A')
396
        # and update old_tree
397
        self.assertEqual(0, old_tree.update())
398
        self.failUnlessExists('checkout/file')
399
        self.assertEqual('A', old_tree.last_revision())
400
401
    def test_update_returns_conflict_count(self):
402
        # working tree formats from the meta-dir format and newer support
403
        # setting the last revision on a tree independently of that on the 
404
        # branch. Its concievable that some future formats may want to 
405
        # couple them again (i.e. because its really a smart server and
406
        # the working tree will always match the branch). So we test
407
        # that formats where initialising a branch does not initialise a 
408
        # tree - and thus have separable entities - support skewing the 
409
        # two things.
410
        main_branch = self.make_branch('tree')
411
        try:
412
            # if there is a working tree now, this is not supported.
413
            main_branch.bzrdir.open_workingtree()
414
            return
415
        except errors.NoWorkingTree:
416
            pass
417
        wt = main_branch.bzrdir.create_workingtree()
418
        # create an out of date working tree by making a checkout in this
419
        # current format
420
        self.build_tree(['checkout/', 'tree/file'])
421
        checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
1508.1.25 by Robert Collins
Update per review comments.
422
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, main_branch)
1508.1.24 by Robert Collins
Add update command for use with checkouts.
423
        old_tree = self.workingtree_format.initialize(checkout)
424
        # now commit to 'tree'
425
        wt.add('file')
426
        wt.commit('A', rev_id='A')
427
        # and add a file file to the checkout
428
        self.build_tree(['checkout/file'])
429
        old_tree.add('file')
430
        # and update old_tree
431
        self.assertEqual(1, old_tree.update())
432
        self.assertEqual('A', old_tree.last_revision())
433
1534.7.199 by Aaron Bentley
Moved merge/revert tests into test_workingtree.py
434
    def test_merge_revert(self):
435
        from bzrlib.merge import merge_inner
436
        this = self.make_branch_and_tree('b1')
437
        open('b1/a', 'wb').write('a test\n')
438
        this.add('a')
439
        open('b1/b', 'wb').write('b test\n')
440
        this.add('b')
441
        this.commit(message='')
442
        base = this.bzrdir.clone('b2').open_workingtree()
443
        open('b2/a', 'wb').write('b test\n')
444
        other = this.bzrdir.clone('b3').open_workingtree()
445
        open('b3/a', 'wb').write('c test\n')
446
        open('b3/c', 'wb').write('c test\n')
447
        other.add('c')
448
449
        open('b1/b', 'wb').write('q test\n')
450
        open('b1/d', 'wb').write('d test\n')
451
        merge_inner(this.branch, other, base, this_tree=this)
452
        self.assertNotEqual(open('b1/a', 'rb').read(), 'a test\n')
453
        this.revert([])
454
        self.assertEqual(open('b1/a', 'rb').read(), 'a test\n')
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
455
        self.assertIs(os.path.exists('b1/b.~1~'), True)
1534.7.199 by Aaron Bentley
Moved merge/revert tests into test_workingtree.py
456
        self.assertIs(os.path.exists('b1/c'), False)
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
457
        self.assertIs(os.path.exists('b1/a.~1~'), False)
1534.7.199 by Aaron Bentley
Moved merge/revert tests into test_workingtree.py
458
        self.assertIs(os.path.exists('b1/d'), True)
1534.7.200 by Aaron Bentley
Merge from mainline
459
1587.1.10 by Robert Collins
update updates working tree and branch together.
460
    def test_update_updates_bound_branch_no_local_commits(self):
461
        # doing an update in a tree updates the branch its bound to too.
462
        master_tree = self.make_branch_and_tree('master')
463
        tree = self.make_branch_and_tree('tree')
464
        try:
465
            tree.branch.bind(master_tree.branch)
466
        except errors.UpgradeRequired:
467
            # legacy branches cannot bind
468
            return
469
        master_tree.commit('foo', rev_id='foo', allow_pointless=True)
470
        tree.update()
471
        self.assertEqual('foo', tree.last_revision())
472
        self.assertEqual('foo', tree.branch.last_revision())
1587.1.11 by Robert Collins
Local commits appear to be working properly.
473
474
    def test_update_turns_local_commit_into_merge(self):
475
        # doing an update with a few local commits and no master commits
1587.1.13 by Robert Collins
Explain why update pivots more clearly in the relevant test.
476
        # makes pending-merges. 
477
        # this is done so that 'bzr update; bzr revert' will always produce
478
        # an exact copy of the 'logical branch' - the referenced branch for
479
        # a checkout, and the master for a bound branch.
480
        # its possible that we should instead have 'bzr update' when there
481
        # is nothing new on the master leave the current commits intact and
482
        # alter 'revert' to revert to the master always. But for now, its
483
        # good.
1587.1.11 by Robert Collins
Local commits appear to be working properly.
484
        master_tree = self.make_branch_and_tree('master')
485
        tree = self.make_branch_and_tree('tree')
486
        try:
487
            tree.branch.bind(master_tree.branch)
488
        except errors.UpgradeRequired:
489
            # legacy branches cannot bind
490
            return
491
        tree.commit('foo', rev_id='foo', allow_pointless=True, local=True)
492
        tree.commit('bar', rev_id='bar', allow_pointless=True, local=True)
493
        tree.update()
494
        self.assertEqual(None, tree.last_revision())
495
        self.assertEqual([], tree.branch.revision_history())
496
        self.assertEqual(['bar'], tree.pending_merges())
497
1558.3.3 by Aaron Bentley
Fix error handling for merge_modified
498
    def test_merge_modified(self):
499
        tree = self.make_branch_and_tree('master')
500
        tree._control_files.put('merge-hashes', StringIO('asdfasdf'))
501
        self.assertRaises(errors.MergeModifiedFormatError, tree.merge_modified)
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
502
1534.10.22 by Aaron Bentley
Got ConflictList implemented
503
    def test_conflicts(self):
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
504
        from bzrlib.tests.test_conflicts import example_conflicts
505
        tree = self.make_branch_and_tree('master')
506
        try:
1534.10.22 by Aaron Bentley
Got ConflictList implemented
507
            tree.set_conflicts(example_conflicts)
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
508
        except UnsupportedOperation:
1534.10.22 by Aaron Bentley
Got ConflictList implemented
509
            raise TestSkipped('set_conflicts not supported')
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
510
            
511
        tree2 = WorkingTree.open('master')
1534.10.22 by Aaron Bentley
Got ConflictList implemented
512
        self.assertEqual(tree2.conflicts(), example_conflicts)
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
513
        tree2._control_files.put('conflicts', StringIO(''))
514
        self.assertRaises(errors.ConflictFormatError, 
1534.10.22 by Aaron Bentley
Got ConflictList implemented
515
                          tree2.conflicts)
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
516
        tree2._control_files.put('conflicts', StringIO('a'))
517
        self.assertRaises(errors.ConflictFormatError, 
1534.10.22 by Aaron Bentley
Got ConflictList implemented
518
                          tree2.conflicts)
1534.10.12 by Aaron Bentley
Merge produces new conflicts
519
520
    def make_merge_conflicts(self):
521
        from bzrlib.merge import merge_inner 
522
        tree = self.make_branch_and_tree('mine')
523
        file('mine/bloo', 'wb').write('one')
524
        tree.add('bloo')
1534.10.14 by Aaron Bentley
Made revert clear conflicts
525
        file('mine/blo', 'wb').write('on')
526
        tree.add('blo')
1534.10.12 by Aaron Bentley
Merge produces new conflicts
527
        tree.commit("blah", allow_pointless=False)
528
        base = tree.basis_tree()
529
        BzrDir.open("mine").sprout("other")
530
        file('other/bloo', 'wb').write('two')
531
        othertree = WorkingTree.open('other')
532
        othertree.commit('blah', allow_pointless=False)
533
        file('mine/bloo', 'wb').write('three')
534
        tree.commit("blah", allow_pointless=False)
535
        merge_inner(tree.branch, othertree, base, this_tree=tree)
536
        return tree
537
538
    def test_merge_conflicts(self):
539
        tree = self.make_merge_conflicts()
1534.10.22 by Aaron Bentley
Got ConflictList implemented
540
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.12 by Aaron Bentley
Merge produces new conflicts
541
542
    def test_clear_merge_conflicts(self):
1534.10.22 by Aaron Bentley
Got ConflictList implemented
543
        from bzrlib.conflicts import ConflictList
1534.10.12 by Aaron Bentley
Merge produces new conflicts
544
        tree = self.make_merge_conflicts()
1534.10.22 by Aaron Bentley
Got ConflictList implemented
545
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.12 by Aaron Bentley
Merge produces new conflicts
546
        try:
1534.10.22 by Aaron Bentley
Got ConflictList implemented
547
            tree.set_conflicts(ConflictList())
1534.10.12 by Aaron Bentley
Merge produces new conflicts
548
        except UnsupportedOperation:
549
            raise TestSkipped
1534.10.22 by Aaron Bentley
Got ConflictList implemented
550
        self.assertEqual(tree.conflicts(), ConflictList())
1534.10.14 by Aaron Bentley
Made revert clear conflicts
551
552
    def test_revert_clear_conflicts(self):
553
        tree = self.make_merge_conflicts()
1534.10.22 by Aaron Bentley
Got ConflictList implemented
554
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.14 by Aaron Bentley
Made revert clear conflicts
555
        tree.revert(["blo"])
1534.10.22 by Aaron Bentley
Got ConflictList implemented
556
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.14 by Aaron Bentley
Made revert clear conflicts
557
        tree.revert(["bloo"])
1534.10.22 by Aaron Bentley
Got ConflictList implemented
558
        self.assertEqual(len(tree.conflicts()), 0)
1534.10.14 by Aaron Bentley
Made revert clear conflicts
559
560
    def test_revert_clear_conflicts2(self):
561
        tree = self.make_merge_conflicts()
1534.10.22 by Aaron Bentley
Got ConflictList implemented
562
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.14 by Aaron Bentley
Made revert clear conflicts
563
        tree.revert([])
1534.10.22 by Aaron Bentley
Got ConflictList implemented
564
        self.assertEqual(len(tree.conflicts()), 0)
1624.3.22 by Olaf Conradi
Merge bzr.dev
565
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
566
    def test_format_description(self):
567
        tree = self.make_branch_and_tree('tree')
568
        text = tree._format.get_format_description()
569
        self.failUnless(len(text))
1681.1.1 by Robert Collins
Make WorkingTree.branch a read only property. (Robert Collins)
570
571
    def test_branch_attribute_is_not_settable(self):
572
        # the branch attribute is an aspect of the working tree, not a
573
        # configurable attribute
574
        tree = self.make_branch_and_tree('tree')
575
        def set_branch():
576
            tree.branch = tree.branch
577
        self.assertRaises(AttributeError, set_branch)
578
1713.3.1 by Robert Collins
Smoke tests for tree.list_files and bzr ignored when a versioned file matches an ignore rule.
579
    def test_list_files_versioned_before_ignored(self):
580
        """A versioned file matching an ignore rule should not be ignored."""
581
        tree = self.make_branch_and_tree('.')
582
        self.build_tree(['foo.pyc'])
583
        # ensure that foo.pyc is ignored
584
        self.build_tree_contents([('.bzrignore', 'foo.pyc')])
585
        tree.add('foo.pyc', 'anid')
586
        files = sorted(list(tree.list_files()))
587
        self.assertEqual((u'.bzrignore', '?', 'file', None), files[0][:-1])
588
        self.assertEqual((u'foo.pyc', 'V', 'file', 'anid'), files[1][:-1])
589
        self.assertEqual(2, len(files))