/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
27
from bzrlib.errors import NotBranchError, NotVersionedError
28
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
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.
29
from bzrlib.tests import TestCaseWithTransport, TestSkipped
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
30
from bzrlib.trace import mutter
31
from bzrlib.transport import get_transport
32
import bzrlib.workingtree as workingtree
33
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
34
                                WorkingTree)
35
36
37
class TestCaseWithWorkingTree(TestCaseWithTransport):
38
39
    def make_bzrdir(self, relpath):
40
        # todo factor out into bzrdir-using-implementations-tests-base-class
41
        try:
42
            url = self.get_url(relpath)
43
            segments = url.split('/')
44
            if segments and segments[-1] not in ('', '.'):
45
                parent = '/'.join(segments[:-1])
46
                t = get_transport(parent)
47
                try:
48
                    t.mkdir(segments[-1])
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.
49
                except errors.FileExists:
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
50
                    pass
51
            return self.bzrdir_format.initialize(url)
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.
52
        except errors.UninitializableFormat:
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
53
            raise TestSkipped("Format %s is not initializable.")
54
55
    def make_branch_and_tree(self, relpath):
56
        made_control = self.make_bzrdir(relpath)
57
        made_control.create_repository()
58
        made_control.create_branch()
59
        return self.workingtree_format.initialize(made_control)
60
61
62
class TestWorkingTree(TestCaseWithWorkingTree):
63
64
    def test_listfiles(self):
65
        tree = self.make_branch_and_tree('.')
66
        os.mkdir('dir')
67
        print >> open('file', 'w'), "content"
68
        if has_symlinks():
69
            os.symlink('target', 'symlink')
70
        files = list(tree.list_files())
71
        self.assertEqual(files[0], ('dir', '?', 'directory', None, TreeDirectory()))
72
        self.assertEqual(files[1], ('file', '?', 'file', None, TreeFile()))
73
        if has_symlinks():
74
            self.assertEqual(files[2], ('symlink', '?', 'symlink', None, TreeLink()))
75
76
    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.
77
        branch = self.make_branch_and_tree('.').branch
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
78
        wt, relpath = WorkingTree.open_containing()
79
        self.assertEqual('', relpath)
80
        self.assertEqual(wt.basedir + '/', branch.base)
81
        wt, relpath = WorkingTree.open_containing(u'.')
82
        self.assertEqual('', relpath)
83
        self.assertEqual(wt.basedir + '/', branch.base)
84
        wt, relpath = WorkingTree.open_containing('./foo')
85
        self.assertEqual('foo', relpath)
86
        self.assertEqual(wt.basedir + '/', branch.base)
87
        wt, relpath = WorkingTree.open_containing('file://' + getcwd() + '/foo')
88
        self.assertEqual('foo', relpath)
89
        self.assertEqual(wt.basedir + '/', branch.base)
90
91
    def test_basic_relpath(self):
92
        # 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.
93
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
94
        self.assertEqual('child',
95
                         tree.relpath(pathjoin(getcwd(), 'child')))
96
97
    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.
98
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
99
        tree.lock_read()
100
        self.assertEqual('r', tree.branch.peek_lock_mode())
101
        tree.unlock()
102
        self.assertEqual(None, tree.branch.peek_lock_mode())
103
        tree.lock_write()
104
        self.assertEqual('w', tree.branch.peek_lock_mode())
105
        tree.unlock()
106
        self.assertEqual(None, tree.branch.peek_lock_mode())
107
 
108
    def get_pullable_trees(self):
109
        self.build_tree(['from/', 'from/file', 'to/'])
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.
110
        tree = self.make_branch_and_tree('from')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
111
        tree.add('file')
112
        tree.commit('foo', 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.
113
        tree_b = self.make_branch_and_tree('to')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
114
        return tree, tree_b
115
 
116
    def test_pull(self):
117
        tree_a, tree_b = self.get_pullable_trees()
118
        tree_b.pull(tree_a.branch)
119
        self.failUnless(tree_b.branch.repository.has_revision('A'))
120
        self.assertEqual('A', tree_b.last_revision())
121
122
    def test_pull_overwrites(self):
123
        tree_a, tree_b = self.get_pullable_trees()
124
        tree_b.commit('foo', rev_id='B')
125
        self.assertEqual(['B'], tree_b.branch.revision_history())
126
        tree_b.pull(tree_a.branch, overwrite=True)
127
        self.failUnless(tree_b.branch.repository.has_revision('A'))
128
        self.failUnless(tree_b.branch.repository.has_revision('B'))
129
        self.assertEqual('A', tree_b.last_revision())
130
131
    def test_revert(self):
132
        """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.
133
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
134
135
        self.build_tree(['hello.txt'])
136
        file('hello.txt', 'w').write('initial hello')
137
138
        self.assertRaises(NotVersionedError,
139
                          tree.revert, ['hello.txt'])
140
        tree.add(['hello.txt'])
141
        tree.commit('create initial hello.txt')
142
143
        self.check_file_contents('hello.txt', 'initial hello')
144
        file('hello.txt', 'w').write('new hello')
145
        self.check_file_contents('hello.txt', 'new hello')
146
147
        # revert file modified since last revision
148
        tree.revert(['hello.txt'])
149
        self.check_file_contents('hello.txt', 'initial hello')
150
        self.check_file_contents('hello.txt~', 'new hello')
151
152
        # reverting again does not clobber the backup
153
        tree.revert(['hello.txt'])
154
        self.check_file_contents('hello.txt', 'initial hello')
155
        self.check_file_contents('hello.txt~', 'new hello')
156
157
    def test_unknowns(self):
158
        tree = self.make_branch_and_tree('.')
159
        self.build_tree(['hello.txt',
160
                         'hello.txt~'])
161
        self.assertEquals(list(tree.unknowns()),
162
                          ['hello.txt'])
163
164
    def test_hashcache(self):
165
        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.
166
        tree = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
167
        self.build_tree(['hello.txt',
168
                         'hello.txt~'])
169
        tree.add('hello.txt')
170
        pause()
171
        sha = tree.get_file_sha1(tree.path2id('hello.txt'))
172
        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.
173
        tree2 = WorkingTree.open('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
174
        sha2 = tree2.get_file_sha1(tree2.path2id('hello.txt'))
175
        self.assertEqual(0, tree2._hashcache.miss_count)
176
        self.assertEqual(1, tree2._hashcache.hit_count)
177
178
    def test_initialize(self):
179
        # 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.
180
        t = self.make_branch_and_tree('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
181
        b = Branch.open('.')
182
        self.assertEqual(t.branch.base, b.base)
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
183
        t2 = WorkingTree.open('.')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
184
        self.assertEqual(t.basedir, t2.basedir)
185
        self.assertEqual(b.base, t2.branch.base)
186
        # TODO maybe we should check the branch format? not sure if its
187
        # appropriate here.
188
189
    def test_rename_dirs(self):
190
        """Test renaming directories and the files within them."""
191
        wt = self.make_branch_and_tree('.')
192
        b = wt.branch
193
        self.build_tree(['dir/', 'dir/sub/', 'dir/sub/file'])
194
        wt.add(['dir', 'dir/sub', 'dir/sub/file'])
195
196
        wt.commit('create initial state')
197
198
        revid = b.revision_history()[0]
199
        self.log('first revision_id is {%s}' % revid)
200
        
201
        inv = b.repository.get_revision_inventory(revid)
202
        self.log('contents of inventory: %r' % inv.entries())
203
204
        self.check_inventory_shape(inv,
205
                                   ['dir', 'dir/sub', 'dir/sub/file'])
206
207
        wt.rename_one('dir', 'newdir')
208
209
        self.check_inventory_shape(wt.read_working_inventory(),
210
                                   ['newdir', 'newdir/sub', 'newdir/sub/file'])
211
212
        wt.rename_one('newdir/sub', 'newdir/newsub')
213
        self.check_inventory_shape(wt.read_working_inventory(),
214
                                   ['newdir', 'newdir/newsub',
215
                                    'newdir/newsub/file'])
216
217
    def test_add_in_unversioned(self):
218
        """Try to add a file in an unversioned directory.
219
220
        "bzr add" adds the parent as necessary, but simple working tree add
221
        doesn't do that.
222
        """
223
        from bzrlib.errors import NotVersionedError
224
        wt = self.make_branch_and_tree('.')
225
        self.build_tree(['foo/',
226
                         'foo/hello'])
227
        self.assertRaises(NotVersionedError,
228
                          wt.add,
229
                          'foo/hello')
230
231
    def test_add_missing(self):
232
        # adding a msising file -> NoSuchFile
233
        wt = self.make_branch_and_tree('.')
234
        self.assertRaises(errors.NoSuchFile, wt.add, 'fpp')
235
236
    def test_remove_verbose(self):
237
        #FIXME the remove api should not print or otherwise depend on the
238
        # text UI - RBC 20060124
239
        wt = self.make_branch_and_tree('.')
240
        self.build_tree(['hello'])
241
        wt.add(['hello'])
242
        wt.commit(message='add hello')
243
        stdout = StringIO()
244
        stderr = StringIO()
245
        self.assertEqual(None, self.apply_redirected(None, stdout, stderr,
246
                                                     wt.remove,
247
                                                     ['hello'],
248
                                                     verbose=True))
249
        self.assertEqual('?       hello\n', stdout.getvalue())
250
        self.assertEqual('', stderr.getvalue())
251
252
    def test_clone_trivial(self):
253
        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.
254
        cloned_dir = wt.bzrdir.clone('target')
255
        cloned = cloned_dir.open_workingtree()
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
256
        self.assertEqual(cloned.last_revision(), wt.last_revision())
257
258
    def test_last_revision(self):
259
        wt = self.make_branch_and_tree('source')
260
        self.assertEqual(None, wt.last_revision())
261
        wt.commit('A', allow_pointless=True, rev_id='A')
262
        self.assertEqual('A', wt.last_revision())
263
264
    def test_set_last_revision(self):
265
        wt = self.make_branch_and_tree('source')
266
        self.assertEqual(None, wt.last_revision())
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
267
        # cannot set the last revision to one not in the branch history.
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
268
        self.assertRaises(errors.NoSuchRevision, wt.set_last_revision, 'A')
269
        wt.commit('A', allow_pointless=True, rev_id='A')
270
        self.assertEqual('A', wt.last_revision())
271
        # None is aways in the branch
272
        wt.set_last_revision(None)
273
        self.assertEqual(None, wt.last_revision())
274
        # and now we can set it to 'A'
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
275
        # because some formats mutate the branch to set it on the tree
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
276
        # we need to alter the branch to let this pass.
277
        wt.branch.set_revision_history(['A', 'B'])
278
        wt.set_last_revision('A')
279
        self.assertEqual('A', wt.last_revision())
280
1508.1.19 by Robert Collins
Give format3 working trees their own last-revision marker.
281
    def test_set_last_revision_different_to_branch(self):
282
        # working tree formats from the meta-dir format and newer support
283
        # setting the last revision on a tree independently of that on the 
284
        # branch. Its concievable that some future formats may want to 
285
        # couple them again (i.e. because its really a smart server and
286
        # the working tree will always match the branch). So we test
287
        # that formats where initialising a branch does not initialise a 
288
        # tree - and thus have separable entities - support skewing the 
289
        # two things.
290
        branch = self.make_branch('tree')
291
        try:
292
            # if there is a working tree now, this is not supported.
293
            branch.bzrdir.open_workingtree()
294
            return
295
        except errors.NoWorkingTree:
296
            pass
297
        wt = branch.bzrdir.create_workingtree()
298
        wt.commit('A', allow_pointless=True, rev_id='A')
299
        wt.set_last_revision(None)
300
        self.assertEqual(None, wt.last_revision())
301
        self.assertEqual('A', wt.branch.last_revision())
302
        # and now we can set it back to 'A'
303
        wt.set_last_revision('A')
304
        self.assertEqual('A', wt.last_revision())
305
        self.assertEqual('A', wt.branch.last_revision())
306
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
307
    def test_clone_and_commit_preserves_last_revision(self):
308
        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.
309
        cloned_dir = wt.bzrdir.clone('target')
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
310
        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.
311
        self.assertNotEqual(cloned_dir.open_workingtree().last_revision(),
312
                            wt.last_revision())
313
314
    def test_clone_preserves_content(self):
315
        wt = self.make_branch_and_tree('source')
316
        self.build_tree(['added', 'deleted', 'notadded'], transport=wt.bzrdir.transport.clone('..'))
317
        wt.add('deleted', 'deleted')
318
        wt.commit('add deleted')
319
        wt.remove('deleted')
320
        wt.add('added', 'added')
321
        cloned_dir = wt.bzrdir.clone('target')
322
        cloned = cloned_dir.open_workingtree()
323
        cloned_transport = cloned.bzrdir.transport.clone('..')
324
        self.assertFalse(cloned_transport.has('deleted'))
325
        self.assertTrue(cloned_transport.has('added'))
326
        self.assertFalse(cloned_transport.has('notadded'))
327
        self.assertEqual('added', cloned.path2id('added'))
328
        self.assertEqual(None, cloned.path2id('deleted'))
329
        self.assertEqual(None, cloned.path2id('notadded'))
1534.4.46 by Robert Collins
Nearly complete .bzr/checkout splitout.
330
        
331
    def test_basis_tree_returns_last_revision(self):
332
        wt = self.make_branch_and_tree('.')
333
        self.build_tree(['foo'])
334
        wt.add('foo', 'foo-id')
335
        wt.commit('A', rev_id='A')
336
        wt.rename_one('foo', 'bar')
337
        wt.commit('B', rev_id='B')
338
        wt.set_last_revision('B')
339
        tree = wt.basis_tree()
340
        self.failUnless(tree.has_filename('bar'))
341
        wt.set_last_revision('A')
342
        tree = wt.basis_tree()
343
        self.failUnless(tree.has_filename('foo'))
344
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.
345
    def test_clone_tree_revision(self):
346
        # make a tree with a last-revision,
347
        # and clone it with a different last-revision, this should switch
348
        # do it.
349
        #
350
        # also test that the content is merged
351
        # and conflicts recorded.
352
        # This should merge between the trees - local edits should be preserved
353
        # but other changes occured.
354
        # we test this by having one file that does
355
        # not change between two revisions, and another that does -
356
        # if the changed one is not changed, fail,
357
        # if the one that did not change has lost a local change, fail.
358
        # 
359
        raise TestSkipped('revision limiting is not implemented yet.')
1508.1.21 by Robert Collins
Implement -r limit for checkout command.
360
361
    def test_initialize_with_revision_id(self):
362
        # a bzrdir can construct a working tree for itself @ a specific revision.
363
        source = self.make_branch_and_tree('source')
364
        source.commit('a', rev_id='a', allow_pointless=True)
365
        source.commit('b', rev_id='b', allow_pointless=True)
366
        self.build_tree(['new/'])
367
        made_control = self.bzrdir_format.initialize('new')
368
        source.branch.repository.clone(made_control)
369
        source.branch.clone(made_control)
370
        made_tree = self.workingtree_format.initialize(made_control, revision_id='a')
371
        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.
372
373
    def test_commit_sets_last_revision(self):
374
        tree = self.make_branch_and_tree('tree')
375
        tree.commit('foo', rev_id='foo', allow_pointless=True)
376
        self.assertEqual('foo', tree.last_revision())
1508.1.24 by Robert Collins
Add update command for use with checkouts.
377
378
    def test_update_sets_last_revision(self):
379
        # working tree formats from the meta-dir format and newer support
380
        # setting the last revision on a tree independently of that on the 
381
        # branch. Its concievable that some future formats may want to 
382
        # couple them again (i.e. because its really a smart server and
383
        # the working tree will always match the branch). So we test
384
        # that formats where initialising a branch does not initialise a 
385
        # tree - and thus have separable entities - support skewing the 
386
        # two things.
387
        main_branch = self.make_branch('tree')
388
        try:
389
            # if there is a working tree now, this is not supported.
390
            main_branch.bzrdir.open_workingtree()
391
            return
392
        except errors.NoWorkingTree:
393
            pass
394
        wt = main_branch.bzrdir.create_workingtree()
395
        # create an out of date working tree by making a checkout in this
396
        # current format
397
        self.build_tree(['checkout/', 'tree/file'])
398
        checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
1508.1.25 by Robert Collins
Update per review comments.
399
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, main_branch)
1508.1.24 by Robert Collins
Add update command for use with checkouts.
400
        old_tree = self.workingtree_format.initialize(checkout)
401
        # now commit to 'tree'
402
        wt.add('file')
403
        wt.commit('A', rev_id='A')
404
        # and update old_tree
405
        self.assertEqual(0, old_tree.update())
406
        self.failUnlessExists('checkout/file')
407
        self.assertEqual('A', old_tree.last_revision())
408
409
    def test_update_returns_conflict_count(self):
410
        # working tree formats from the meta-dir format and newer support
411
        # setting the last revision on a tree independently of that on the 
412
        # branch. Its concievable that some future formats may want to 
413
        # couple them again (i.e. because its really a smart server and
414
        # the working tree will always match the branch). So we test
415
        # that formats where initialising a branch does not initialise a 
416
        # tree - and thus have separable entities - support skewing the 
417
        # two things.
418
        main_branch = self.make_branch('tree')
419
        try:
420
            # if there is a working tree now, this is not supported.
421
            main_branch.bzrdir.open_workingtree()
422
            return
423
        except errors.NoWorkingTree:
424
            pass
425
        wt = main_branch.bzrdir.create_workingtree()
426
        # create an out of date working tree by making a checkout in this
427
        # current format
428
        self.build_tree(['checkout/', 'tree/file'])
429
        checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
1508.1.25 by Robert Collins
Update per review comments.
430
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, main_branch)
1508.1.24 by Robert Collins
Add update command for use with checkouts.
431
        old_tree = self.workingtree_format.initialize(checkout)
432
        # now commit to 'tree'
433
        wt.add('file')
434
        wt.commit('A', rev_id='A')
435
        # and add a file file to the checkout
436
        self.build_tree(['checkout/file'])
437
        old_tree.add('file')
438
        # and update old_tree
439
        self.assertEqual(1, old_tree.update())
440
        self.assertEqual('A', old_tree.last_revision())
441