~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: Wouter van Heyst
  • Date: 2007-01-18 18:37:21 UTC
  • mto: (2234.3.3 0.14)
  • mto: This revision was merged to the branch mainline in revision 2243.
  • Revision ID: larstiq@larstiq.dyndns.org-20070118183721-78uzxifyyyoqxja9
(Alexander Belchenko) add windows installer check for python2.5

Show diffs side-by-side

added added

removed removed

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