/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_workingtree.py

Branch now uses BzrDir reasonably sanely.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
22
from bzrlib.branch import Branch
 
23
from bzrlib.bzrdir import BzrDir
 
24
import bzrlib.errors as errors
 
25
from bzrlib.errors import NotBranchError, NotVersionedError
 
26
from bzrlib.tests import TestCaseWithTransport
 
27
from bzrlib.trace import mutter
 
28
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
 
29
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
 
30
                                WorkingTree)
 
31
 
 
32
class TestTreeDirectory(TestCaseWithTransport):
 
33
 
 
34
    def test_kind_character(self):
 
35
        self.assertEqual(TreeDirectory().kind_character(), '/')
 
36
 
 
37
 
 
38
class TestTreeEntry(TestCaseWithTransport):
 
39
 
 
40
    def test_kind_character(self):
 
41
        self.assertEqual(TreeEntry().kind_character(), '???')
 
42
 
 
43
 
 
44
class TestTreeFile(TestCaseWithTransport):
 
45
 
 
46
    def test_kind_character(self):
 
47
        self.assertEqual(TreeFile().kind_character(), '')
 
48
 
 
49
 
 
50
class TestTreeLink(TestCaseWithTransport):
 
51
 
 
52
    def test_kind_character(self):
 
53
        self.assertEqual(TreeLink().kind_character(), '')
 
54
 
 
55
 
 
56
class TestWorkingTree(TestCaseWithTransport):
 
57
 
 
58
    def test_listfiles(self):
 
59
        tree = WorkingTree.create_standalone('.')
 
60
        os.mkdir('dir')
 
61
        print >> open('file', 'w'), "content"
 
62
        if has_symlinks():
 
63
            os.symlink('target', 'symlink')
 
64
        files = list(tree.list_files())
 
65
        self.assertEqual(files[0], ('dir', '?', 'directory', None, TreeDirectory()))
 
66
        self.assertEqual(files[1], ('file', '?', 'file', None, TreeFile()))
 
67
        if has_symlinks():
 
68
            self.assertEqual(files[2], ('symlink', '?', 'symlink', None, TreeLink()))
 
69
 
 
70
    def test_open_containing(self):
 
71
        branch = WorkingTree.create_standalone('.').branch
 
72
        wt, relpath = WorkingTree.open_containing()
 
73
        self.assertEqual('', relpath)
 
74
        self.assertEqual(wt.basedir + '/', branch.base)
 
75
        wt, relpath = WorkingTree.open_containing(u'.')
 
76
        self.assertEqual('', relpath)
 
77
        self.assertEqual(wt.basedir + '/', branch.base)
 
78
        wt, relpath = WorkingTree.open_containing('./foo')
 
79
        self.assertEqual('foo', relpath)
 
80
        self.assertEqual(wt.basedir + '/', branch.base)
 
81
        # paths that are urls are just plain wrong for working trees.
 
82
        self.assertRaises(NotBranchError,
 
83
                          WorkingTree.open_containing, 
 
84
                          'file:///' + getcwd())
 
85
 
 
86
    def test_construct_with_branch(self):
 
87
        branch = WorkingTree.create_standalone('.').branch
 
88
        tree = WorkingTree(branch.base, branch)
 
89
        self.assertEqual(branch, tree.branch)
 
90
        self.assertEqual(branch.base, tree.basedir + '/')
 
91
    
 
92
    def test_construct_without_branch(self):
 
93
        branch = WorkingTree.create_standalone('.').branch
 
94
        tree = WorkingTree(branch.base)
 
95
        self.assertEqual(branch.base, tree.branch.base)
 
96
        self.assertEqual(branch.base, tree.basedir + '/')
 
97
 
 
98
    def test_basic_relpath(self):
 
99
        # for comprehensive relpath tests, see whitebox.py.
 
100
        tree = WorkingTree.create_standalone('.')
 
101
        self.assertEqual('child',
 
102
                         tree.relpath(pathjoin(getcwd(), 'child')))
 
103
 
 
104
    def test_lock_locks_branch(self):
 
105
        tree = WorkingTree.create_standalone('.')
 
106
        tree.lock_read()
 
107
        self.assertEqual('r', tree.branch.peek_lock_mode())
 
108
        tree.unlock()
 
109
        self.assertEqual(None, tree.branch.peek_lock_mode())
 
110
        tree.lock_write()
 
111
        self.assertEqual('w', tree.branch.peek_lock_mode())
 
112
        tree.unlock()
 
113
        self.assertEqual(None, tree.branch.peek_lock_mode())
 
114
 
 
115
    def get_pullable_trees(self):
 
116
        self.build_tree(['from/', 'from/file', 'to/'])
 
117
        tree = WorkingTree.create_standalone('from')
 
118
        tree.add('file')
 
119
        tree.commit('foo', rev_id='A')
 
120
        tree_b = WorkingTree.create_standalone('to')
 
121
        return tree, tree_b
 
122
 
 
123
    def test_pull(self):
 
124
        tree_a, tree_b = self.get_pullable_trees()
 
125
        tree_b.pull(tree_a.branch)
 
126
        self.failUnless(tree_b.branch.repository.has_revision('A'))
 
127
        self.assertEqual(['A'], tree_b.branch.revision_history())
 
128
 
 
129
    def test_pull_overwrites(self):
 
130
        tree_a, tree_b = self.get_pullable_trees()
 
131
        tree_b.commit('foo', rev_id='B')
 
132
        self.assertEqual(['B'], tree_b.branch.revision_history())
 
133
        tree_b.pull(tree_a.branch, overwrite=True)
 
134
        self.failUnless(tree_b.branch.repository.has_revision('A'))
 
135
        self.failUnless(tree_b.branch.repository.has_revision('B'))
 
136
        self.assertEqual(['A'], tree_b.branch.revision_history())
 
137
 
 
138
    def test_revert(self):
 
139
        """Test selected-file revert"""
 
140
        tree = WorkingTree.create_standalone('.')
 
141
 
 
142
        self.build_tree(['hello.txt'])
 
143
        file('hello.txt', 'w').write('initial hello')
 
144
 
 
145
        self.assertRaises(NotVersionedError,
 
146
                          tree.revert, ['hello.txt'])
 
147
        tree.add(['hello.txt'])
 
148
        tree.commit('create initial hello.txt')
 
149
 
 
150
        self.check_file_contents('hello.txt', 'initial hello')
 
151
        file('hello.txt', 'w').write('new hello')
 
152
        self.check_file_contents('hello.txt', 'new hello')
 
153
 
 
154
        # revert file modified since last revision
 
155
        tree.revert(['hello.txt'])
 
156
        self.check_file_contents('hello.txt', 'initial hello')
 
157
        self.check_file_contents('hello.txt~', 'new hello')
 
158
 
 
159
        # reverting again does not clobber the backup
 
160
        tree.revert(['hello.txt'])
 
161
        self.check_file_contents('hello.txt', 'initial hello')
 
162
        self.check_file_contents('hello.txt~', 'new hello')
 
163
 
 
164
    def test_unknowns(self):
 
165
        tree = WorkingTree.create_standalone('.')
 
166
        self.build_tree(['hello.txt',
 
167
                         'hello.txt~'])
 
168
        self.assertEquals(list(tree.unknowns()),
 
169
                          ['hello.txt'])
 
170
 
 
171
    def test_hashcache(self):
 
172
        from bzrlib.tests.test_hashcache import pause
 
173
        tree = WorkingTree.create_standalone('.')
 
174
        self.build_tree(['hello.txt',
 
175
                         'hello.txt~'])
 
176
        tree.add('hello.txt')
 
177
        pause()
 
178
        sha = tree.get_file_sha1(tree.path2id('hello.txt'))
 
179
        self.assertEqual(1, tree._hashcache.miss_count)
 
180
        tree2 = WorkingTree('.', tree.branch)
 
181
        sha2 = tree2.get_file_sha1(tree2.path2id('hello.txt'))
 
182
        self.assertEqual(0, tree2._hashcache.miss_count)
 
183
        self.assertEqual(1, tree2._hashcache.hit_count)
 
184
 
 
185
    def test_checkout(self):
 
186
        # at this point as we dont have checkout versions, checkout simply
 
187
        # populates the required files for a working tree at the dir.
 
188
        b = BzrDir.create_branch_and_repo('branch')
 
189
        t = WorkingTree.create(b, 'tree')
 
190
        # as we are moving the ownership to working tree, we will check here
 
191
        # that its split out correctly
 
192
        self.failIfExists('branch/.bzr/inventory')
 
193
        self.failIfExists('branch/.bzr/pending-merges')
 
194
        sio = StringIO()
 
195
        bzrlib.xml5.serializer_v5.write_inventory(bzrlib.inventory.Inventory(),
 
196
                                                  sio)
 
197
        self.assertFileEqual(sio.getvalue(), 'tree/.bzr/inventory')
 
198
        self.assertFileEqual('', 'tree/.bzr/pending-merges')
 
199
 
 
200
    def test_initialize(self):
 
201
        # initialize should create a working tree and branch in an existing dir
 
202
        t = WorkingTree.create_standalone('.')
 
203
        b = Branch.open('.')
 
204
        self.assertEqual(t.branch.base, b.base)
 
205
        t2 = WorkingTree('.')
 
206
        self.assertEqual(t.basedir, t2.basedir)
 
207
        self.assertEqual(b.base, t2.branch.base)
 
208
        # TODO maybe we should check the branch format? not sure if its
 
209
        # appropriate here.
 
210
 
 
211
    def test_rename_dirs(self):
 
212
        """Test renaming directories and the files within them."""
 
213
        wt = self.make_branch_and_tree('.')
 
214
        b = wt.branch
 
215
        self.build_tree(['dir/', 'dir/sub/', 'dir/sub/file'])
 
216
        wt.add(['dir', 'dir/sub', 'dir/sub/file'])
 
217
 
 
218
        wt.commit('create initial state')
 
219
 
 
220
        revid = b.revision_history()[0]
 
221
        self.log('first revision_id is {%s}' % revid)
 
222
        
 
223
        inv = b.repository.get_revision_inventory(revid)
 
224
        self.log('contents of inventory: %r' % inv.entries())
 
225
 
 
226
        self.check_inventory_shape(inv,
 
227
                                   ['dir', 'dir/sub', 'dir/sub/file'])
 
228
 
 
229
        wt.rename_one('dir', 'newdir')
 
230
 
 
231
        self.check_inventory_shape(wt.read_working_inventory(),
 
232
                                   ['newdir', 'newdir/sub', 'newdir/sub/file'])
 
233
 
 
234
        wt.rename_one('newdir/sub', 'newdir/newsub')
 
235
        self.check_inventory_shape(wt.read_working_inventory(),
 
236
                                   ['newdir', 'newdir/newsub',
 
237
                                    'newdir/newsub/file'])
 
238
 
 
239
    def test_add_in_unversioned(self):
 
240
        """Try to add a file in an unversioned directory.
 
241
 
 
242
        "bzr add" adds the parent as necessary, but simple working tree add
 
243
        doesn't do that.
 
244
        """
 
245
        from bzrlib.errors import NotVersionedError
 
246
        wt = self.make_branch_and_tree('.')
 
247
        self.build_tree(['foo/',
 
248
                         'foo/hello'])
 
249
        self.assertRaises(NotVersionedError,
 
250
                          wt.add,
 
251
                          'foo/hello')
 
252
 
 
253
    def test_add_missing(self):
 
254
        # adding a msising file -> NoSuchFile
 
255
        wt = self.make_branch_and_tree('.')
 
256
        self.assertRaises(errors.NoSuchFile, wt.add, 'fpp')
 
257
 
 
258
    def test_remove_verbose(self):
 
259
        #FIXME the remove api should not print or otherwise depend on the
 
260
        # text UI - RBC 20060124
 
261
        wt = self.make_branch_and_tree('.')
 
262
        self.build_tree(['hello'])
 
263
        wt.add(['hello'])
 
264
        wt.commit(message='add hello')
 
265
        stdout = StringIO()
 
266
        stderr = StringIO()
 
267
        self.assertEqual(None, self.apply_redirected(None, stdout, stderr,
 
268
                                                     wt.remove,
 
269
                                                     ['hello'],
 
270
                                                     verbose=True))
 
271
        self.assertEqual('?       hello\n', stdout.getvalue())
 
272
        self.assertEqual('', stderr.getvalue())
 
273
 
 
274
    def test_clone_trivial(self):
 
275
        wt = self.make_branch_and_tree('source')
 
276
        cloned = wt.clone('target')
 
277
        self.assertEqual(cloned.last_revision(), wt.last_revision())
 
278
 
 
279
    def test_last_revision(self):
 
280
        wt = self.make_branch_and_tree('source')
 
281
        self.assertEqual(None, wt.last_revision())
 
282
        wt.commit('A', allow_pointless=True, rev_id='A')
 
283
        self.assertEqual('A', wt.last_revision())
 
284
 
 
285
    def test_set_last_revision(self):
 
286
        wt = self.make_branch_and_tree('source')
 
287
        self.assertEqual(None, wt.last_revision())
 
288
        # cannot set the last revision to one not in the branch
 
289
        self.assertRaises(errors.NoSuchRevision, wt.set_last_revision, 'A')
 
290
        wt.commit('A', allow_pointless=True, rev_id='A')
 
291
        self.assertEqual('A', wt.last_revision())
 
292
        # None is aways in the branch
 
293
        wt.set_last_revision(None)
 
294
        self.assertEqual(None, wt.last_revision())
 
295
        # and now we can set it to 'A'
 
296
        # because the current format mutates the branch to set it,
 
297
        # we need to alter the branch to let this pass.
 
298
        wt.branch.set_revision_history(['A', 'B'])
 
299
        wt.set_last_revision('A')
 
300
        self.assertEqual('A', wt.last_revision())
 
301
 
 
302
    def test_clone_and_commit_preserves_last_revision(self):
 
303
        wt = self.make_branch_and_tree('source')
 
304
        cloned = wt.clone('target')
 
305
        wt.commit('A', allow_pointless=True, rev_id='A')
 
306
        self.assertNotEqual(cloned.last_revision(), wt.last_revision())
 
307
        
 
308
    def test_basis_tree_returns_last_revision(self):
 
309
        wt = self.make_branch_and_tree('.')
 
310
        self.build_tree(['foo'])
 
311
        wt.add('foo', 'foo-id')
 
312
        wt.commit('A', rev_id='A')
 
313
        wt.rename_one('foo', 'bar')
 
314
        wt.commit('B', rev_id='B')
 
315
        wt.set_last_revision('B')
 
316
        tree = wt.basis_tree()
 
317
        self.failUnless(tree.has_filename('bar'))
 
318
        wt.set_last_revision('A')
 
319
        tree = wt.basis_tree()
 
320
        self.failUnless(tree.has_filename('foo'))