/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

  • Committer: Martin Pool
  • Date: 2009-11-14 11:23:07 UTC
  • mto: This revision was merged to the branch mainline in revision 4828.
  • Revision ID: mbp@sourcefrog.net-20091114112307-gezkfgg9ymipqv96
Further cleanup of removal reporting code

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
#
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
 
18
18
from cStringIO import StringIO
19
19
import os
20
20
 
21
 
import bzrlib
 
21
from bzrlib import (
 
22
    bzrdir,
 
23
    conflicts,
 
24
    errors,
 
25
    workingtree,
 
26
    )
22
27
from bzrlib.branch import Branch
23
 
import bzrlib.bzrdir as bzrdir
24
28
from bzrlib.bzrdir import BzrDir
25
 
from bzrlib.conflicts import *
26
 
import bzrlib.errors as errors
27
 
from bzrlib.errors import NotBranchError, NotVersionedError
28
29
from bzrlib.lockdir import LockDir
29
 
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
30
 
from bzrlib.tests import TestCaseWithTransport, TestSkipped
31
 
from bzrlib.trace import mutter
 
30
from bzrlib.mutabletree import needs_tree_write_lock
 
31
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
32
32
from bzrlib.transport import get_transport
33
 
import bzrlib.workingtree as workingtree
34
 
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
35
 
                                WorkingTree)
 
33
from bzrlib.workingtree import (
 
34
    TreeEntry,
 
35
    TreeDirectory,
 
36
    TreeFile,
 
37
    TreeLink,
 
38
    )
 
39
 
36
40
 
37
41
class TestTreeDirectory(TestCaseWithTransport):
38
42
 
77
81
            workingtree.WorkingTreeFormat.set_default_format(old_format)
78
82
        self.assertEqual(old_format, workingtree.WorkingTreeFormat.get_default_format())
79
83
 
 
84
    def test_open(self):
 
85
        tree = self.make_branch_and_tree('.')
 
86
        open_direct = workingtree.WorkingTree.open('.')
 
87
        self.assertEqual(tree.basedir, open_direct.basedir)
 
88
        open_no_args = workingtree.WorkingTree.open()
 
89
        self.assertEqual(tree.basedir, open_no_args.basedir)
 
90
 
 
91
    def test_open_containing(self):
 
92
        tree = self.make_branch_and_tree('.')
 
93
        open_direct, relpath = workingtree.WorkingTree.open_containing('.')
 
94
        self.assertEqual(tree.basedir, open_direct.basedir)
 
95
        self.assertEqual('', relpath)
 
96
        open_no_args, relpath = workingtree.WorkingTree.open_containing()
 
97
        self.assertEqual(tree.basedir, open_no_args.basedir)
 
98
        self.assertEqual('', relpath)
 
99
        open_subdir, relpath = workingtree.WorkingTree.open_containing('subdir')
 
100
        self.assertEqual(tree.basedir, open_subdir.basedir)
 
101
        self.assertEqual('subdir', relpath)
 
102
 
80
103
 
81
104
class SampleTreeFormat(workingtree.WorkingTreeFormat):
82
105
    """A sample format
83
106
 
84
 
    this format is initializable, unsupported to aid in testing the 
 
107
    this format is initializable, unsupported to aid in testing the
85
108
    open and open_downlevel routines.
86
109
    """
87
110
 
89
112
        """See WorkingTreeFormat.get_format_string()."""
90
113
        return "Sample tree format."
91
114
 
92
 
    def initialize(self, a_bzrdir, revision_id=None):
 
115
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
116
                   accelerator_tree=None, hardlink=False):
93
117
        """Sample branches cannot be created."""
94
118
        t = a_bzrdir.get_workingtree_transport(self)
95
 
        t.put('format', StringIO(self.get_format_string()))
 
119
        t.put_bytes('format', self.get_format_string())
96
120
        return 'A tree'
97
121
 
98
122
    def is_supported(self):
118
142
            found_format = workingtree.WorkingTreeFormat.find_format(dir)
119
143
            self.failUnless(isinstance(found_format, format.__class__))
120
144
        check_format(workingtree.WorkingTreeFormat3(), "bar")
121
 
        
 
145
 
122
146
    def test_find_format_no_tree(self):
123
147
        dir = bzrdir.BzrDirMetaFormat1().initialize('.')
124
148
        self.assertRaises(errors.NoWorkingTree,
169
193
        t = control.get_workingtree_transport(None)
170
194
        self.assertEqualDiff('Bazaar-NG Working Tree format 3',
171
195
                             t.get('format').read())
172
 
        self.assertEqualDiff('<inventory format="5">\n'
173
 
                             '</inventory>\n',
174
 
                             t.get('inventory').read())
 
196
        self.assertEqualDiff(t.get('inventory').read(),
 
197
                              '<inventory format="5">\n'
 
198
                              '</inventory>\n',
 
199
                             )
175
200
        self.assertEqualDiff('### bzr hashcache v5\n',
176
201
                             t.get('stat-cache').read())
177
202
        self.assertFalse(t.has('inventory.basis'))
178
203
        # no last-revision file means 'None' or 'NULLREVISION'
179
204
        self.assertFalse(t.has('last-revision'))
180
 
        # TODO RBC 20060210 do a commit, check the inventory.basis is created 
 
205
        # TODO RBC 20060210 do a commit, check the inventory.basis is created
181
206
        # correctly and last-revision file becomes present.
182
207
 
183
208
    def test_uses_lockdir(self):
184
209
        """WorkingTreeFormat3 uses its own LockDir:
185
 
            
 
210
 
186
211
            - lock is a directory
187
212
            - when the WorkingTree is locked, LockDir can see that
188
213
        """
205
230
        tree.unlock()
206
231
        self.assertEquals(our_lock.peek(), None)
207
232
 
 
233
    def test_missing_pending_merges(self):
 
234
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
 
235
        control.create_repository()
 
236
        control.create_branch()
 
237
        tree = workingtree.WorkingTreeFormat3().initialize(control)
 
238
        tree._transport.delete("pending-merges")
 
239
        self.assertEqual([], tree.get_parent_ids())
 
240
 
 
241
 
 
242
class TestFormat2WorkingTree(TestCaseWithTransport):
 
243
    """Tests that are specific to format 2 trees."""
 
244
 
208
245
    def create_format2_tree(self, url):
209
 
        return BzrDir.create_standalone_workingtree(url)
 
246
        return self.make_branch_and_tree(
 
247
            url, format=bzrdir.BzrDirFormat6())
210
248
 
211
 
    def test_conflicts_format2(self):
 
249
    def test_conflicts(self):
212
250
        # test backwards compatability
213
251
        tree = self.create_format2_tree('.')
214
252
        self.assertRaises(errors.UnsupportedOperation, tree.set_conflicts,
215
253
                          None)
216
254
        file('lala.BASE', 'wb').write('labase')
217
 
        expected = ContentsConflict('lala')
 
255
        expected = conflicts.ContentsConflict('lala')
218
256
        self.assertEqual(list(tree.conflicts()), [expected])
219
257
        file('lala', 'wb').write('la')
220
258
        tree.add('lala', 'lala-id')
221
 
        expected = ContentsConflict('lala', file_id='lala-id')
 
259
        expected = conflicts.ContentsConflict('lala', file_id='lala-id')
222
260
        self.assertEqual(list(tree.conflicts()), [expected])
223
261
        file('lala.THIS', 'wb').write('lathis')
224
262
        file('lala.OTHER', 'wb').write('laother')
225
263
        # When "text conflict"s happen, stem, THIS and OTHER are text
226
 
        expected = TextConflict('lala', file_id='lala-id')
 
264
        expected = conflicts.TextConflict('lala', file_id='lala-id')
227
265
        self.assertEqual(list(tree.conflicts()), [expected])
228
266
        os.unlink('lala.OTHER')
229
267
        os.mkdir('lala.OTHER')
230
 
        expected = ContentsConflict('lala', file_id='lala-id')
 
268
        expected = conflicts.ContentsConflict('lala', file_id='lala-id')
231
269
        self.assertEqual(list(tree.conflicts()), [expected])
 
270
 
 
271
 
 
272
class InstrumentedTree(object):
 
273
    """A instrumented tree to check the needs_tree_write_lock decorator."""
 
274
 
 
275
    def __init__(self):
 
276
        self._locks = []
 
277
 
 
278
    def lock_tree_write(self):
 
279
        self._locks.append('t')
 
280
 
 
281
    @needs_tree_write_lock
 
282
    def method_with_tree_write_lock(self, *args, **kwargs):
 
283
        """A lock_tree_write decorated method that returns its arguments."""
 
284
        return args, kwargs
 
285
 
 
286
    @needs_tree_write_lock
 
287
    def method_that_raises(self):
 
288
        """This method causes an exception when called with parameters.
 
289
 
 
290
        This allows the decorator code to be checked - it should still call
 
291
        unlock.
 
292
        """
 
293
 
 
294
    def unlock(self):
 
295
        self._locks.append('u')
 
296
 
 
297
 
 
298
class TestInstrumentedTree(TestCase):
 
299
 
 
300
    def test_needs_tree_write_lock(self):
 
301
        """@needs_tree_write_lock should be semantically transparent."""
 
302
        tree = InstrumentedTree()
 
303
        self.assertEqual(
 
304
            'method_with_tree_write_lock',
 
305
            tree.method_with_tree_write_lock.__name__)
 
306
        self.assertEqual(
 
307
            "A lock_tree_write decorated method that returns its arguments.",
 
308
            tree.method_with_tree_write_lock.__doc__)
 
309
        args = (1, 2, 3)
 
310
        kwargs = {'a':'b'}
 
311
        result = tree.method_with_tree_write_lock(1,2,3, a='b')
 
312
        self.assertEqual((args, kwargs), result)
 
313
        self.assertEqual(['t', 'u'], tree._locks)
 
314
        self.assertRaises(TypeError, tree.method_that_raises, 'foo')
 
315
        self.assertEqual(['t', 'u', 't', 'u'], tree._locks)
 
316
 
 
317
 
 
318
class TestRevert(TestCaseWithTransport):
 
319
 
 
320
    def test_revert_conflicts_recursive(self):
 
321
        this_tree = self.make_branch_and_tree('this-tree')
 
322
        self.build_tree_contents([('this-tree/foo/',),
 
323
                                  ('this-tree/foo/bar', 'bar')])
 
324
        this_tree.add(['foo', 'foo/bar'])
 
325
        this_tree.commit('created foo/bar')
 
326
        other_tree = this_tree.bzrdir.sprout('other-tree').open_workingtree()
 
327
        self.build_tree_contents([('other-tree/foo/bar', 'baz')])
 
328
        other_tree.commit('changed bar')
 
329
        self.build_tree_contents([('this-tree/foo/bar', 'qux')])
 
330
        this_tree.commit('changed qux')
 
331
        this_tree.merge_from_branch(other_tree.branch)
 
332
        self.assertEqual(1, len(this_tree.conflicts()))
 
333
        this_tree.revert(['foo'])
 
334
        self.assertEqual(0, len(this_tree.conflicts()))
 
335
 
 
336
 
 
337
class TestAutoResolve(TestCaseWithTransport):
 
338
 
 
339
    def test_auto_resolve(self):
 
340
        base = self.make_branch_and_tree('base')
 
341
        self.build_tree_contents([('base/hello', 'Hello')])
 
342
        base.add('hello', 'hello_id')
 
343
        base.commit('Hello')
 
344
        other = base.bzrdir.sprout('other').open_workingtree()
 
345
        self.build_tree_contents([('other/hello', 'hELLO')])
 
346
        other.commit('Case switch')
 
347
        this = base.bzrdir.sprout('this').open_workingtree()
 
348
        self.failUnlessExists('this/hello')
 
349
        self.build_tree_contents([('this/hello', 'Hello World')])
 
350
        this.commit('Add World')
 
351
        this.merge_from_branch(other.branch)
 
352
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
353
                         this.conflicts())
 
354
        this.auto_resolve()
 
355
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
356
                         this.conflicts())
 
357
        self.build_tree_contents([('this/hello', '<<<<<<<')])
 
358
        this.auto_resolve()
 
359
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
360
                         this.conflicts())
 
361
        self.build_tree_contents([('this/hello', '=======')])
 
362
        this.auto_resolve()
 
363
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
364
                         this.conflicts())
 
365
        self.build_tree_contents([('this/hello', '\n>>>>>>>')])
 
366
        remaining, resolved = this.auto_resolve()
 
367
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
368
                         this.conflicts())
 
369
        self.assertEqual([], resolved)
 
370
        self.build_tree_contents([('this/hello', 'hELLO wORLD')])
 
371
        remaining, resolved = this.auto_resolve()
 
372
        self.assertEqual([], this.conflicts())
 
373
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
374
                         resolved)
 
375
        self.failIfExists('this/hello.BASE')
 
376
 
 
377
    def test_auto_resolve_dir(self):
 
378
        tree = self.make_branch_and_tree('tree')
 
379
        self.build_tree(['tree/hello/'])
 
380
        tree.add('hello', 'hello-id')
 
381
        file_conflict = conflicts.TextConflict('file', None, 'hello-id')
 
382
        tree.set_conflicts(conflicts.ConflictList([file_conflict]))
 
383
        tree.auto_resolve()
 
384
 
 
385
 
 
386
class TestFindTrees(TestCaseWithTransport):
 
387
 
 
388
    def test_find_trees(self):
 
389
        self.make_branch_and_tree('foo')
 
390
        self.make_branch_and_tree('foo/bar')
 
391
        # Sticking a tree inside a control dir is heinous, so let's skip it
 
392
        self.make_branch_and_tree('foo/.bzr/baz')
 
393
        self.make_branch('qux')
 
394
        trees = workingtree.WorkingTree.find_trees('.')
 
395
        self.assertEqual(2, len(list(trees)))