~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-07-12 03:22:41 UTC
  • mfrom: (1711.2.86 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20060712032241-2352b3ef35093aa1
(jam) minor cleanups, updates to NEWS for bug fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
from bzrlib.selftest import TestCase
 
17
from cStringIO import StringIO
 
18
import os
 
19
import time
18
20
 
19
 
from bzrlib.inventory import Inventory, InventoryEntry
 
21
from bzrlib import errors, inventory, osutils
 
22
from bzrlib.branch import Branch
 
23
from bzrlib.diff import internal_diff
 
24
from bzrlib.inventory import (Inventory, ROOT_ID, InventoryFile,
 
25
    InventoryDirectory, InventoryEntry)
 
26
from bzrlib.osutils import (has_symlinks, rename, pathjoin, is_inside_any, 
 
27
    is_inside_or_parent_of_any)
 
28
from bzrlib.tests import TestCase, TestCaseWithTransport
 
29
from bzrlib.transform import TreeTransform
 
30
from bzrlib.uncommit import uncommit
20
31
 
21
32
 
22
33
class TestInventory(TestCase):
23
34
 
24
35
    def test_is_within(self):
25
 
        from bzrlib.osutils import is_inside_any
26
 
        
 
36
 
 
37
        SRC_FOO_C = pathjoin('src', 'foo.c')
 
38
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
 
39
                         (['src'], SRC_FOO_C),
 
40
                         (['src'], 'src'),
 
41
                         ]:
 
42
            self.assert_(is_inside_any(dirs, fn))
 
43
            
 
44
        for dirs, fn in [(['src'], 'srccontrol'),
 
45
                         (['src'], 'srccontrol/foo')]:
 
46
            self.assertFalse(is_inside_any(dirs, fn))
 
47
 
 
48
    def test_is_within_or_parent(self):
27
49
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
28
50
                         (['src'], 'src/foo.c'),
 
51
                         (['src/bar.c'], 'src'),
 
52
                         (['src/bar.c', 'bla/foo.c'], 'src'),
29
53
                         (['src'], 'src'),
30
54
                         ]:
31
 
            self.assert_(is_inside_any(dirs, fn))
 
55
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
32
56
            
33
57
        for dirs, fn in [(['src'], 'srccontrol'),
 
58
                         (['srccontrol/foo.c'], 'src'),
34
59
                         (['src'], 'srccontrol/foo')]:
35
 
            self.assertFalse(is_inside_any(dirs, fn))
36
 
            
 
60
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
 
61
 
37
62
    def test_ids(self):
38
63
        """Test detection of files within selected directories."""
39
64
        inv = Inventory()
50
75
        
51
76
        self.assert_('src-id' in inv)
52
77
 
53
 
 
 
78
    def test_iter_entries(self):
 
79
        inv = Inventory()
 
80
        
 
81
        for args in [('src', 'directory', 'src-id'), 
 
82
                     ('doc', 'directory', 'doc-id'), 
 
83
                     ('src/hello.c', 'file', 'hello-id'),
 
84
                     ('src/bye.c', 'file', 'bye-id'),
 
85
                     ('Makefile', 'file', 'makefile-id')]:
 
86
            inv.add_path(*args)
 
87
 
 
88
        self.assertEqual([
 
89
            ('Makefile', 'makefile-id'),
 
90
            ('doc', 'doc-id'),
 
91
            ('src', 'src-id'),
 
92
            ('src/bye.c', 'bye-id'),
 
93
            ('src/hello.c', 'hello-id'),
 
94
            ], [(path, ie.file_id) for path, ie in inv.iter_entries()])
 
95
            
 
96
    def test_iter_entries_by_dir(self):
 
97
        inv = Inventory()
 
98
        
 
99
        for args in [('src', 'directory', 'src-id'), 
 
100
                     ('doc', 'directory', 'doc-id'), 
 
101
                     ('src/hello.c', 'file', 'hello-id'),
 
102
                     ('src/bye.c', 'file', 'bye-id'),
 
103
                     ('zz', 'file', 'zz-id'),
 
104
                     ('src/sub/', 'directory', 'sub-id'),
 
105
                     ('src/zz.c', 'file', 'zzc-id'),
 
106
                     ('src/sub/a', 'file', 'a-id'),
 
107
                     ('Makefile', 'file', 'makefile-id')]:
 
108
            inv.add_path(*args)
 
109
 
 
110
        self.assertEqual([
 
111
            ('Makefile', 'makefile-id'),
 
112
            ('doc', 'doc-id'),
 
113
            ('src', 'src-id'),
 
114
            ('zz', 'zz-id'),
 
115
            ('src/bye.c', 'bye-id'),
 
116
            ('src/hello.c', 'hello-id'),
 
117
            ('src/sub', 'sub-id'),
 
118
            ('src/zz.c', 'zzc-id'),
 
119
            ('src/sub/a', 'a-id'),
 
120
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir()])
 
121
            
54
122
    def test_version(self):
55
123
        """Inventory remembers the text's version."""
56
124
        inv = Inventory()
57
125
        ie = inv.add_path('foo.txt', 'file')
58
126
        ## XXX
59
127
 
 
128
 
 
129
class TestInventoryEntry(TestCase):
 
130
 
 
131
    def test_file_kind_character(self):
 
132
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
133
        self.assertEqual(file.kind_character(), '')
 
134
 
 
135
    def test_dir_kind_character(self):
 
136
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
137
        self.assertEqual(dir.kind_character(), '/')
 
138
 
 
139
    def test_link_kind_character(self):
 
140
        dir = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
141
        self.assertEqual(dir.kind_character(), '')
 
142
 
 
143
    def test_dir_detect_changes(self):
 
144
        left = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
145
        left.text_sha1 = 123
 
146
        left.executable = True
 
147
        left.symlink_target='foo'
 
148
        right = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
149
        right.text_sha1 = 321
 
150
        right.symlink_target='bar'
 
151
        self.assertEqual((False, False), left.detect_changes(right))
 
152
        self.assertEqual((False, False), right.detect_changes(left))
 
153
 
 
154
    def test_file_detect_changes(self):
 
155
        left = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
156
        left.text_sha1 = 123
 
157
        right = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
158
        right.text_sha1 = 123
 
159
        self.assertEqual((False, False), left.detect_changes(right))
 
160
        self.assertEqual((False, False), right.detect_changes(left))
 
161
        left.executable = True
 
162
        self.assertEqual((False, True), left.detect_changes(right))
 
163
        self.assertEqual((False, True), right.detect_changes(left))
 
164
        right.text_sha1 = 321
 
165
        self.assertEqual((True, True), left.detect_changes(right))
 
166
        self.assertEqual((True, True), right.detect_changes(left))
 
167
 
 
168
    def test_symlink_detect_changes(self):
 
169
        left = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
170
        left.text_sha1 = 123
 
171
        left.executable = True
 
172
        left.symlink_target='foo'
 
173
        right = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
174
        right.text_sha1 = 321
 
175
        right.symlink_target='foo'
 
176
        self.assertEqual((False, False), left.detect_changes(right))
 
177
        self.assertEqual((False, False), right.detect_changes(left))
 
178
        left.symlink_target = 'different'
 
179
        self.assertEqual((True, False), left.detect_changes(right))
 
180
        self.assertEqual((True, False), right.detect_changes(left))
 
181
 
 
182
    def test_file_has_text(self):
 
183
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
 
184
        self.failUnless(file.has_text())
 
185
 
 
186
    def test_directory_has_text(self):
 
187
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
 
188
        self.failIf(dir.has_text())
 
189
 
 
190
    def test_link_has_text(self):
 
191
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
 
192
        self.failIf(link.has_text())
 
193
 
 
194
    def test_make_entry(self):
 
195
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
 
196
            inventory.InventoryFile)
 
197
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
 
198
            inventory.InventoryLink)
 
199
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
 
200
            inventory.InventoryDirectory)
 
201
 
 
202
    def test_make_entry_non_normalized(self):
 
203
        orig_normalized_filename = osutils.normalized_filename
 
204
 
 
205
        try:
 
206
            osutils.normalized_filename = osutils._accessible_normalized_filename
 
207
            entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
 
208
            self.assertEqual(u'\xe5', entry.name)
 
209
            self.assertIsInstance(entry, inventory.InventoryFile)
 
210
 
 
211
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
 
212
            self.assertRaises(errors.InvalidNormalization,
 
213
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
 
214
        finally:
 
215
            osutils.normalized_filename = orig_normalized_filename
 
216
 
 
217
 
 
218
class TestEntryDiffing(TestCaseWithTransport):
 
219
 
 
220
    def setUp(self):
 
221
        super(TestEntryDiffing, self).setUp()
 
222
        self.wt = self.make_branch_and_tree('.')
 
223
        self.branch = self.wt.branch
 
224
        print >> open('file', 'wb'), 'foo'
 
225
        print >> open('binfile', 'wb'), 'foo'
 
226
        self.wt.add(['file'], ['fileid'])
 
227
        self.wt.add(['binfile'], ['binfileid'])
 
228
        if has_symlinks():
 
229
            os.symlink('target1', 'symlink')
 
230
            self.wt.add(['symlink'], ['linkid'])
 
231
        self.wt.commit('message_1', rev_id = '1')
 
232
        print >> open('file', 'wb'), 'bar'
 
233
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
 
234
        if has_symlinks():
 
235
            os.unlink('symlink')
 
236
            os.symlink('target2', 'symlink')
 
237
        self.tree_1 = self.branch.repository.revision_tree('1')
 
238
        self.inv_1 = self.branch.repository.get_inventory('1')
 
239
        self.file_1 = self.inv_1['fileid']
 
240
        self.file_1b = self.inv_1['binfileid']
 
241
        self.tree_2 = self.wt
 
242
        self.inv_2 = self.tree_2.read_working_inventory()
 
243
        self.file_2 = self.inv_2['fileid']
 
244
        self.file_2b = self.inv_2['binfileid']
 
245
        if has_symlinks():
 
246
            self.link_1 = self.inv_1['linkid']
 
247
            self.link_2 = self.inv_2['linkid']
 
248
 
 
249
    def test_file_diff_deleted(self):
 
250
        output = StringIO()
 
251
        self.file_1.diff(internal_diff, 
 
252
                          "old_label", self.tree_1,
 
253
                          "/dev/null", None, None,
 
254
                          output)
 
255
        self.assertEqual(output.getvalue(), "--- old_label\n"
 
256
                                            "+++ /dev/null\n"
 
257
                                            "@@ -1,1 +0,0 @@\n"
 
258
                                            "-foo\n"
 
259
                                            "\n")
 
260
 
 
261
    def test_file_diff_added(self):
 
262
        output = StringIO()
 
263
        self.file_1.diff(internal_diff, 
 
264
                          "new_label", self.tree_1,
 
265
                          "/dev/null", None, None,
 
266
                          output, reverse=True)
 
267
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
 
268
                                            "+++ new_label\n"
 
269
                                            "@@ -0,0 +1,1 @@\n"
 
270
                                            "+foo\n"
 
271
                                            "\n")
 
272
 
 
273
    def test_file_diff_changed(self):
 
274
        output = StringIO()
 
275
        self.file_1.diff(internal_diff, 
 
276
                          "/dev/null", self.tree_1, 
 
277
                          "new_label", self.file_2, self.tree_2,
 
278
                          output)
 
279
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
 
280
                                            "+++ new_label\n"
 
281
                                            "@@ -1,1 +1,1 @@\n"
 
282
                                            "-foo\n"
 
283
                                            "+bar\n"
 
284
                                            "\n")
 
285
        
 
286
    def test_file_diff_binary(self):
 
287
        output = StringIO()
 
288
        self.file_1.diff(internal_diff, 
 
289
                          "/dev/null", self.tree_1, 
 
290
                          "new_label", self.file_2b, self.tree_2,
 
291
                          output)
 
292
        self.assertEqual(output.getvalue(), 
 
293
                         "Binary files /dev/null and new_label differ\n")
 
294
    def test_link_diff_deleted(self):
 
295
        if not has_symlinks():
 
296
            return
 
297
        output = StringIO()
 
298
        self.link_1.diff(internal_diff, 
 
299
                          "old_label", self.tree_1,
 
300
                          "/dev/null", None, None,
 
301
                          output)
 
302
        self.assertEqual(output.getvalue(),
 
303
                         "=== target was 'target1'\n")
 
304
 
 
305
    def test_link_diff_added(self):
 
306
        if not has_symlinks():
 
307
            return
 
308
        output = StringIO()
 
309
        self.link_1.diff(internal_diff, 
 
310
                          "new_label", self.tree_1,
 
311
                          "/dev/null", None, None,
 
312
                          output, reverse=True)
 
313
        self.assertEqual(output.getvalue(),
 
314
                         "=== target is 'target1'\n")
 
315
 
 
316
    def test_link_diff_changed(self):
 
317
        if not has_symlinks():
 
318
            return
 
319
        output = StringIO()
 
320
        self.link_1.diff(internal_diff, 
 
321
                          "/dev/null", self.tree_1, 
 
322
                          "new_label", self.link_2, self.tree_2,
 
323
                          output)
 
324
        self.assertEqual(output.getvalue(),
 
325
                         "=== target changed 'target1' => 'target2'\n")
 
326
 
 
327
 
 
328
class TestSnapshot(TestCaseWithTransport):
 
329
 
 
330
    def setUp(self):
 
331
        # for full testing we'll need a branch
 
332
        # with a subdir to test parent changes.
 
333
        # and a file, link and dir under that.
 
334
        # but right now I only need one attribute
 
335
        # to change, and then test merge patterns
 
336
        # with fake parent entries.
 
337
        super(TestSnapshot, self).setUp()
 
338
        self.wt = self.make_branch_and_tree('.')
 
339
        self.branch = self.wt.branch
 
340
        self.build_tree(['subdir/', 'subdir/file'], line_endings='binary')
 
341
        self.wt.add(['subdir', 'subdir/file'],
 
342
                                       ['dirid', 'fileid'])
 
343
        if has_symlinks():
 
344
            pass
 
345
        self.wt.commit('message_1', rev_id = '1')
 
346
        self.tree_1 = self.branch.repository.revision_tree('1')
 
347
        self.inv_1 = self.branch.repository.get_inventory('1')
 
348
        self.file_1 = self.inv_1['fileid']
 
349
        self.file_active = self.wt.inventory['fileid']
 
350
        self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
 
351
 
 
352
    def test_snapshot_new_revision(self):
 
353
        # This tests that a simple commit with no parents makes a new
 
354
        # revision value in the inventory entry
 
355
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
 
356
        # expected outcome - file_1 has a revision id of '2', and we can get
 
357
        # its text of 'file contents' out of the weave.
 
358
        self.assertEqual(self.file_1.revision, '1')
 
359
        self.assertEqual(self.file_active.revision, '2')
 
360
        # this should be a separate test probably, but lets check it once..
 
361
        lines = self.branch.repository.weave_store.get_weave(
 
362
            'fileid', 
 
363
            self.branch.get_transaction()).get_lines('2')
 
364
        self.assertEqual(lines, ['contents of subdir/file\n'])
 
365
 
 
366
    def test_snapshot_unchanged(self):
 
367
        #This tests that a simple commit does not make a new entry for
 
368
        # an unchanged inventory entry
 
369
        self.file_active.snapshot('2', 'subdir/file', {'1':self.file_1},
 
370
                                  self.wt, self.builder)
 
371
        self.assertEqual(self.file_1.revision, '1')
 
372
        self.assertEqual(self.file_active.revision, '1')
 
373
        vf = self.branch.repository.weave_store.get_weave(
 
374
            'fileid', 
 
375
            self.branch.repository.get_transaction())
 
376
        self.assertRaises(errors.RevisionNotPresent,
 
377
                          vf.get_lines,
 
378
                          '2')
 
379
 
 
380
    def test_snapshot_merge_identical_different_revid(self):
 
381
        # This tests that a commit with two identical parents, one of which has
 
382
        # a different revision id, results in a new revision id in the entry.
 
383
        # 1->other, commit a merge of other against 1, results in 2.
 
384
        other_ie = inventory.InventoryFile('fileid', 'newname', self.file_1.parent_id)
 
385
        other_ie = inventory.InventoryFile('fileid', 'file', self.file_1.parent_id)
 
386
        other_ie.revision = '1'
 
387
        other_ie.text_sha1 = self.file_1.text_sha1
 
388
        other_ie.text_size = self.file_1.text_size
 
389
        self.assertEqual(self.file_1, other_ie)
 
390
        other_ie.revision = 'other'
 
391
        self.assertNotEqual(self.file_1, other_ie)
 
392
        versionfile = self.branch.repository.weave_store.get_weave(
 
393
            'fileid', self.branch.repository.get_transaction())
 
394
        versionfile.clone_text('other', '1', ['1'])
 
395
        self.file_active.snapshot('2', 'subdir/file', 
 
396
                                  {'1':self.file_1, 'other':other_ie},
 
397
                                  self.wt, self.builder)
 
398
        self.assertEqual(self.file_active.revision, '2')
 
399
 
 
400
    def test_snapshot_changed(self):
 
401
        # This tests that a commit with one different parent results in a new
 
402
        # revision id in the entry.
 
403
        self.file_active.name='newname'
 
404
        rename('subdir/file', 'subdir/newname')
 
405
        self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1}, 
 
406
                                  self.wt, self.builder)
 
407
        # expected outcome - file_1 has a revision id of '2'
 
408
        self.assertEqual(self.file_active.revision, '2')
 
409
 
 
410
 
 
411
class TestPreviousHeads(TestCaseWithTransport):
 
412
 
 
413
    def setUp(self):
 
414
        # we want several inventories, that respectively
 
415
        # give use the following scenarios:
 
416
        # A) fileid not in any inventory (A),
 
417
        # B) fileid present in one inventory (B) and (A,B)
 
418
        # C) fileid present in two inventories, and they
 
419
        #   are not mutual descendents (B, C)
 
420
        # D) fileid present in two inventories and one is
 
421
        #   a descendent of the other. (B, D)
 
422
        super(TestPreviousHeads, self).setUp()
 
423
        self.wt = self.make_branch_and_tree('.')
 
424
        self.branch = self.wt.branch
 
425
        self.build_tree(['file'])
 
426
        self.wt.commit('new branch', allow_pointless=True, rev_id='A')
 
427
        self.inv_A = self.branch.repository.get_inventory('A')
 
428
        self.wt.add(['file'], ['fileid'])
 
429
        self.wt.commit('add file', rev_id='B')
 
430
        self.inv_B = self.branch.repository.get_inventory('B')
 
431
        uncommit(self.branch, tree=self.wt)
 
432
        self.assertEqual(self.branch.revision_history(), ['A'])
 
433
        self.wt.commit('another add of file', rev_id='C')
 
434
        self.inv_C = self.branch.repository.get_inventory('C')
 
435
        self.wt.add_pending_merge('B')
 
436
        self.wt.commit('merge in B', rev_id='D')
 
437
        self.inv_D = self.branch.repository.get_inventory('D')
 
438
        self.file_active = self.wt.inventory['fileid']
 
439
        self.weave = self.branch.repository.weave_store.get_weave('fileid',
 
440
            self.branch.repository.get_transaction())
 
441
        
 
442
    def get_previous_heads(self, inventories):
 
443
        return self.file_active.find_previous_heads(
 
444
            inventories, 
 
445
            self.branch.repository.weave_store,
 
446
            self.branch.repository.get_transaction())
 
447
        
 
448
    def test_fileid_in_no_inventory(self):
 
449
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
 
450
 
 
451
    def test_fileid_in_one_inventory(self):
 
452
        self.assertEqual({'B':self.inv_B['fileid']},
 
453
                         self.get_previous_heads([self.inv_B]))
 
454
        self.assertEqual({'B':self.inv_B['fileid']},
 
455
                         self.get_previous_heads([self.inv_A, self.inv_B]))
 
456
        self.assertEqual({'B':self.inv_B['fileid']},
 
457
                         self.get_previous_heads([self.inv_B, self.inv_A]))
 
458
 
 
459
    def test_fileid_in_two_inventories_gives_both_entries(self):
 
460
        self.assertEqual({'B':self.inv_B['fileid'],
 
461
                          'C':self.inv_C['fileid']},
 
462
                          self.get_previous_heads([self.inv_B, self.inv_C]))
 
463
        self.assertEqual({'B':self.inv_B['fileid'],
 
464
                          'C':self.inv_C['fileid']},
 
465
                          self.get_previous_heads([self.inv_C, self.inv_B]))
 
466
 
 
467
    def test_fileid_in_two_inventories_already_merged_gives_head(self):
 
468
        self.assertEqual({'D':self.inv_D['fileid']},
 
469
                         self.get_previous_heads([self.inv_B, self.inv_D]))
 
470
        self.assertEqual({'D':self.inv_D['fileid']},
 
471
                         self.get_previous_heads([self.inv_D, self.inv_B]))
 
472
 
 
473
    # TODO: test two inventories with the same file revision 
 
474
 
 
475
 
 
476
class TestDescribeChanges(TestCase):
 
477
 
 
478
    def test_describe_change(self):
 
479
        # we need to test the following change combinations:
 
480
        # rename
 
481
        # reparent
 
482
        # modify
 
483
        # gone
 
484
        # added
 
485
        # renamed/reparented and modified
 
486
        # change kind (perhaps can't be done yet?)
 
487
        # also, merged in combination with all of these?
 
488
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
 
489
        old_a.text_sha1 = '123132'
 
490
        old_a.text_size = 0
 
491
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
 
492
        new_a.text_sha1 = '123132'
 
493
        new_a.text_size = 0
 
494
 
 
495
        self.assertChangeDescription('unchanged', old_a, new_a)
 
496
 
 
497
        new_a.text_size = 10
 
498
        new_a.text_sha1 = 'abcabc'
 
499
        self.assertChangeDescription('modified', old_a, new_a)
 
500
 
 
501
        self.assertChangeDescription('added', None, new_a)
 
502
        self.assertChangeDescription('removed', old_a, None)
 
503
        # perhaps a bit questionable but seems like the most reasonable thing...
 
504
        self.assertChangeDescription('unchanged', None, None)
 
505
 
 
506
        # in this case it's both renamed and modified; show a rename and 
 
507
        # modification:
 
508
        new_a.name = 'newfilename'
 
509
        self.assertChangeDescription('modified and renamed', old_a, new_a)
 
510
 
 
511
        # reparenting is 'renaming'
 
512
        new_a.name = old_a.name
 
513
        new_a.parent_id = 'somedir-id'
 
514
        self.assertChangeDescription('modified and renamed', old_a, new_a)
 
515
 
 
516
        # reset the content values so its not modified
 
517
        new_a.text_size = old_a.text_size
 
518
        new_a.text_sha1 = old_a.text_sha1
 
519
        new_a.name = old_a.name
 
520
 
 
521
        new_a.name = 'newfilename'
 
522
        self.assertChangeDescription('renamed', old_a, new_a)
 
523
 
 
524
        # reparenting is 'renaming'
 
525
        new_a.name = old_a.name
 
526
        new_a.parent_id = 'somedir-id'
 
527
        self.assertChangeDescription('renamed', old_a, new_a)
 
528
 
 
529
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
 
530
        change = InventoryEntry.describe_change(old_ie, new_ie)
 
531
        self.assertEqual(expected_change, change)
 
532
 
 
533
 
 
534
class TestRevert(TestCaseWithTransport):
 
535
 
 
536
    def test_dangling_id(self):
 
537
        wt = self.make_branch_and_tree('b1')
 
538
        self.assertEqual(len(wt.inventory), 1)
 
539
        open('b1/a', 'wb').write('a test\n')
 
540
        wt.add('a')
 
541
        self.assertEqual(len(wt.inventory), 2)
 
542
        os.unlink('b1/a')
 
543
        wt.revert([])
 
544
        self.assertEqual(len(wt.inventory), 1)