~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

first cut at merge from integration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
from cStringIO import StringIO
18
18
import os
19
 
import time
20
19
 
21
20
from bzrlib.branch import Branch
22
21
import bzrlib.errors as errors
23
22
from bzrlib.diff import internal_diff
24
 
from bzrlib.inventory import (Inventory, ROOT_ID, InventoryFile,
25
 
    InventoryDirectory, InventoryEntry)
 
23
from bzrlib.inventory import Inventory, ROOT_ID
26
24
import bzrlib.inventory as inventory
27
 
from bzrlib.osutils import (has_symlinks, rename, pathjoin, is_inside_any, 
28
 
    is_inside_or_parent_of_any)
 
25
from bzrlib.osutils import has_symlinks, rename, pathjoin
29
26
from bzrlib.tests import TestCase, TestCaseWithTransport
30
 
from bzrlib.transform import TreeTransform
31
 
from bzrlib.uncommit import uncommit
 
27
from bzrlib.workingtree import WorkingTree
32
28
 
33
29
 
34
30
class TestInventory(TestCase):
35
31
 
36
32
    def test_is_within(self):
 
33
        from bzrlib.osutils import is_inside_any
37
34
 
38
35
        SRC_FOO_C = pathjoin('src', 'foo.c')
39
36
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
45
42
        for dirs, fn in [(['src'], 'srccontrol'),
46
43
                         (['src'], 'srccontrol/foo')]:
47
44
            self.assertFalse(is_inside_any(dirs, fn))
48
 
 
49
 
    def test_is_within_or_parent(self):
50
 
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
51
 
                         (['src'], 'src/foo.c'),
52
 
                         (['src/bar.c'], 'src'),
53
 
                         (['src/bar.c', 'bla/foo.c'], 'src'),
54
 
                         (['src'], 'src'),
55
 
                         ]:
56
 
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
57
45
            
58
 
        for dirs, fn in [(['src'], 'srccontrol'),
59
 
                         (['srccontrol/foo.c'], 'src'),
60
 
                         (['src'], 'srccontrol/foo')]:
61
 
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
62
 
 
63
46
    def test_ids(self):
64
47
        """Test detection of files within selected directories."""
65
48
        inv = Inventory()
76
59
        
77
60
        self.assert_('src-id' in inv)
78
61
 
79
 
    def test_iter_entries(self):
80
 
        inv = Inventory()
81
 
        
82
 
        for args in [('src', 'directory', 'src-id'), 
83
 
                     ('doc', 'directory', 'doc-id'), 
84
 
                     ('src/hello.c', 'file', 'hello-id'),
85
 
                     ('src/bye.c', 'file', 'bye-id'),
86
 
                     ('Makefile', 'file', 'makefile-id')]:
87
 
            inv.add_path(*args)
88
 
 
89
 
        self.assertEqual([
90
 
            ('Makefile', 'makefile-id'),
91
 
            ('doc', 'doc-id'),
92
 
            ('src', 'src-id'),
93
 
            ('src/bye.c', 'bye-id'),
94
 
            ('src/hello.c', 'hello-id'),
95
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries()])
96
 
            
97
 
    def test_iter_entries_by_dir(self):
98
 
        inv = Inventory()
99
 
        
100
 
        for args in [('src', 'directory', 'src-id'), 
101
 
                     ('doc', 'directory', 'doc-id'), 
102
 
                     ('src/hello.c', 'file', 'hello-id'),
103
 
                     ('src/bye.c', 'file', 'bye-id'),
104
 
                     ('zz', 'file', 'zz-id'),
105
 
                     ('src/sub/', 'directory', 'sub-id'),
106
 
                     ('src/zz.c', 'file', 'zzc-id'),
107
 
                     ('src/sub/a', 'file', 'a-id'),
108
 
                     ('Makefile', 'file', 'makefile-id')]:
109
 
            inv.add_path(*args)
110
 
 
111
 
        self.assertEqual([
112
 
            ('Makefile', 'makefile-id'),
113
 
            ('doc', 'doc-id'),
114
 
            ('src', 'src-id'),
115
 
            ('zz', 'zz-id'),
116
 
            ('src/bye.c', 'bye-id'),
117
 
            ('src/hello.c', 'hello-id'),
118
 
            ('src/sub', 'sub-id'),
119
 
            ('src/zz.c', 'zzc-id'),
120
 
            ('src/sub/a', 'a-id'),
121
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir()])
122
 
            
 
62
 
123
63
    def test_version(self):
124
64
        """Inventory remembers the text's version."""
125
65
        inv = Inventory()
192
132
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
193
133
        self.failIf(link.has_text())
194
134
 
195
 
    def test_make_entry(self):
196
 
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
197
 
            inventory.InventoryFile)
198
 
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
199
 
            inventory.InventoryLink)
200
 
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
201
 
            inventory.InventoryDirectory)
202
135
 
203
136
class TestEntryDiffing(TestCaseWithTransport):
204
137
 
207
140
        self.wt = self.make_branch_and_tree('.')
208
141
        self.branch = self.wt.branch
209
142
        print >> open('file', 'wb'), 'foo'
210
 
        print >> open('binfile', 'wb'), 'foo'
211
143
        self.wt.add(['file'], ['fileid'])
212
 
        self.wt.add(['binfile'], ['binfileid'])
213
144
        if has_symlinks():
214
145
            os.symlink('target1', 'symlink')
215
146
            self.wt.add(['symlink'], ['linkid'])
216
147
        self.wt.commit('message_1', rev_id = '1')
217
148
        print >> open('file', 'wb'), 'bar'
218
 
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
219
149
        if has_symlinks():
220
150
            os.unlink('symlink')
221
151
            os.symlink('target2', 'symlink')
222
152
        self.tree_1 = self.branch.repository.revision_tree('1')
223
153
        self.inv_1 = self.branch.repository.get_inventory('1')
224
154
        self.file_1 = self.inv_1['fileid']
225
 
        self.file_1b = self.inv_1['binfileid']
226
 
        self.tree_2 = self.wt
 
155
        self.tree_2 = self.branch.working_tree()
227
156
        self.inv_2 = self.tree_2.read_working_inventory()
228
157
        self.file_2 = self.inv_2['fileid']
229
 
        self.file_2b = self.inv_2['binfileid']
230
158
        if has_symlinks():
231
159
            self.link_1 = self.inv_1['linkid']
232
160
            self.link_2 = self.inv_2['linkid']
237
165
                          "old_label", self.tree_1,
238
166
                          "/dev/null", None, None,
239
167
                          output)
240
 
        self.assertEqual(output.getvalue(), "--- old_label\n"
241
 
                                            "+++ /dev/null\n"
 
168
        self.assertEqual(output.getvalue(), "--- old_label\t\n"
 
169
                                            "+++ /dev/null\t\n"
242
170
                                            "@@ -1,1 +0,0 @@\n"
243
171
                                            "-foo\n"
244
172
                                            "\n")
249
177
                          "new_label", self.tree_1,
250
178
                          "/dev/null", None, None,
251
179
                          output, reverse=True)
252
 
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
253
 
                                            "+++ new_label\n"
 
180
        self.assertEqual(output.getvalue(), "--- /dev/null\t\n"
 
181
                                            "+++ new_label\t\n"
254
182
                                            "@@ -0,0 +1,1 @@\n"
255
183
                                            "+foo\n"
256
184
                                            "\n")
261
189
                          "/dev/null", self.tree_1, 
262
190
                          "new_label", self.file_2, self.tree_2,
263
191
                          output)
264
 
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
265
 
                                            "+++ new_label\n"
 
192
        self.assertEqual(output.getvalue(), "--- /dev/null\t\n"
 
193
                                            "+++ new_label\t\n"
266
194
                                            "@@ -1,1 +1,1 @@\n"
267
195
                                            "-foo\n"
268
196
                                            "+bar\n"
269
197
                                            "\n")
270
198
        
271
 
    def test_file_diff_binary(self):
272
 
        output = StringIO()
273
 
        self.file_1.diff(internal_diff, 
274
 
                          "/dev/null", self.tree_1, 
275
 
                          "new_label", self.file_2b, self.tree_2,
276
 
                          output)
277
 
        self.assertEqual(output.getvalue(), 
278
 
                         "Binary files /dev/null and new_label differ\n")
279
199
    def test_link_diff_deleted(self):
280
200
        if not has_symlinks():
281
201
            return
332
252
        self.inv_1 = self.branch.repository.get_inventory('1')
333
253
        self.file_1 = self.inv_1['fileid']
334
254
        self.file_active = self.wt.inventory['fileid']
335
 
        self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
336
255
 
337
256
    def test_snapshot_new_revision(self):
338
257
        # This tests that a simple commit with no parents makes a new
339
258
        # revision value in the inventory entry
340
 
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
 
259
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, 
 
260
                                  self.branch.repository.weave_store,
 
261
                                  self.branch.get_transaction())
341
262
        # expected outcome - file_1 has a revision id of '2', and we can get
342
263
        # its text of 'file contents' out of the weave.
343
264
        self.assertEqual(self.file_1.revision, '1')
344
265
        self.assertEqual(self.file_active.revision, '2')
345
266
        # this should be a separate test probably, but lets check it once..
346
 
        lines = self.branch.repository.weave_store.get_weave(
347
 
            'fileid', 
348
 
            self.branch.get_transaction()).get_lines('2')
 
267
        lines = self.branch.repository.weave_store.get_lines('fileid','2',
 
268
            self.branch.get_transaction())
349
269
        self.assertEqual(lines, ['contents of subdir/file\n'])
350
270
 
351
271
    def test_snapshot_unchanged(self):
352
272
        #This tests that a simple commit does not make a new entry for
353
273
        # an unchanged inventory entry
354
274
        self.file_active.snapshot('2', 'subdir/file', {'1':self.file_1},
355
 
                                  self.wt, self.builder)
 
275
                                  self.wt, 
 
276
                                  self.branch.repository.weave_store,
 
277
                                  self.branch.get_transaction())
356
278
        self.assertEqual(self.file_1.revision, '1')
357
279
        self.assertEqual(self.file_active.revision, '1')
358
 
        vf = self.branch.repository.weave_store.get_weave(
359
 
            'fileid', 
360
 
            self.branch.repository.get_transaction())
361
 
        self.assertRaises(errors.RevisionNotPresent,
362
 
                          vf.get_lines,
363
 
                          '2')
 
280
        self.assertRaises(errors.WeaveError,
 
281
                          self.branch.repository.weave_store.get_lines, 
 
282
                          'fileid', '2', self.branch.get_transaction())
364
283
 
365
284
    def test_snapshot_merge_identical_different_revid(self):
366
285
        # This tests that a commit with two identical parents, one of which has
374
293
        self.assertEqual(self.file_1, other_ie)
375
294
        other_ie.revision = 'other'
376
295
        self.assertNotEqual(self.file_1, other_ie)
377
 
        versionfile = self.branch.repository.weave_store.get_weave(
378
 
            'fileid', self.branch.repository.get_transaction())
379
 
        versionfile.clone_text('other', '1', ['1'])
 
296
        self.branch.repository.weave_store.add_identical_text('fileid', '1', 
 
297
            'other', ['1'], self.branch.get_transaction())
380
298
        self.file_active.snapshot('2', 'subdir/file', 
381
299
                                  {'1':self.file_1, 'other':other_ie},
382
 
                                  self.wt, self.builder)
 
300
                                  self.wt, 
 
301
                                  self.branch.repository.weave_store,
 
302
                                  self.branch.get_transaction())
383
303
        self.assertEqual(self.file_active.revision, '2')
384
304
 
385
305
    def test_snapshot_changed(self):
388
308
        self.file_active.name='newname'
389
309
        rename('subdir/file', 'subdir/newname')
390
310
        self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1}, 
391
 
                                  self.wt, self.builder)
 
311
                                  self.wt,
 
312
                                  self.branch.repository.weave_store,
 
313
                                  self.branch.get_transaction())
392
314
        # expected outcome - file_1 has a revision id of '2'
393
315
        self.assertEqual(self.file_active.revision, '2')
394
316
 
413
335
        self.wt.add(['file'], ['fileid'])
414
336
        self.wt.commit('add file', rev_id='B')
415
337
        self.inv_B = self.branch.repository.get_inventory('B')
416
 
        uncommit(self.branch, tree=self.wt)
 
338
        self.branch.lock_write()
 
339
        try:
 
340
            self.branch.control_files.put_utf8('revision-history', 'A\n')
 
341
        finally:
 
342
            self.branch.unlock()
417
343
        self.assertEqual(self.branch.revision_history(), ['A'])
418
344
        self.wt.commit('another add of file', rev_id='C')
419
345
        self.inv_C = self.branch.repository.get_inventory('C')
420
346
        self.wt.add_pending_merge('B')
421
347
        self.wt.commit('merge in B', rev_id='D')
422
348
        self.inv_D = self.branch.repository.get_inventory('D')
423
 
        self.file_active = self.wt.inventory['fileid']
 
349
        self.file_active = self.branch.working_tree().inventory['fileid']
424
350
        self.weave = self.branch.repository.weave_store.get_weave('fileid',
425
 
            self.branch.repository.get_transaction())
 
351
            self.branch.get_transaction())
426
352
        
427
353
    def get_previous_heads(self, inventories):
428
 
        return self.file_active.find_previous_heads(
429
 
            inventories, 
430
 
            self.branch.repository.weave_store,
431
 
            self.branch.repository.get_transaction())
 
354
        return self.file_active.find_previous_heads(inventories, self.weave)
432
355
        
433
356
    def test_fileid_in_no_inventory(self):
434
357
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
458
381
    # TODO: test two inventories with the same file revision 
459
382
 
460
383
 
461
 
class TestDescribeChanges(TestCase):
462
 
 
463
 
    def test_describe_change(self):
464
 
        # we need to test the following change combinations:
465
 
        # rename
466
 
        # reparent
467
 
        # modify
468
 
        # gone
469
 
        # added
470
 
        # renamed/reparented and modified
471
 
        # change kind (perhaps can't be done yet?)
472
 
        # also, merged in combination with all of these?
473
 
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
474
 
        old_a.text_sha1 = '123132'
475
 
        old_a.text_size = 0
476
 
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
477
 
        new_a.text_sha1 = '123132'
478
 
        new_a.text_size = 0
479
 
 
480
 
        self.assertChangeDescription('unchanged', old_a, new_a)
481
 
 
482
 
        new_a.text_size = 10
483
 
        new_a.text_sha1 = 'abcabc'
484
 
        self.assertChangeDescription('modified', old_a, new_a)
485
 
 
486
 
        self.assertChangeDescription('added', None, new_a)
487
 
        self.assertChangeDescription('removed', old_a, None)
488
 
        # perhaps a bit questionable but seems like the most reasonable thing...
489
 
        self.assertChangeDescription('unchanged', None, None)
490
 
 
491
 
        # in this case it's both renamed and modified; show a rename and 
492
 
        # modification:
493
 
        new_a.name = 'newfilename'
494
 
        self.assertChangeDescription('modified and renamed', old_a, new_a)
495
 
 
496
 
        # reparenting is 'renaming'
497
 
        new_a.name = old_a.name
498
 
        new_a.parent_id = 'somedir-id'
499
 
        self.assertChangeDescription('modified and renamed', old_a, new_a)
500
 
 
501
 
        # reset the content values so its not modified
502
 
        new_a.text_size = old_a.text_size
503
 
        new_a.text_sha1 = old_a.text_sha1
504
 
        new_a.name = old_a.name
505
 
 
506
 
        new_a.name = 'newfilename'
507
 
        self.assertChangeDescription('renamed', old_a, new_a)
508
 
 
509
 
        # reparenting is 'renaming'
510
 
        new_a.name = old_a.name
511
 
        new_a.parent_id = 'somedir-id'
512
 
        self.assertChangeDescription('renamed', old_a, new_a)
513
 
 
514
 
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
515
 
        change = InventoryEntry.describe_change(old_ie, new_ie)
516
 
        self.assertEqual(expected_change, change)
517
 
 
518
 
 
519
384
class TestExecutable(TestCaseWithTransport):
520
385
 
521
386
    def test_stays_executable(self):
 
387
        basic_inv = """<inventory format="5">
 
388
<file file_id="a-20051208024829-849e76f7968d7a86" name="a" executable="yes" />
 
389
<file file_id="b-20051208024829-849e76f7968d7a86" name="b" />
 
390
</inventory>
 
391
"""
 
392
        wt = self.make_branch_and_tree('b1')
 
393
        b = wt.branch
 
394
        open('b1/a', 'wb').write('a test\n')
 
395
        open('b1/b', 'wb').write('b test\n')
 
396
        os.chmod('b1/a', 0755)
 
397
        os.chmod('b1/b', 0644)
 
398
        # Manually writing the inventory, to ensure that
 
399
        # the executable="yes" entry is set for 'a' and not for 'b'
 
400
        open('b1/.bzr/inventory', 'wb').write(basic_inv)
 
401
 
522
402
        a_id = "a-20051208024829-849e76f7968d7a86"
523
403
        b_id = "b-20051208024829-849e76f7968d7a86"
524
 
        wt = self.make_branch_and_tree('b1')
525
 
        b = wt.branch
526
 
        tt = TreeTransform(wt)
527
 
        tt.new_file('a', tt.root, 'a test\n', a_id, True)
528
 
        tt.new_file('b', tt.root, 'b test\n', b_id, False)
529
 
        tt.apply()
530
 
 
531
 
        self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
532
 
 
533
 
        # reopen the tree and ensure it stuck.
534
 
        wt = wt.bzrdir.open_workingtree()
535
 
        self.assertEqual(['a', 'b'], [cn for cn,ie in wt.inventory.iter_entries()])
536
 
 
537
 
        self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
538
 
        self.failIf(wt.is_executable(b_id), "'b' gained an execute bit")
539
 
 
540
 
        wt.commit('adding a,b', rev_id='r1')
 
404
        t = WorkingTree('b1', b)
 
405
        self.assertEqual(['a', 'b'], [cn for cn,ie in t.inventory.iter_entries()])
 
406
 
 
407
        self.failUnless(t.is_executable(a_id), "'a' lost the execute bit")
 
408
        self.failIf(t.is_executable(b_id), "'b' gained an execute bit")
 
409
 
 
410
        t.commit('adding a,b', rev_id='r1')
541
411
 
542
412
        rev_tree = b.repository.revision_tree('r1')
543
413
        self.failUnless(rev_tree.is_executable(a_id), "'a' lost the execute bit")
549
419
        # Make sure the entries are gone
550
420
        os.remove('b1/a')
551
421
        os.remove('b1/b')
552
 
        self.failIf(wt.has_id(a_id))
553
 
        self.failIf(wt.has_filename('a'))
554
 
        self.failIf(wt.has_id(b_id))
555
 
        self.failIf(wt.has_filename('b'))
 
422
        self.failIf(t.has_id(a_id))
 
423
        self.failIf(t.has_filename('a'))
 
424
        self.failIf(t.has_id(b_id))
 
425
        self.failIf(t.has_filename('b'))
556
426
 
557
427
        # Make sure that revert is able to bring them back,
558
428
        # and sets 'a' back to being executable
559
429
 
560
 
        wt.revert(['a', 'b'], rev_tree, backups=False)
561
 
        self.assertEqual(['a', 'b'], [cn for cn,ie in wt.inventory.iter_entries()])
 
430
        t.revert(['a', 'b'], rev_tree, backups=False)
 
431
        self.assertEqual(['a', 'b'], [cn for cn,ie in t.inventory.iter_entries()])
562
432
 
563
 
        self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
564
 
        self.failIf(wt.is_executable(b_id), "'b' gained an execute bit")
 
433
        self.failUnless(t.is_executable(a_id), "'a' lost the execute bit")
 
434
        self.failIf(t.is_executable(b_id), "'b' gained an execute bit")
565
435
 
566
436
        # Now remove them again, and make sure that after a
567
437
        # commit, they are still marked correctly
568
438
        os.remove('b1/a')
569
439
        os.remove('b1/b')
570
 
        wt.commit('removed', rev_id='r2')
 
440
        t.commit('removed', rev_id='r2')
571
441
 
572
 
        self.assertEqual([], [cn for cn,ie in wt.inventory.iter_entries()])
573
 
        self.failIf(wt.has_id(a_id))
574
 
        self.failIf(wt.has_filename('a'))
575
 
        self.failIf(wt.has_id(b_id))
576
 
        self.failIf(wt.has_filename('b'))
 
442
        self.assertEqual([], [cn for cn,ie in t.inventory.iter_entries()])
 
443
        self.failIf(t.has_id(a_id))
 
444
        self.failIf(t.has_filename('a'))
 
445
        self.failIf(t.has_id(b_id))
 
446
        self.failIf(t.has_filename('b'))
577
447
 
578
448
        # Now revert back to the previous commit
579
 
        wt.revert([], rev_tree, backups=False)
580
 
        self.assertEqual(['a', 'b'], [cn for cn,ie in wt.inventory.iter_entries()])
581
 
 
582
 
        self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
583
 
        self.failIf(wt.is_executable(b_id), "'b' gained an execute bit")
 
449
        t.revert([], rev_tree, backups=False)
 
450
        # TODO: FIXME: For some reason, after revert, the tree does not 
 
451
        # regenerate its working inventory, so we have to manually delete
 
452
        # the working tree, and create a new one
 
453
        # This seems to happen any time you do a merge operation on the
 
454
        # working tree
 
455
        del t
 
456
        t = WorkingTree('b1', b)
 
457
 
 
458
        self.assertEqual(['a', 'b'], [cn for cn,ie in t.inventory.iter_entries()])
 
459
 
 
460
        self.failUnless(t.is_executable(a_id), "'a' lost the execute bit")
 
461
        self.failIf(t.is_executable(b_id), "'b' gained an execute bit")
584
462
 
585
463
        # Now make sure that 'bzr branch' also preserves the
586
464
        # executable bit
587
465
        # TODO: Maybe this should be a blackbox test
588
 
        d2 = b.bzrdir.clone('b2', revision_id='r1')
589
 
        t2 = d2.open_workingtree()
590
 
        b2 = t2.branch
 
466
        b.clone('b2', revision='r1')
 
467
        b2 = Branch.open('b2')
591
468
        self.assertEquals('r1', b2.last_revision())
 
469
        t2 = b2.working_tree()
592
470
 
593
471
        self.assertEqual(['a', 'b'], [cn for cn,ie in t2.inventory.iter_entries()])
594
472
        self.failUnless(t2.is_executable(a_id), "'a' lost the execute bit")
597
475
        # Make sure pull will delete the files
598
476
        t2.pull(b)
599
477
        self.assertEquals('r2', b2.last_revision())
 
478
        # FIXME: Same thing here, t2 needs to be recreated
 
479
        del t2
 
480
        t2 = b2.working_tree()
600
481
        self.assertEqual([], [cn for cn,ie in t2.inventory.iter_entries()])
601
482
 
602
483
        # Now commit the changes on the first branch
603
484
        # so that the second branch can pull the changes
604
485
        # and make sure that the executable bit has been copied
605
 
        wt.commit('resurrected', rev_id='r3')
 
486
        t.commit('resurrected', rev_id='r3')
606
487
 
607
488
        t2.pull(b)
 
489
        # FIXME: And here
 
490
        del t2
 
491
        t2 = b2.working_tree()
608
492
        self.assertEquals('r3', b2.last_revision())
609
493
        self.assertEqual(['a', 'b'], [cn for cn,ie in t2.inventory.iter_entries()])
610
494
 
611
495
        self.failUnless(t2.is_executable(a_id), "'a' lost the execute bit")
612
496
        self.failIf(t2.is_executable(b_id), "'b' gained an execute bit")
613
 
 
614
 
 
615
 
class TestRevert(TestCaseWithTransport):
616
 
 
617
 
    def test_dangling_id(self):
618
 
        wt = self.make_branch_and_tree('b1')
619
 
        self.assertEqual(len(wt.inventory), 1)
620
 
        open('b1/a', 'wb').write('a test\n')
621
 
        wt.add('a')
622
 
        self.assertEqual(len(wt.inventory), 2)
623
 
        os.unlink('b1/a')
624
 
        wt.revert([])
625
 
        self.assertEqual(len(wt.inventory), 1)