~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
from cStringIO import StringIO
18
18
import os
19
 
import time
20
19
 
21
20
from bzrlib.branch import Branch
22
21
import bzrlib.errors as errors
23
22
from bzrlib.diff import internal_diff
24
 
from bzrlib.inventory import (Inventory, ROOT_ID, InventoryFile,
25
 
    InventoryDirectory, InventoryEntry)
 
23
from bzrlib.inventory import Inventory, ROOT_ID
26
24
import bzrlib.inventory as inventory
27
 
from bzrlib.osutils import (has_symlinks, rename, pathjoin, is_inside_any, 
28
 
    is_inside_or_parent_of_any)
 
25
from bzrlib.osutils import has_symlinks, rename, pathjoin
29
26
from bzrlib.tests import TestCase, TestCaseWithTransport
30
 
from bzrlib.transform import TreeTransform
31
 
from bzrlib.uncommit import uncommit
32
27
 
33
28
 
34
29
class TestInventory(TestCase):
35
30
 
36
31
    def test_is_within(self):
 
32
        from bzrlib.osutils import is_inside_any
37
33
 
38
34
        SRC_FOO_C = pathjoin('src', 'foo.c')
39
35
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
45
41
        for dirs, fn in [(['src'], 'srccontrol'),
46
42
                         (['src'], 'srccontrol/foo')]:
47
43
            self.assertFalse(is_inside_any(dirs, fn))
48
 
 
49
 
    def test_is_within_or_parent(self):
50
 
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
51
 
                         (['src'], 'src/foo.c'),
52
 
                         (['src/bar.c'], 'src'),
53
 
                         (['src/bar.c', 'bla/foo.c'], 'src'),
54
 
                         (['src'], 'src'),
55
 
                         ]:
56
 
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
57
44
            
58
 
        for dirs, fn in [(['src'], 'srccontrol'),
59
 
                         (['srccontrol/foo.c'], 'src'),
60
 
                         (['src'], 'srccontrol/foo')]:
61
 
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
62
 
 
63
45
    def test_ids(self):
64
46
        """Test detection of files within selected directories."""
65
47
        inv = Inventory()
76
58
        
77
59
        self.assert_('src-id' in inv)
78
60
 
79
 
    def test_iter_entries(self):
80
 
        inv = Inventory()
81
 
        
82
 
        for args in [('src', 'directory', 'src-id'), 
83
 
                     ('doc', 'directory', 'doc-id'), 
84
 
                     ('src/hello.c', 'file', 'hello-id'),
85
 
                     ('src/bye.c', 'file', 'bye-id'),
86
 
                     ('Makefile', 'file', 'makefile-id')]:
87
 
            inv.add_path(*args)
88
 
 
89
 
        self.assertEqual([
90
 
            ('Makefile', 'makefile-id'),
91
 
            ('doc', 'doc-id'),
92
 
            ('src', 'src-id'),
93
 
            ('src/bye.c', 'bye-id'),
94
 
            ('src/hello.c', 'hello-id'),
95
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries()])
96
 
            
97
 
    def test_iter_entries_by_dir(self):
98
 
        inv = Inventory()
99
 
        
100
 
        for args in [('src', 'directory', 'src-id'), 
101
 
                     ('doc', 'directory', 'doc-id'), 
102
 
                     ('src/hello.c', 'file', 'hello-id'),
103
 
                     ('src/bye.c', 'file', 'bye-id'),
104
 
                     ('zz', 'file', 'zz-id'),
105
 
                     ('src/sub/', 'directory', 'sub-id'),
106
 
                     ('src/zz.c', 'file', 'zzc-id'),
107
 
                     ('src/sub/a', 'file', 'a-id'),
108
 
                     ('Makefile', 'file', 'makefile-id')]:
109
 
            inv.add_path(*args)
110
 
 
111
 
        self.assertEqual([
112
 
            ('Makefile', 'makefile-id'),
113
 
            ('doc', 'doc-id'),
114
 
            ('src', 'src-id'),
115
 
            ('zz', 'zz-id'),
116
 
            ('src/bye.c', 'bye-id'),
117
 
            ('src/hello.c', 'hello-id'),
118
 
            ('src/sub', 'sub-id'),
119
 
            ('src/zz.c', 'zzc-id'),
120
 
            ('src/sub/a', 'a-id'),
121
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir()])
122
 
            
 
61
 
123
62
    def test_version(self):
124
63
        """Inventory remembers the text's version."""
125
64
        inv = Inventory()
192
131
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
193
132
        self.failIf(link.has_text())
194
133
 
195
 
    def test_make_entry(self):
196
 
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
197
 
            inventory.InventoryFile)
198
 
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
199
 
            inventory.InventoryLink)
200
 
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
201
 
            inventory.InventoryDirectory)
202
134
 
203
135
class TestEntryDiffing(TestCaseWithTransport):
204
136
 
207
139
        self.wt = self.make_branch_and_tree('.')
208
140
        self.branch = self.wt.branch
209
141
        print >> open('file', 'wb'), 'foo'
210
 
        print >> open('binfile', 'wb'), 'foo'
211
142
        self.wt.add(['file'], ['fileid'])
212
 
        self.wt.add(['binfile'], ['binfileid'])
213
143
        if has_symlinks():
214
144
            os.symlink('target1', 'symlink')
215
145
            self.wt.add(['symlink'], ['linkid'])
216
146
        self.wt.commit('message_1', rev_id = '1')
217
147
        print >> open('file', 'wb'), 'bar'
218
 
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
219
148
        if has_symlinks():
220
149
            os.unlink('symlink')
221
150
            os.symlink('target2', 'symlink')
222
151
        self.tree_1 = self.branch.repository.revision_tree('1')
223
152
        self.inv_1 = self.branch.repository.get_inventory('1')
224
153
        self.file_1 = self.inv_1['fileid']
225
 
        self.file_1b = self.inv_1['binfileid']
226
154
        self.tree_2 = self.wt
227
155
        self.inv_2 = self.tree_2.read_working_inventory()
228
156
        self.file_2 = self.inv_2['fileid']
229
 
        self.file_2b = self.inv_2['binfileid']
230
157
        if has_symlinks():
231
158
            self.link_1 = self.inv_1['linkid']
232
159
            self.link_2 = self.inv_2['linkid']
237
164
                          "old_label", self.tree_1,
238
165
                          "/dev/null", None, None,
239
166
                          output)
240
 
        self.assertEqual(output.getvalue(), "--- old_label\n"
241
 
                                            "+++ /dev/null\n"
 
167
        self.assertEqual(output.getvalue(), "--- old_label\t\n"
 
168
                                            "+++ /dev/null\t\n"
242
169
                                            "@@ -1,1 +0,0 @@\n"
243
170
                                            "-foo\n"
244
171
                                            "\n")
249
176
                          "new_label", self.tree_1,
250
177
                          "/dev/null", None, None,
251
178
                          output, reverse=True)
252
 
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
253
 
                                            "+++ new_label\n"
 
179
        self.assertEqual(output.getvalue(), "--- /dev/null\t\n"
 
180
                                            "+++ new_label\t\n"
254
181
                                            "@@ -0,0 +1,1 @@\n"
255
182
                                            "+foo\n"
256
183
                                            "\n")
261
188
                          "/dev/null", self.tree_1, 
262
189
                          "new_label", self.file_2, self.tree_2,
263
190
                          output)
264
 
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
265
 
                                            "+++ new_label\n"
 
191
        self.assertEqual(output.getvalue(), "--- /dev/null\t\n"
 
192
                                            "+++ new_label\t\n"
266
193
                                            "@@ -1,1 +1,1 @@\n"
267
194
                                            "-foo\n"
268
195
                                            "+bar\n"
269
196
                                            "\n")
270
197
        
271
 
    def test_file_diff_binary(self):
272
 
        output = StringIO()
273
 
        self.file_1.diff(internal_diff, 
274
 
                          "/dev/null", self.tree_1, 
275
 
                          "new_label", self.file_2b, self.tree_2,
276
 
                          output)
277
 
        self.assertEqual(output.getvalue(), 
278
 
                         "Binary files /dev/null and new_label differ\n")
279
198
    def test_link_diff_deleted(self):
280
199
        if not has_symlinks():
281
200
            return
332
251
        self.inv_1 = self.branch.repository.get_inventory('1')
333
252
        self.file_1 = self.inv_1['fileid']
334
253
        self.file_active = self.wt.inventory['fileid']
335
 
        self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
336
254
 
337
255
    def test_snapshot_new_revision(self):
338
256
        # This tests that a simple commit with no parents makes a new
339
257
        # revision value in the inventory entry
340
 
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
 
258
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, 
 
259
                                  self.branch.repository.weave_store,
 
260
                                  self.branch.get_transaction())
341
261
        # expected outcome - file_1 has a revision id of '2', and we can get
342
262
        # its text of 'file contents' out of the weave.
343
263
        self.assertEqual(self.file_1.revision, '1')
344
264
        self.assertEqual(self.file_active.revision, '2')
345
265
        # this should be a separate test probably, but lets check it once..
346
 
        lines = self.branch.repository.weave_store.get_weave(
347
 
            'fileid', 
348
 
            self.branch.get_transaction()).get_lines('2')
 
266
        lines = self.branch.repository.weave_store.get_lines('fileid','2',
 
267
            self.branch.get_transaction())
349
268
        self.assertEqual(lines, ['contents of subdir/file\n'])
350
269
 
351
270
    def test_snapshot_unchanged(self):
352
271
        #This tests that a simple commit does not make a new entry for
353
272
        # an unchanged inventory entry
354
273
        self.file_active.snapshot('2', 'subdir/file', {'1':self.file_1},
355
 
                                  self.wt, self.builder)
 
274
                                  self.wt, 
 
275
                                  self.branch.repository.weave_store,
 
276
                                  self.branch.get_transaction())
356
277
        self.assertEqual(self.file_1.revision, '1')
357
278
        self.assertEqual(self.file_active.revision, '1')
358
 
        vf = self.branch.repository.weave_store.get_weave(
359
 
            'fileid', 
360
 
            self.branch.repository.get_transaction())
361
 
        self.assertRaises(errors.RevisionNotPresent,
362
 
                          vf.get_lines,
363
 
                          '2')
 
279
        self.assertRaises(errors.WeaveError,
 
280
                          self.branch.repository.weave_store.get_lines, 
 
281
                          'fileid', '2', self.branch.get_transaction())
364
282
 
365
283
    def test_snapshot_merge_identical_different_revid(self):
366
284
        # This tests that a commit with two identical parents, one of which has
374
292
        self.assertEqual(self.file_1, other_ie)
375
293
        other_ie.revision = 'other'
376
294
        self.assertNotEqual(self.file_1, other_ie)
377
 
        versionfile = self.branch.repository.weave_store.get_weave(
378
 
            'fileid', self.branch.repository.get_transaction())
379
 
        versionfile.clone_text('other', '1', ['1'])
 
295
        self.branch.repository.weave_store.add_identical_text('fileid', '1', 
 
296
            'other', ['1'], self.branch.get_transaction())
380
297
        self.file_active.snapshot('2', 'subdir/file', 
381
298
                                  {'1':self.file_1, 'other':other_ie},
382
 
                                  self.wt, self.builder)
 
299
                                  self.wt, 
 
300
                                  self.branch.repository.weave_store,
 
301
                                  self.branch.get_transaction())
383
302
        self.assertEqual(self.file_active.revision, '2')
384
303
 
385
304
    def test_snapshot_changed(self):
388
307
        self.file_active.name='newname'
389
308
        rename('subdir/file', 'subdir/newname')
390
309
        self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1}, 
391
 
                                  self.wt, self.builder)
 
310
                                  self.wt,
 
311
                                  self.branch.repository.weave_store,
 
312
                                  self.branch.get_transaction())
392
313
        # expected outcome - file_1 has a revision id of '2'
393
314
        self.assertEqual(self.file_active.revision, '2')
394
315
 
413
334
        self.wt.add(['file'], ['fileid'])
414
335
        self.wt.commit('add file', rev_id='B')
415
336
        self.inv_B = self.branch.repository.get_inventory('B')
416
 
        uncommit(self.branch, tree=self.wt)
 
337
        self.branch.lock_write()
 
338
        try:
 
339
            self.branch.control_files.put_utf8('revision-history', 'A\n')
 
340
        finally:
 
341
            self.branch.unlock()
417
342
        self.assertEqual(self.branch.revision_history(), ['A'])
418
343
        self.wt.commit('another add of file', rev_id='C')
419
344
        self.inv_C = self.branch.repository.get_inventory('C')
422
347
        self.inv_D = self.branch.repository.get_inventory('D')
423
348
        self.file_active = self.wt.inventory['fileid']
424
349
        self.weave = self.branch.repository.weave_store.get_weave('fileid',
425
 
            self.branch.repository.get_transaction())
 
350
            self.branch.get_transaction())
426
351
        
427
352
    def get_previous_heads(self, inventories):
428
 
        return self.file_active.find_previous_heads(
429
 
            inventories, 
430
 
            self.branch.repository.weave_store,
431
 
            self.branch.repository.get_transaction())
 
353
        return self.file_active.find_previous_heads(inventories, self.weave)
432
354
        
433
355
    def test_fileid_in_no_inventory(self):
434
356
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
458
380
    # TODO: test two inventories with the same file revision 
459
381
 
460
382
 
461
 
class TestDescribeChanges(TestCase):
462
 
 
463
 
    def test_describe_change(self):
464
 
        # we need to test the following change combinations:
465
 
        # rename
466
 
        # reparent
467
 
        # modify
468
 
        # gone
469
 
        # added
470
 
        # renamed/reparented and modified
471
 
        # change kind (perhaps can't be done yet?)
472
 
        # also, merged in combination with all of these?
473
 
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
474
 
        old_a.text_sha1 = '123132'
475
 
        old_a.text_size = 0
476
 
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
477
 
        new_a.text_sha1 = '123132'
478
 
        new_a.text_size = 0
479
 
 
480
 
        self.assertChangeDescription('unchanged', old_a, new_a)
481
 
 
482
 
        new_a.text_size = 10
483
 
        new_a.text_sha1 = 'abcabc'
484
 
        self.assertChangeDescription('modified', old_a, new_a)
485
 
 
486
 
        self.assertChangeDescription('added', None, new_a)
487
 
        self.assertChangeDescription('removed', old_a, None)
488
 
        # perhaps a bit questionable but seems like the most reasonable thing...
489
 
        self.assertChangeDescription('unchanged', None, None)
490
 
 
491
 
        # in this case it's both renamed and modified; show a rename and 
492
 
        # modification:
493
 
        new_a.name = 'newfilename'
494
 
        self.assertChangeDescription('modified and renamed', old_a, new_a)
495
 
 
496
 
        # reparenting is 'renaming'
497
 
        new_a.name = old_a.name
498
 
        new_a.parent_id = 'somedir-id'
499
 
        self.assertChangeDescription('modified and renamed', old_a, new_a)
500
 
 
501
 
        # reset the content values so its not modified
502
 
        new_a.text_size = old_a.text_size
503
 
        new_a.text_sha1 = old_a.text_sha1
504
 
        new_a.name = old_a.name
505
 
 
506
 
        new_a.name = 'newfilename'
507
 
        self.assertChangeDescription('renamed', old_a, new_a)
508
 
 
509
 
        # reparenting is 'renaming'
510
 
        new_a.name = old_a.name
511
 
        new_a.parent_id = 'somedir-id'
512
 
        self.assertChangeDescription('renamed', old_a, new_a)
513
 
 
514
 
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
515
 
        change = InventoryEntry.describe_change(old_ie, new_ie)
516
 
        self.assertEqual(expected_change, change)
517
 
 
518
 
 
519
383
class TestExecutable(TestCaseWithTransport):
520
384
 
521
385
    def test_stays_executable(self):
 
386
        basic_inv = """<inventory format="5">
 
387
<file file_id="a-20051208024829-849e76f7968d7a86" name="a" executable="yes" />
 
388
<file file_id="b-20051208024829-849e76f7968d7a86" name="b" />
 
389
</inventory>
 
390
"""
 
391
        wt = self.make_branch_and_tree('b1')
 
392
        b = wt.branch
 
393
        open('b1/a', 'wb').write('a test\n')
 
394
        open('b1/b', 'wb').write('b test\n')
 
395
        os.chmod('b1/a', 0755)
 
396
        os.chmod('b1/b', 0644)
 
397
        # Manually writing the inventory, to ensure that
 
398
        # the executable="yes" entry is set for 'a' and not for 'b'
 
399
        open('b1/.bzr/inventory', 'wb').write(basic_inv)
 
400
 
522
401
        a_id = "a-20051208024829-849e76f7968d7a86"
523
402
        b_id = "b-20051208024829-849e76f7968d7a86"
524
 
        wt = self.make_branch_and_tree('b1')
525
 
        b = wt.branch
526
 
        tt = TreeTransform(wt)
527
 
        tt.new_file('a', tt.root, 'a test\n', a_id, True)
528
 
        tt.new_file('b', tt.root, 'b test\n', b_id, False)
529
 
        tt.apply()
530
 
 
531
 
        self.failUnless(wt.is_executable(a_id), "'a' lost the execute bit")
532
 
 
533
 
        # reopen the tree and ensure it stuck.
534
403
        wt = wt.bzrdir.open_workingtree()
535
404
        self.assertEqual(['a', 'b'], [cn for cn,ie in wt.inventory.iter_entries()])
536
405
 
610
479
 
611
480
        self.failUnless(t2.is_executable(a_id), "'a' lost the execute bit")
612
481
        self.failIf(t2.is_executable(b_id), "'b' gained an execute bit")
613
 
 
614
 
 
615
 
class TestRevert(TestCaseWithTransport):
616
 
 
617
 
    def test_dangling_id(self):
618
 
        wt = self.make_branch_and_tree('b1')
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
 
        os.unlink('b1/a')
624
 
        wt.revert([])
625
 
        self.assertEqual(len(wt.inventory), 1)