~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-01-13 05:14:24 UTC
  • mfrom: (3936.1.3 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20090113051424-nrk3zkfe09h46i9y
(mbp) merge 1.11 and advance to 1.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
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
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
17
 
21
18
from bzrlib import errors, inventory, osutils
22
 
from bzrlib.branch import Branch
23
 
from bzrlib.diff import internal_diff
24
19
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
 
        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
 
20
    InventoryDirectory, InventoryEntry, TreeReference)
 
21
from bzrlib.tests import TestCase
192
22
 
193
23
 
194
24
class TestInventoryEntry(TestCase):
280
110
            osutils.normalized_filename = orig_normalized_filename
281
111
 
282
112
 
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
113
class TestDescribeChanges(TestCase):
542
114
 
543
115
    def test_describe_change(self):
594
166
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
595
167
        change = InventoryEntry.describe_change(old_ie, new_ie)
596
168
        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'))