/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testinv.py

  • Committer: Martin Pool
  • Date: 2005-08-04 22:04:40 UTC
  • Revision ID: mbp@sourcefrog.net-20050804220440-99562df8151d1ac5
- add pending merge from aaron

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
 
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, TreeReference)
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),
 
17
from bzrlib.selftest import TestBase
 
18
 
 
19
from bzrlib.inventory import Inventory, InventoryEntry
 
20
 
 
21
 
 
22
class TestIsWithin(TestBase):
 
23
    def runTest(self):
 
24
        from bzrlib.osutils import is_inside_any
 
25
        
 
26
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
 
27
                         (['src'], 'src/foo.c'),
48
28
                         (['src'], 'src'),
49
29
                         ]:
50
30
            self.assert_(is_inside_any(dirs, fn))
52
32
        for dirs, fn in [(['src'], 'srccontrol'),
53
33
                         (['src'], 'srccontrol/foo')]:
54
34
            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):
 
35
            
 
36
            
 
37
            
 
38
class TestInventoryIds(TestBase):
 
39
    def runTest(self):
71
40
        """Test detection of files within selected directories."""
72
41
        inv = Inventory()
73
42
        
82
51
        self.assertEqual(inv.path2id('src/bye.c'), 'bye-id')
83
52
        
84
53
        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
 
        self.assertEqual([
143
 
            ('', ROOT_ID),
144
 
            ('Makefile', 'makefile-id'),
145
 
            ('doc', 'doc-id'),
146
 
            ('src', 'src-id'),
147
 
            ('zz', 'zz-id'),
148
 
            ('src/bye.c', 'bye-id'),
149
 
            ('src/hello.c', 'hello-id'),
150
 
            ('src/sub', 'sub-id'),
151
 
            ('src/zz.c', 'zzc-id'),
152
 
            ('src/sub/a', 'a-id'),
153
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
154
 
                specific_file_ids=('a-id', 'zzc-id', 'doc-id', ROOT_ID,
155
 
                'hello-id', 'bye-id', 'zz-id', 'src-id', 'makefile-id', 
156
 
                'sub-id'))])
157
 
 
158
 
        self.assertEqual([
159
 
            ('Makefile', 'makefile-id'),
160
 
            ('doc', 'doc-id'),
161
 
            ('zz', 'zz-id'),
162
 
            ('src/bye.c', 'bye-id'),
163
 
            ('src/hello.c', 'hello-id'),
164
 
            ('src/zz.c', 'zzc-id'),
165
 
            ('src/sub/a', 'a-id'),
166
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
167
 
                specific_file_ids=('a-id', 'zzc-id', 'doc-id',
168
 
                'hello-id', 'bye-id', 'zz-id', 'makefile-id'))])
169
 
 
170
 
        self.assertEqual([
171
 
            ('Makefile', 'makefile-id'),
172
 
            ('src/bye.c', 'bye-id'),
173
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
174
 
                specific_file_ids=('bye-id', 'makefile-id'))])
175
 
 
176
 
        self.assertEqual([
177
 
            ('Makefile', 'makefile-id'),
178
 
            ('src/bye.c', 'bye-id'),
179
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
180
 
                specific_file_ids=('bye-id', 'makefile-id'))])
181
 
 
182
 
        self.assertEqual([
183
 
            ('src/bye.c', 'bye-id'),
184
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
185
 
                specific_file_ids=('bye-id',))])
186
 
 
187
 
    def test_version(self):
188
 
        """Inventory remembers the text's version."""
189
 
        inv = Inventory()
190
 
        ie = inv.add_path('foo.txt', 'file')
191
 
        ## XXX
192
 
 
193
 
    def test_add_recursive(self):
194
 
        parent = InventoryDirectory('src-id', 'src', ROOT_ID)
195
 
        child = InventoryFile('hello-id', 'hello.c', 'src-id')
196
 
        parent.children[child.file_id] = child
197
 
        inv = Inventory()
198
 
        inv.add(parent)
199
 
        self.assertEqual('src/hello.c', inv.id2path('hello-id'))
200
 
 
201
 
 
202
 
class TestInventoryEntry(TestCase):
203
 
 
204
 
    def test_file_kind_character(self):
205
 
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
206
 
        self.assertEqual(file.kind_character(), '')
207
 
 
208
 
    def test_dir_kind_character(self):
209
 
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
210
 
        self.assertEqual(dir.kind_character(), '/')
211
 
 
212
 
    def test_link_kind_character(self):
213
 
        dir = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
214
 
        self.assertEqual(dir.kind_character(), '')
215
 
 
216
 
    def test_dir_detect_changes(self):
217
 
        left = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
218
 
        left.text_sha1 = 123
219
 
        left.executable = True
220
 
        left.symlink_target='foo'
221
 
        right = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
222
 
        right.text_sha1 = 321
223
 
        right.symlink_target='bar'
224
 
        self.assertEqual((False, False), left.detect_changes(right))
225
 
        self.assertEqual((False, False), right.detect_changes(left))
226
 
 
227
 
    def test_file_detect_changes(self):
228
 
        left = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
229
 
        left.text_sha1 = 123
230
 
        right = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
231
 
        right.text_sha1 = 123
232
 
        self.assertEqual((False, False), left.detect_changes(right))
233
 
        self.assertEqual((False, False), right.detect_changes(left))
234
 
        left.executable = True
235
 
        self.assertEqual((False, True), left.detect_changes(right))
236
 
        self.assertEqual((False, True), right.detect_changes(left))
237
 
        right.text_sha1 = 321
238
 
        self.assertEqual((True, True), left.detect_changes(right))
239
 
        self.assertEqual((True, True), right.detect_changes(left))
240
 
 
241
 
    def test_symlink_detect_changes(self):
242
 
        left = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
243
 
        left.text_sha1 = 123
244
 
        left.executable = True
245
 
        left.symlink_target='foo'
246
 
        right = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
247
 
        right.text_sha1 = 321
248
 
        right.symlink_target='foo'
249
 
        self.assertEqual((False, False), left.detect_changes(right))
250
 
        self.assertEqual((False, False), right.detect_changes(left))
251
 
        left.symlink_target = 'different'
252
 
        self.assertEqual((True, False), left.detect_changes(right))
253
 
        self.assertEqual((True, False), right.detect_changes(left))
254
 
 
255
 
    def test_file_has_text(self):
256
 
        file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
257
 
        self.failUnless(file.has_text())
258
 
 
259
 
    def test_directory_has_text(self):
260
 
        dir = inventory.InventoryDirectory('123', 'hello.c', ROOT_ID)
261
 
        self.failIf(dir.has_text())
262
 
 
263
 
    def test_link_has_text(self):
264
 
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
265
 
        self.failIf(link.has_text())
266
 
 
267
 
    def test_make_entry(self):
268
 
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
269
 
            inventory.InventoryFile)
270
 
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
271
 
            inventory.InventoryLink)
272
 
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
273
 
            inventory.InventoryDirectory)
274
 
 
275
 
    def test_make_entry_non_normalized(self):
276
 
        orig_normalized_filename = osutils.normalized_filename
277
 
 
278
 
        try:
279
 
            osutils.normalized_filename = osutils._accessible_normalized_filename
280
 
            entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
281
 
            self.assertEqual(u'\xe5', entry.name)
282
 
            self.assertIsInstance(entry, inventory.InventoryFile)
283
 
 
284
 
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
285
 
            self.assertRaises(errors.InvalidNormalization,
286
 
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
287
 
        finally:
288
 
            osutils.normalized_filename = orig_normalized_filename
289
 
 
290
 
 
291
 
class TestEntryDiffing(TestCaseWithTransport):
292
 
 
293
 
    def setUp(self):
294
 
        super(TestEntryDiffing, self).setUp()
295
 
        self.wt = self.make_branch_and_tree('.')
296
 
        self.branch = self.wt.branch
297
 
        print >> open('file', 'wb'), 'foo'
298
 
        print >> open('binfile', 'wb'), 'foo'
299
 
        self.wt.add(['file'], ['fileid'])
300
 
        self.wt.add(['binfile'], ['binfileid'])
301
 
        if has_symlinks():
302
 
            os.symlink('target1', 'symlink')
303
 
            self.wt.add(['symlink'], ['linkid'])
304
 
        self.wt.commit('message_1', rev_id = '1')
305
 
        print >> open('file', 'wb'), 'bar'
306
 
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
307
 
        if has_symlinks():
308
 
            os.unlink('symlink')
309
 
            os.symlink('target2', 'symlink')
310
 
        self.tree_1 = self.branch.repository.revision_tree('1')
311
 
        self.inv_1 = self.branch.repository.get_inventory('1')
312
 
        self.file_1 = self.inv_1['fileid']
313
 
        self.file_1b = self.inv_1['binfileid']
314
 
        self.tree_2 = self.wt
315
 
        self.tree_2.lock_read()
316
 
        self.addCleanup(self.tree_2.unlock)
317
 
        self.inv_2 = self.tree_2.read_working_inventory()
318
 
        self.file_2 = self.inv_2['fileid']
319
 
        self.file_2b = self.inv_2['binfileid']
320
 
        if has_symlinks():
321
 
            self.link_1 = self.inv_1['linkid']
322
 
            self.link_2 = self.inv_2['linkid']
323
 
 
324
 
    def test_file_diff_deleted(self):
325
 
        output = StringIO()
326
 
        self.file_1.diff(internal_diff, 
327
 
                          "old_label", self.tree_1,
328
 
                          "/dev/null", None, None,
329
 
                          output)
330
 
        self.assertEqual(output.getvalue(), "--- old_label\n"
331
 
                                            "+++ /dev/null\n"
332
 
                                            "@@ -1,1 +0,0 @@\n"
333
 
                                            "-foo\n"
334
 
                                            "\n")
335
 
 
336
 
    def test_file_diff_added(self):
337
 
        output = StringIO()
338
 
        self.file_1.diff(internal_diff, 
339
 
                          "new_label", self.tree_1,
340
 
                          "/dev/null", None, None,
341
 
                          output, reverse=True)
342
 
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
343
 
                                            "+++ new_label\n"
344
 
                                            "@@ -0,0 +1,1 @@\n"
345
 
                                            "+foo\n"
346
 
                                            "\n")
347
 
 
348
 
    def test_file_diff_changed(self):
349
 
        output = StringIO()
350
 
        self.file_1.diff(internal_diff, 
351
 
                          "/dev/null", self.tree_1, 
352
 
                          "new_label", self.file_2, self.tree_2,
353
 
                          output)
354
 
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
355
 
                                            "+++ new_label\n"
356
 
                                            "@@ -1,1 +1,1 @@\n"
357
 
                                            "-foo\n"
358
 
                                            "+bar\n"
359
 
                                            "\n")
360
 
        
361
 
    def test_file_diff_binary(self):
362
 
        output = StringIO()
363
 
        self.file_1.diff(internal_diff, 
364
 
                          "/dev/null", self.tree_1, 
365
 
                          "new_label", self.file_2b, self.tree_2,
366
 
                          output)
367
 
        self.assertEqual(output.getvalue(), 
368
 
                         "Binary files /dev/null and new_label differ\n")
369
 
    def test_link_diff_deleted(self):
370
 
        if not has_symlinks():
371
 
            return
372
 
        output = StringIO()
373
 
        self.link_1.diff(internal_diff, 
374
 
                          "old_label", self.tree_1,
375
 
                          "/dev/null", None, None,
376
 
                          output)
377
 
        self.assertEqual(output.getvalue(),
378
 
                         "=== target was 'target1'\n")
379
 
 
380
 
    def test_link_diff_added(self):
381
 
        if not has_symlinks():
382
 
            return
383
 
        output = StringIO()
384
 
        self.link_1.diff(internal_diff, 
385
 
                          "new_label", self.tree_1,
386
 
                          "/dev/null", None, None,
387
 
                          output, reverse=True)
388
 
        self.assertEqual(output.getvalue(),
389
 
                         "=== target is 'target1'\n")
390
 
 
391
 
    def test_link_diff_changed(self):
392
 
        if not has_symlinks():
393
 
            return
394
 
        output = StringIO()
395
 
        self.link_1.diff(internal_diff, 
396
 
                          "/dev/null", self.tree_1, 
397
 
                          "new_label", self.link_2, self.tree_2,
398
 
                          output)
399
 
        self.assertEqual(output.getvalue(),
400
 
                         "=== target changed 'target1' => 'target2'\n")
401
 
 
402
 
 
403
 
class TestSnapshot(TestCaseWithTransport):
404
 
 
405
 
    def setUp(self):
406
 
        # for full testing we'll need a branch
407
 
        # with a subdir to test parent changes.
408
 
        # and a file, link and dir under that.
409
 
        # but right now I only need one attribute
410
 
        # to change, and then test merge patterns
411
 
        # with fake parent entries.
412
 
        super(TestSnapshot, self).setUp()
413
 
        self.wt = self.make_branch_and_tree('.')
414
 
        self.branch = self.wt.branch
415
 
        self.build_tree(['subdir/', 'subdir/file'], line_endings='binary')
416
 
        self.wt.add(['subdir', 'subdir/file'],
417
 
                                       ['dirid', 'fileid'])
418
 
        if has_symlinks():
419
 
            pass
420
 
        self.wt.commit('message_1', rev_id = '1')
421
 
        self.tree_1 = self.branch.repository.revision_tree('1')
422
 
        self.inv_1 = self.branch.repository.get_inventory('1')
423
 
        self.file_1 = self.inv_1['fileid']
424
 
        self.wt.lock_write()
425
 
        self.addCleanup(self.wt.unlock)
426
 
        self.file_active = self.wt.inventory['fileid']
427
 
        self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
428
 
 
429
 
    def test_snapshot_new_revision(self):
430
 
        # This tests that a simple commit with no parents makes a new
431
 
        # revision value in the inventory entry
432
 
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
433
 
        # expected outcome - file_1 has a revision id of '2', and we can get
434
 
        # its text of 'file contents' out of the weave.
435
 
        self.assertEqual(self.file_1.revision, '1')
436
 
        self.assertEqual(self.file_active.revision, '2')
437
 
        # this should be a separate test probably, but lets check it once..
438
 
        lines = self.branch.repository.weave_store.get_weave(
439
 
            'fileid', 
440
 
            self.branch.get_transaction()).get_lines('2')
441
 
        self.assertEqual(lines, ['contents of subdir/file\n'])
442
 
 
443
 
    def test_snapshot_unchanged(self):
444
 
        #This tests that a simple commit does not make a new entry for
445
 
        # an unchanged inventory entry
446
 
        self.file_active.snapshot('2', 'subdir/file', {'1':self.file_1},
447
 
                                  self.wt, self.builder)
448
 
        self.assertEqual(self.file_1.revision, '1')
449
 
        self.assertEqual(self.file_active.revision, '1')
450
 
        vf = self.branch.repository.weave_store.get_weave(
451
 
            'fileid', 
452
 
            self.branch.repository.get_transaction())
453
 
        self.assertRaises(errors.RevisionNotPresent,
454
 
                          vf.get_lines,
455
 
                          '2')
456
 
 
457
 
    def test_snapshot_merge_identical_different_revid(self):
458
 
        # This tests that a commit with two identical parents, one of which has
459
 
        # a different revision id, results in a new revision id in the entry.
460
 
        # 1->other, commit a merge of other against 1, results in 2.
461
 
        other_ie = inventory.InventoryFile('fileid', 'newname', self.file_1.parent_id)
462
 
        other_ie = inventory.InventoryFile('fileid', 'file', self.file_1.parent_id)
463
 
        other_ie.revision = '1'
464
 
        other_ie.text_sha1 = self.file_1.text_sha1
465
 
        other_ie.text_size = self.file_1.text_size
466
 
        self.assertEqual(self.file_1, other_ie)
467
 
        other_ie.revision = 'other'
468
 
        self.assertNotEqual(self.file_1, other_ie)
469
 
        versionfile = self.branch.repository.weave_store.get_weave(
470
 
            'fileid', self.branch.repository.get_transaction())
471
 
        versionfile.clone_text('other', '1', ['1'])
472
 
        self.file_active.snapshot('2', 'subdir/file', 
473
 
                                  {'1':self.file_1, 'other':other_ie},
474
 
                                  self.wt, self.builder)
475
 
        self.assertEqual(self.file_active.revision, '2')
476
 
 
477
 
    def test_snapshot_changed(self):
478
 
        # This tests that a commit with one different parent results in a new
479
 
        # revision id in the entry.
480
 
        self.wt.rename_one('subdir/file', 'subdir/newname')
481
 
        self.file_active = self.wt.inventory['fileid']
482
 
        self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1}, 
483
 
                                  self.wt, self.builder)
484
 
        # expected outcome - file_1 has a revision id of '2'
485
 
        self.assertEqual(self.file_active.revision, '2')
486
 
 
487
 
 
488
 
class TestPreviousHeads(TestCaseWithTransport):
489
 
 
490
 
    def setUp(self):
491
 
        # we want several inventories, that respectively
492
 
        # give use the following scenarios:
493
 
        # A) fileid not in any inventory (A),
494
 
        # B) fileid present in one inventory (B) and (A,B)
495
 
        # C) fileid present in two inventories, and they
496
 
        #   are not mutual descendents (B, C)
497
 
        # D) fileid present in two inventories and one is
498
 
        #   a descendent of the other. (B, D)
499
 
        super(TestPreviousHeads, self).setUp()
500
 
        self.wt = self.make_branch_and_tree('.')
501
 
        self.branch = self.wt.branch
502
 
        self.build_tree(['file'])
503
 
        self.wt.commit('new branch', allow_pointless=True, rev_id='A')
504
 
        self.inv_A = self.branch.repository.get_inventory('A')
505
 
        self.wt.add(['file'], ['fileid'])
506
 
        self.wt.commit('add file', rev_id='B')
507
 
        self.inv_B = self.branch.repository.get_inventory('B')
508
 
        uncommit(self.branch, tree=self.wt)
509
 
        self.assertEqual(self.branch.revision_history(), ['A'])
510
 
        self.wt.commit('another add of file', rev_id='C')
511
 
        self.inv_C = self.branch.repository.get_inventory('C')
512
 
        self.wt.add_parent_tree_id('B')
513
 
        self.wt.commit('merge in B', rev_id='D')
514
 
        self.inv_D = self.branch.repository.get_inventory('D')
515
 
        self.wt.lock_read()
516
 
        self.addCleanup(self.wt.unlock)
517
 
        self.file_active = self.wt.inventory['fileid']
518
 
        self.weave = self.branch.repository.weave_store.get_weave('fileid',
519
 
            self.branch.repository.get_transaction())
520
 
        
521
 
    def get_previous_heads(self, inventories):
522
 
        return self.file_active.find_previous_heads(
523
 
            inventories, 
524
 
            self.branch.repository.weave_store,
525
 
            self.branch.repository.get_transaction())
526
 
        
527
 
    def test_fileid_in_no_inventory(self):
528
 
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
529
 
 
530
 
    def test_fileid_in_one_inventory(self):
531
 
        self.assertEqual({'B':self.inv_B['fileid']},
532
 
                         self.get_previous_heads([self.inv_B]))
533
 
        self.assertEqual({'B':self.inv_B['fileid']},
534
 
                         self.get_previous_heads([self.inv_A, self.inv_B]))
535
 
        self.assertEqual({'B':self.inv_B['fileid']},
536
 
                         self.get_previous_heads([self.inv_B, self.inv_A]))
537
 
 
538
 
    def test_fileid_in_two_inventories_gives_both_entries(self):
539
 
        self.assertEqual({'B':self.inv_B['fileid'],
540
 
                          'C':self.inv_C['fileid']},
541
 
                          self.get_previous_heads([self.inv_B, self.inv_C]))
542
 
        self.assertEqual({'B':self.inv_B['fileid'],
543
 
                          'C':self.inv_C['fileid']},
544
 
                          self.get_previous_heads([self.inv_C, self.inv_B]))
545
 
 
546
 
    def test_fileid_in_two_inventories_already_merged_gives_head(self):
547
 
        self.assertEqual({'D':self.inv_D['fileid']},
548
 
                         self.get_previous_heads([self.inv_B, self.inv_D]))
549
 
        self.assertEqual({'D':self.inv_D['fileid']},
550
 
                         self.get_previous_heads([self.inv_D, self.inv_B]))
551
 
 
552
 
    # TODO: test two inventories with the same file revision 
553
 
 
554
 
 
555
 
class TestDescribeChanges(TestCase):
556
 
 
557
 
    def test_describe_change(self):
558
 
        # we need to test the following change combinations:
559
 
        # rename
560
 
        # reparent
561
 
        # modify
562
 
        # gone
563
 
        # added
564
 
        # renamed/reparented and modified
565
 
        # change kind (perhaps can't be done yet?)
566
 
        # also, merged in combination with all of these?
567
 
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
568
 
        old_a.text_sha1 = '123132'
569
 
        old_a.text_size = 0
570
 
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
571
 
        new_a.text_sha1 = '123132'
572
 
        new_a.text_size = 0
573
 
 
574
 
        self.assertChangeDescription('unchanged', old_a, new_a)
575
 
 
576
 
        new_a.text_size = 10
577
 
        new_a.text_sha1 = 'abcabc'
578
 
        self.assertChangeDescription('modified', old_a, new_a)
579
 
 
580
 
        self.assertChangeDescription('added', None, new_a)
581
 
        self.assertChangeDescription('removed', old_a, None)
582
 
        # perhaps a bit questionable but seems like the most reasonable thing...
583
 
        self.assertChangeDescription('unchanged', None, None)
584
 
 
585
 
        # in this case it's both renamed and modified; show a rename and 
586
 
        # modification:
587
 
        new_a.name = 'newfilename'
588
 
        self.assertChangeDescription('modified and renamed', old_a, new_a)
589
 
 
590
 
        # reparenting is 'renaming'
591
 
        new_a.name = old_a.name
592
 
        new_a.parent_id = 'somedir-id'
593
 
        self.assertChangeDescription('modified and renamed', old_a, new_a)
594
 
 
595
 
        # reset the content values so its not modified
596
 
        new_a.text_size = old_a.text_size
597
 
        new_a.text_sha1 = old_a.text_sha1
598
 
        new_a.name = old_a.name
599
 
 
600
 
        new_a.name = 'newfilename'
601
 
        self.assertChangeDescription('renamed', old_a, new_a)
602
 
 
603
 
        # reparenting is 'renaming'
604
 
        new_a.name = old_a.name
605
 
        new_a.parent_id = 'somedir-id'
606
 
        self.assertChangeDescription('renamed', old_a, new_a)
607
 
 
608
 
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
609
 
        change = InventoryEntry.describe_change(old_ie, new_ie)
610
 
        self.assertEqual(expected_change, change)
611
 
 
612
 
 
613
 
class TestRevert(TestCaseWithTransport):
614
 
 
615
 
    def test_dangling_id(self):
616
 
        wt = self.make_branch_and_tree('b1')
617
 
        wt.lock_tree_write()
618
 
        self.addCleanup(wt.unlock)
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
 
        wt.flush() # workaround revert doing wt._write_inventory for now.
624
 
        os.unlink('b1/a')
625
 
        wt.revert([])
626
 
        self.assertEqual(len(wt.inventory), 1)
627
 
 
628
 
 
629
 
class TestIsRoot(TestCase):
630
 
    """Ensure our root-checking code is accurate."""
631
 
 
632
 
    def test_is_root(self):
633
 
        inv = Inventory('TREE_ROOT')
634
 
        self.assertTrue(inv.is_root('TREE_ROOT'))
635
 
        self.assertFalse(inv.is_root('booga'))
636
 
        inv.root.file_id = 'booga'
637
 
        self.assertFalse(inv.is_root('TREE_ROOT'))
638
 
        self.assertTrue(inv.is_root('booga'))
639
 
        # works properly even if no root is set
640
 
        inv.root = None
641
 
        self.assertFalse(inv.is_root('TREE_ROOT'))
642
 
        self.assertFalse(inv.is_root('booga'))
643
 
 
644
 
 
645
 
class TestTreeReference(TestCase):
646
 
    
647
 
    def test_create(self):
648
 
        inv = Inventory('tree-root-123')
649
 
        inv.add(TreeReference('nested-id', 'nested', parent_id='tree-root-123',
650
 
                              revision='rev', reference_revision='rev2'))