~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: Martin Pool
  • Date: 2005-07-07 07:57:12 UTC
  • mto: This revision was merged to the branch mainline in revision 852.
  • Revision ID: mbp@sourcefrog.net-20050707075712-4784aa908809b905
- preliminary merge conflict detection

Show diffs side-by-side

added added

removed removed

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