~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testinv.py

  • Committer: Robert Collins
  • Date: 2005-09-27 07:24:40 UTC
  • mfrom: (1185.1.41)
  • Revision ID: robertc@robertcollins.net-20050927072440-1bf4d99c3e1db5b3
pair programming worx... merge integration and weave

Show diffs side-by-side

added added

removed removed

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