/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~'])
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
158
        self.build_tree_contents([('.bzrignore', '*.~*\n')])
159
        tree.add('.bzrignore')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
160
        self.assertEquals(list(tree.unknowns()),
161
                          ['hello.txt'])
162
163
    def test_hashcache(self):
164
        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.
165
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
166
        self.build_tree(['hello.txt',
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
167
                         'hello.txt.~1~'])
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
168
        tree.add('hello.txt')
169
        pause()
170
        sha = tree.get_file_sha1(tree.path2id('hello.txt'))
171
        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.
172
        tree2 = WorkingTree.open('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
173
        sha2 = tree2.get_file_sha1(tree2.path2id('hello.txt'))
174
        self.assertEqual(0, tree2._hashcache.miss_count)
175
        self.assertEqual(1, tree2._hashcache.hit_count)
176
177
    def test_initialize(self):
178
        # 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.
179
        t = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
180
        b = Branch.open('.')
181
        self.assertEqual(t.branch.base, b.base)
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
182
        t2 = WorkingTree.open('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
183
        self.assertEqual(t.basedir, t2.basedir)
184
        self.assertEqual(b.base, t2.branch.base)
185
        # TODO maybe we should check the branch format? not sure if its
186
        # appropriate here.
187
188
    def test_rename_dirs(self):
189
        """Test renaming directories and the files within them."""
190
        wt = self.make_branch_and_tree('.')
191
        b = wt.branch
192
        self.build_tree(['dir/', 'dir/sub/', 'dir/sub/file'])
193
        wt.add(['dir', 'dir/sub', 'dir/sub/file'])
194
195
        wt.commit('create initial state')
196
197
        revid = b.revision_history()[0]
198
        self.log('first revision_id is {%s}' % revid)
199
        
200
        inv = b.repository.get_revision_inventory(revid)
201
        self.log('contents of inventory: %r' % inv.entries())
202
203
        self.check_inventory_shape(inv,
204
                                   ['dir', 'dir/sub', 'dir/sub/file'])
205
206
        wt.rename_one('dir', 'newdir')
207
208
        self.check_inventory_shape(wt.read_working_inventory(),
209
                                   ['newdir', 'newdir/sub', 'newdir/sub/file'])
210
211
        wt.rename_one('newdir/sub', 'newdir/newsub')
212
        self.check_inventory_shape(wt.read_working_inventory(),
213
                                   ['newdir', 'newdir/newsub',
214
                                    'newdir/newsub/file'])
215
216
    def test_add_in_unversioned(self):
217
        """Try to add a file in an unversioned directory.
218
219
        "bzr add" adds the parent as necessary, but simple working tree add
220
        doesn't do that.
221
        """
222
        from bzrlib.errors import NotVersionedError
223
        wt = self.make_branch_and_tree('.')
224
        self.build_tree(['foo/',
225
                         'foo/hello'])
226
        self.assertRaises(NotVersionedError,
227
                          wt.add,
228
                          'foo/hello')
229
230
    def test_add_missing(self):
231
        # adding a msising file -> NoSuchFile
232
        wt = self.make_branch_and_tree('.')
233
        self.assertRaises(errors.NoSuchFile, wt.add, 'fpp')
234
235
    def test_remove_verbose(self):
236
        #FIXME the remove api should not print or otherwise depend on the
237
        # text UI - RBC 20060124
238
        wt = self.make_branch_and_tree('.')
239
        self.build_tree(['hello'])
240
        wt.add(['hello'])
241
        wt.commit(message='add hello')
242
        stdout = StringIO()
243
        stderr = StringIO()
244
        self.assertEqual(None, self.apply_redirected(None, stdout, stderr,
245
                                                     wt.remove,
246
                                                     ['hello'],
247
                                                     verbose=True))
248
        self.assertEqual('?       hello\n', stdout.getvalue())
249
        self.assertEqual('', stderr.getvalue())
250
251
    def test_clone_trivial(self):
252
        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.
253
        cloned_dir = wt.bzrdir.clone('target')
254
        cloned = cloned_dir.open_workingtree()
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
255
        self.assertEqual(cloned.last_revision(), wt.last_revision())
256
257
    def test_last_revision(self):
258
        wt = self.make_branch_and_tree('source')
259
        self.assertEqual(None, wt.last_revision())
260
        wt.commit('A', allow_pointless=True, rev_id='A')
261
        self.assertEqual('A', wt.last_revision())
262
263
    def test_set_last_revision(self):
264
        wt = self.make_branch_and_tree('source')
265
        self.assertEqual(None, wt.last_revision())
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
266
        # cannot set the last revision to one not in the branch history.
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
267
        self.assertRaises(errors.NoSuchRevision, wt.set_last_revision, 'A')
268
        wt.commit('A', allow_pointless=True, rev_id='A')
269
        self.assertEqual('A', wt.last_revision())
270
        # None is aways in the branch
271
        wt.set_last_revision(None)
272
        self.assertEqual(None, wt.last_revision())
273
        # and now we can set it to 'A'
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
274
        # because some formats mutate the branch to set it on the tree
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
275
        # we need to alter the branch to let this pass.
276
        wt.branch.set_revision_history(['A', 'B'])
277
        wt.set_last_revision('A')
278
        self.assertEqual('A', wt.last_revision())
279
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
280
    def test_set_last_revision_different_to_branch(self):
281
        # working tree formats from the meta-dir format and newer support
282
        # setting the last revision on a tree independently of that on the 
283
        # branch. Its concievable that some future formats may want to 
284
        # couple them again (i.e. because its really a smart server and
285
        # the working tree will always match the branch). So we test
286
        # that formats where initialising a branch does not initialise a 
287
        # tree - and thus have separable entities - support skewing the 
288
        # two things.
289
        branch = self.make_branch('tree')
290
        try:
291
            # if there is a working tree now, this is not supported.
292
            branch.bzrdir.open_workingtree()
293
            return
294
        except errors.NoWorkingTree:
295
            pass
296
        wt = branch.bzrdir.create_workingtree()
297
        wt.commit('A', allow_pointless=True, rev_id='A')
298
        wt.set_last_revision(None)
299
        self.assertEqual(None, wt.last_revision())
300
        self.assertEqual('A', wt.branch.last_revision())
301
        # and now we can set it back to 'A'
302
        wt.set_last_revision('A')
303
        self.assertEqual('A', wt.last_revision())
304
        self.assertEqual('A', wt.branch.last_revision())
305
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
306
    def test_clone_and_commit_preserves_last_revision(self):
307
        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.
308
        cloned_dir = wt.bzrdir.clone('target')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
309
        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.
310
        self.assertNotEqual(cloned_dir.open_workingtree().last_revision(),
311
                            wt.last_revision())
312
313
    def test_clone_preserves_content(self):
314
        wt = self.make_branch_and_tree('source')
315
        self.build_tree(['added', 'deleted', 'notadded'], transport=wt.bzrdir.transport.clone('..'))
316
        wt.add('deleted', 'deleted')
317
        wt.commit('add deleted')
318
        wt.remove('deleted')
319
        wt.add('added', 'added')
320
        cloned_dir = wt.bzrdir.clone('target')
321
        cloned = cloned_dir.open_workingtree()
322
        cloned_transport = cloned.bzrdir.transport.clone('..')
323
        self.assertFalse(cloned_transport.has('deleted'))
324
        self.assertTrue(cloned_transport.has('added'))
325
        self.assertFalse(cloned_transport.has('notadded'))
326
        self.assertEqual('added', cloned.path2id('added'))
327
        self.assertEqual(None, cloned.path2id('deleted'))
328
        self.assertEqual(None, cloned.path2id('notadded'))
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
329
        
330
    def test_basis_tree_returns_last_revision(self):
331
        wt = self.make_branch_and_tree('.')
332
        self.build_tree(['foo'])
333
        wt.add('foo', 'foo-id')
334
        wt.commit('A', rev_id='A')
335
        wt.rename_one('foo', 'bar')
336
        wt.commit('B', rev_id='B')
337
        wt.set_last_revision('B')
338
        tree = wt.basis_tree()
339
        self.failUnless(tree.has_filename('bar'))
340
        wt.set_last_revision('A')
341
        tree = wt.basis_tree()
342
        self.failUnless(tree.has_filename('foo'))
343
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.
344
    def test_clone_tree_revision(self):
345
        # make a tree with a last-revision,
346
        # and clone it with a different last-revision, this should switch
347
        # do it.
348
        #
349
        # also test that the content is merged
350
        # and conflicts recorded.
351
        # This should merge between the trees - local edits should be preserved
352
        # but other changes occured.
353
        # we test this by having one file that does
354
        # not change between two revisions, and another that does -
355
        # if the changed one is not changed, fail,
356
        # if the one that did not change has lost a local change, fail.
357
        # 
358
        raise TestSkipped('revision limiting is not implemented yet.')
1508.1.21 by Robert Collins
Implement -r limit for checkout command.
359
360
    def test_initialize_with_revision_id(self):
361
        # a bzrdir can construct a working tree for itself @ a specific revision.
362
        source = self.make_branch_and_tree('source')
363
        source.commit('a', rev_id='a', allow_pointless=True)
364
        source.commit('b', rev_id='b', allow_pointless=True)
365
        self.build_tree(['new/'])
366
        made_control = self.bzrdir_format.initialize('new')
367
        source.branch.repository.clone(made_control)
368
        source.branch.clone(made_control)
369
        made_tree = self.workingtree_format.initialize(made_control, revision_id='a')
370
        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.
371
1508.1.24 by Robert Collins
Add update command for use with checkouts.
372
    def test_update_sets_last_revision(self):
373
        # working tree formats from the meta-dir format and newer support
374
        # setting the last revision on a tree independently of that on the 
375
        # branch. Its concievable that some future formats may want to 
376
        # couple them again (i.e. because its really a smart server and
377
        # the working tree will always match the branch). So we test
378
        # that formats where initialising a branch does not initialise a 
379
        # tree - and thus have separable entities - support skewing the 
380
        # two things.
381
        main_branch = self.make_branch('tree')
382
        try:
383
            # if there is a working tree now, this is not supported.
384
            main_branch.bzrdir.open_workingtree()
385
            return
386
        except errors.NoWorkingTree:
387
            pass
388
        wt = main_branch.bzrdir.create_workingtree()
389
        # create an out of date working tree by making a checkout in this
390
        # current format
391
        self.build_tree(['checkout/', 'tree/file'])
392
        checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
1508.1.25 by Robert Collins
Update per review comments.
393
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, main_branch)
1508.1.24 by Robert Collins
Add update command for use with checkouts.
394
        old_tree = self.workingtree_format.initialize(checkout)
395
        # now commit to 'tree'
396
        wt.add('file')
397
        wt.commit('A', rev_id='A')
398
        # and update old_tree
399
        self.assertEqual(0, old_tree.update())
400
        self.failUnlessExists('checkout/file')
401
        self.assertEqual('A', old_tree.last_revision())
402
403
    def test_update_returns_conflict_count(self):
404
        # working tree formats from the meta-dir format and newer support
405
        # setting the last revision on a tree independently of that on the 
406
        # branch. Its concievable that some future formats may want to 
407
        # couple them again (i.e. because its really a smart server and
408
        # the working tree will always match the branch). So we test
409
        # that formats where initialising a branch does not initialise a 
410
        # tree - and thus have separable entities - support skewing the 
411
        # two things.
412
        main_branch = self.make_branch('tree')
413
        try:
414
            # if there is a working tree now, this is not supported.
415
            main_branch.bzrdir.open_workingtree()
416
            return
417
        except errors.NoWorkingTree:
418
            pass
419
        wt = main_branch.bzrdir.create_workingtree()
420
        # create an out of date working tree by making a checkout in this
421
        # current format
422
        self.build_tree(['checkout/', 'tree/file'])
423
        checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
1508.1.25 by Robert Collins
Update per review comments.
424
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, main_branch)
1508.1.24 by Robert Collins
Add update command for use with checkouts.
425
        old_tree = self.workingtree_format.initialize(checkout)
426
        # now commit to 'tree'
427
        wt.add('file')
428
        wt.commit('A', rev_id='A')
429
        # and add a file file to the checkout
430
        self.build_tree(['checkout/file'])
431
        old_tree.add('file')
432
        # and update old_tree
433
        self.assertEqual(1, old_tree.update())
434
        self.assertEqual('A', old_tree.last_revision())
435
1534.7.199 by Aaron Bentley
Moved merge/revert tests into test_workingtree.py
436
    def test_merge_revert(self):
437
        from bzrlib.merge import merge_inner
438
        this = self.make_branch_and_tree('b1')
439
        open('b1/a', 'wb').write('a test\n')
440
        this.add('a')
441
        open('b1/b', 'wb').write('b test\n')
442
        this.add('b')
443
        this.commit(message='')
444
        base = this.bzrdir.clone('b2').open_workingtree()
445
        open('b2/a', 'wb').write('b test\n')
446
        other = this.bzrdir.clone('b3').open_workingtree()
447
        open('b3/a', 'wb').write('c test\n')
448
        open('b3/c', 'wb').write('c test\n')
449
        other.add('c')
450
451
        open('b1/b', 'wb').write('q test\n')
452
        open('b1/d', 'wb').write('d test\n')
453
        merge_inner(this.branch, other, base, this_tree=this)
454
        self.assertNotEqual(open('b1/a', 'rb').read(), 'a test\n')
455
        this.revert([])
456
        self.assertEqual(open('b1/a', 'rb').read(), 'a test\n')
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
457
        self.assertIs(os.path.exists('b1/b.~1~'), True)
1534.7.199 by Aaron Bentley
Moved merge/revert tests into test_workingtree.py
458
        self.assertIs(os.path.exists('b1/c'), False)
1534.10.29 by Aaron Bentley
Fixed backup numbering to match GNU standard better
459
        self.assertIs(os.path.exists('b1/a.~1~'), False)
1534.7.199 by Aaron Bentley
Moved merge/revert tests into test_workingtree.py
460
        self.assertIs(os.path.exists('b1/d'), True)
1534.7.200 by Aaron Bentley
Merge from mainline
461
1587.1.10 by Robert Collins
update updates working tree and branch together.
462
    def test_update_updates_bound_branch_no_local_commits(self):
463
        # doing an update in a tree updates the branch its bound to too.
464
        master_tree = self.make_branch_and_tree('master')
465
        tree = self.make_branch_and_tree('tree')
466
        try:
467
            tree.branch.bind(master_tree.branch)
468
        except errors.UpgradeRequired:
469
            # legacy branches cannot bind
470
            return
471
        master_tree.commit('foo', rev_id='foo', allow_pointless=True)
472
        tree.update()
473
        self.assertEqual('foo', tree.last_revision())
474
        self.assertEqual('foo', tree.branch.last_revision())
1587.1.11 by Robert Collins
Local commits appear to be working properly.
475
476
    def test_update_turns_local_commit_into_merge(self):
477
        # 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.
478
        # makes pending-merges. 
479
        # this is done so that 'bzr update; bzr revert' will always produce
480
        # an exact copy of the 'logical branch' - the referenced branch for
481
        # a checkout, and the master for a bound branch.
482
        # its possible that we should instead have 'bzr update' when there
483
        # is nothing new on the master leave the current commits intact and
484
        # alter 'revert' to revert to the master always. But for now, its
485
        # good.
1587.1.11 by Robert Collins
Local commits appear to be working properly.
486
        master_tree = self.make_branch_and_tree('master')
487
        tree = self.make_branch_and_tree('tree')
488
        try:
489
            tree.branch.bind(master_tree.branch)
490
        except errors.UpgradeRequired:
491
            # legacy branches cannot bind
492
            return
493
        tree.commit('foo', rev_id='foo', allow_pointless=True, local=True)
494
        tree.commit('bar', rev_id='bar', allow_pointless=True, local=True)
495
        tree.update()
496
        self.assertEqual(None, tree.last_revision())
497
        self.assertEqual([], tree.branch.revision_history())
498
        self.assertEqual(['bar'], tree.pending_merges())
499
1558.3.3 by Aaron Bentley
Fix error handling for merge_modified
500
    def test_merge_modified(self):
501
        tree = self.make_branch_and_tree('master')
502
        tree._control_files.put('merge-hashes', StringIO('asdfasdf'))
503
        self.assertRaises(errors.MergeModifiedFormatError, tree.merge_modified)
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
504
1534.10.22 by Aaron Bentley
Got ConflictList implemented
505
    def test_conflicts(self):
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
506
        from bzrlib.tests.test_conflicts import example_conflicts
507
        tree = self.make_branch_and_tree('master')
508
        try:
1534.10.22 by Aaron Bentley
Got ConflictList implemented
509
            tree.set_conflicts(example_conflicts)
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
510
        except UnsupportedOperation:
1534.10.22 by Aaron Bentley
Got ConflictList implemented
511
            raise TestSkipped('set_conflicts not supported')
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
512
            
513
        tree2 = WorkingTree.open('master')
1534.10.22 by Aaron Bentley
Got ConflictList implemented
514
        self.assertEqual(tree2.conflicts(), example_conflicts)
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
515
        tree2._control_files.put('conflicts', StringIO(''))
516
        self.assertRaises(errors.ConflictFormatError, 
1534.10.22 by Aaron Bentley
Got ConflictList implemented
517
                          tree2.conflicts)
1534.10.8 by Aaron Bentley
Implemented conflict_lines in terms of old system on WorkingTree
518
        tree2._control_files.put('conflicts', StringIO('a'))
519
        self.assertRaises(errors.ConflictFormatError, 
1534.10.22 by Aaron Bentley
Got ConflictList implemented
520
                          tree2.conflicts)
1534.10.12 by Aaron Bentley
Merge produces new conflicts
521
522
    def make_merge_conflicts(self):
523
        from bzrlib.merge import merge_inner 
524
        tree = self.make_branch_and_tree('mine')
525
        file('mine/bloo', 'wb').write('one')
526
        tree.add('bloo')
1534.10.14 by Aaron Bentley
Made revert clear conflicts
527
        file('mine/blo', 'wb').write('on')
528
        tree.add('blo')
1534.10.12 by Aaron Bentley
Merge produces new conflicts
529
        tree.commit("blah", allow_pointless=False)
530
        base = tree.basis_tree()
531
        BzrDir.open("mine").sprout("other")
532
        file('other/bloo', 'wb').write('two')
533
        othertree = WorkingTree.open('other')
534
        othertree.commit('blah', allow_pointless=False)
535
        file('mine/bloo', 'wb').write('three')
536
        tree.commit("blah", allow_pointless=False)
537
        merge_inner(tree.branch, othertree, base, this_tree=tree)
538
        return tree
539
540
    def test_merge_conflicts(self):
541
        tree = self.make_merge_conflicts()
1534.10.22 by Aaron Bentley
Got ConflictList implemented
542
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.12 by Aaron Bentley
Merge produces new conflicts
543
544
    def test_clear_merge_conflicts(self):
1534.10.22 by Aaron Bentley
Got ConflictList implemented
545
        from bzrlib.conflicts import ConflictList
1534.10.12 by Aaron Bentley
Merge produces new conflicts
546
        tree = self.make_merge_conflicts()
1534.10.22 by Aaron Bentley
Got ConflictList implemented
547
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.12 by Aaron Bentley
Merge produces new conflicts
548
        try:
1534.10.22 by Aaron Bentley
Got ConflictList implemented
549
            tree.set_conflicts(ConflictList())
1534.10.12 by Aaron Bentley
Merge produces new conflicts
550
        except UnsupportedOperation:
551
            raise TestSkipped
1534.10.22 by Aaron Bentley
Got ConflictList implemented
552
        self.assertEqual(tree.conflicts(), ConflictList())
1534.10.14 by Aaron Bentley
Made revert clear conflicts
553
554
    def test_revert_clear_conflicts(self):
555
        tree = self.make_merge_conflicts()
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(["blo"])
1534.10.22 by Aaron Bentley
Got ConflictList implemented
558
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.14 by Aaron Bentley
Made revert clear conflicts
559
        tree.revert(["bloo"])
1534.10.22 by Aaron Bentley
Got ConflictList implemented
560
        self.assertEqual(len(tree.conflicts()), 0)
1534.10.14 by Aaron Bentley
Made revert clear conflicts
561
562
    def test_revert_clear_conflicts2(self):
563
        tree = self.make_merge_conflicts()
1534.10.22 by Aaron Bentley
Got ConflictList implemented
564
        self.assertEqual(len(tree.conflicts()), 1)
1534.10.14 by Aaron Bentley
Made revert clear conflicts
565
        tree.revert([])
1534.10.22 by Aaron Bentley
Got ConflictList implemented
566
        self.assertEqual(len(tree.conflicts()), 0)
1624.3.22 by Olaf Conradi
Merge bzr.dev
567
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
568
    def test_format_description(self):
569
        tree = self.make_branch_and_tree('tree')
570
        text = tree._format.get_format_description()
571
        self.failUnless(len(text))
1681.1.1 by Robert Collins
Make WorkingTree.branch a read only property. (Robert Collins)
572
573
    def test_branch_attribute_is_not_settable(self):
574
        # the branch attribute is an aspect of the working tree, not a
575
        # configurable attribute
576
        tree = self.make_branch_and_tree('tree')
577
        def set_branch():
578
            tree.branch = tree.branch
579
        self.assertRaises(AttributeError, set_branch)
580
1713.3.1 by Robert Collins
Smoke tests for tree.list_files and bzr ignored when a versioned file matches an ignore rule.
581
    def test_list_files_versioned_before_ignored(self):
582
        """A versioned file matching an ignore rule should not be ignored."""
583
        tree = self.make_branch_and_tree('.')
584
        self.build_tree(['foo.pyc'])
585
        # ensure that foo.pyc is ignored
586
        self.build_tree_contents([('.bzrignore', 'foo.pyc')])
587
        tree.add('foo.pyc', 'anid')
588
        files = sorted(list(tree.list_files()))
589
        self.assertEqual((u'.bzrignore', '?', 'file', None), files[0][:-1])
590
        self.assertEqual((u'foo.pyc', 'V', 'file', 'anid'), files[1][:-1])
591
        self.assertEqual(2, len(files))