~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: 2006-08-17 07:52:09 UTC
  • mfrom: (1910.3.4 trivial)
  • Revision ID: pqm@pqm.ubuntu.com-20060817075209-e85a1f9e05ff8b87
(andrew) Trivial fixes to NotImplemented errors.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 by 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
17
20
 
18
21
from bzrlib import errors, inventory, osutils
 
22
from bzrlib.branch import Branch
 
23
from bzrlib.diff import internal_diff
19
24
from bzrlib.inventory import (Inventory, ROOT_ID, InventoryFile,
20
 
    InventoryDirectory, InventoryEntry, TreeReference)
21
 
from bzrlib.tests import TestCase
 
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_is_within(self):
 
36
 
 
37
        SRC_FOO_C = pathjoin('src', 'foo.c')
 
38
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
 
39
                         (['src'], SRC_FOO_C),
 
40
                         (['src'], 'src'),
 
41
                         ]:
 
42
            self.assert_(is_inside_any(dirs, fn))
 
43
            
 
44
        for dirs, fn in [(['src'], 'srccontrol'),
 
45
                         (['src'], 'srccontrol/foo')]:
 
46
            self.assertFalse(is_inside_any(dirs, fn))
 
47
 
 
48
    def test_is_within_or_parent(self):
 
49
        for dirs, fn in [(['src', 'doc'], 'src/foo.c'),
 
50
                         (['src'], 'src/foo.c'),
 
51
                         (['src/bar.c'], 'src'),
 
52
                         (['src/bar.c', 'bla/foo.c'], 'src'),
 
53
                         (['src'], 'src'),
 
54
                         ]:
 
55
            self.assert_(is_inside_or_parent_of_any(dirs, fn))
 
56
            
 
57
        for dirs, fn in [(['src'], 'srccontrol'),
 
58
                         (['srccontrol/foo.c'], 'src'),
 
59
                         (['src'], 'srccontrol/foo')]:
 
60
            self.assertFalse(is_inside_or_parent_of_any(dirs, fn))
 
61
 
 
62
    def test_ids(self):
 
63
        """Test detection of files within selected directories."""
 
64
        inv = Inventory()
 
65
        
 
66
        for args in [('src', 'directory', 'src-id'), 
 
67
                     ('doc', 'directory', 'doc-id'), 
 
68
                     ('src/hello.c', 'file'),
 
69
                     ('src/bye.c', 'file', 'bye-id'),
 
70
                     ('Makefile', 'file')]:
 
71
            inv.add_path(*args)
 
72
            
 
73
        self.assertEqual(inv.path2id('src'), 'src-id')
 
74
        self.assertEqual(inv.path2id('src/bye.c'), 'bye-id')
 
75
        
 
76
        self.assert_('src-id' in inv)
 
77
 
 
78
    def test_iter_entries(self):
 
79
        inv = Inventory()
 
80
        
 
81
        for args in [('src', 'directory', 'src-id'), 
 
82
                     ('doc', 'directory', 'doc-id'), 
 
83
                     ('src/hello.c', 'file', 'hello-id'),
 
84
                     ('src/bye.c', 'file', 'bye-id'),
 
85
                     ('Makefile', 'file', 'makefile-id')]:
 
86
            inv.add_path(*args)
 
87
 
 
88
        self.assertEqual([
 
89
            ('', ROOT_ID),
 
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
            ('', ROOT_ID),
 
113
            ('Makefile', 'makefile-id'),
 
114
            ('doc', 'doc-id'),
 
115
            ('src', 'src-id'),
 
116
            ('zz', 'zz-id'),
 
117
            ('src/bye.c', 'bye-id'),
 
118
            ('src/hello.c', 'hello-id'),
 
119
            ('src/sub', 'sub-id'),
 
120
            ('src/zz.c', 'zzc-id'),
 
121
            ('src/sub/a', 'a-id'),
 
122
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir()])
 
123
            
 
124
    def test_version(self):
 
125
        """Inventory remembers the text's version."""
 
126
        inv = Inventory()
 
127
        ie = inv.add_path('foo.txt', 'file')
 
128
        ## XXX
22
129
 
23
130
 
24
131
class TestInventoryEntry(TestCase):
110
217
            osutils.normalized_filename = orig_normalized_filename
111
218
 
112
219
 
 
220
class TestEntryDiffing(TestCaseWithTransport):
 
221
 
 
222
    def setUp(self):
 
223
        super(TestEntryDiffing, self).setUp()
 
224
        self.wt = self.make_branch_and_tree('.')
 
225
        self.branch = self.wt.branch
 
226
        print >> open('file', 'wb'), 'foo'
 
227
        print >> open('binfile', 'wb'), 'foo'
 
228
        self.wt.add(['file'], ['fileid'])
 
229
        self.wt.add(['binfile'], ['binfileid'])
 
230
        if has_symlinks():
 
231
            os.symlink('target1', 'symlink')
 
232
            self.wt.add(['symlink'], ['linkid'])
 
233
        self.wt.commit('message_1', rev_id = '1')
 
234
        print >> open('file', 'wb'), 'bar'
 
235
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
 
236
        if has_symlinks():
 
237
            os.unlink('symlink')
 
238
            os.symlink('target2', 'symlink')
 
239
        self.tree_1 = self.branch.repository.revision_tree('1')
 
240
        self.inv_1 = self.branch.repository.get_inventory('1')
 
241
        self.file_1 = self.inv_1['fileid']
 
242
        self.file_1b = self.inv_1['binfileid']
 
243
        self.tree_2 = self.wt
 
244
        self.inv_2 = self.tree_2.read_working_inventory()
 
245
        self.file_2 = self.inv_2['fileid']
 
246
        self.file_2b = self.inv_2['binfileid']
 
247
        if has_symlinks():
 
248
            self.link_1 = self.inv_1['linkid']
 
249
            self.link_2 = self.inv_2['linkid']
 
250
 
 
251
    def test_file_diff_deleted(self):
 
252
        output = StringIO()
 
253
        self.file_1.diff(internal_diff, 
 
254
                          "old_label", self.tree_1,
 
255
                          "/dev/null", None, None,
 
256
                          output)
 
257
        self.assertEqual(output.getvalue(), "--- old_label\n"
 
258
                                            "+++ /dev/null\n"
 
259
                                            "@@ -1,1 +0,0 @@\n"
 
260
                                            "-foo\n"
 
261
                                            "\n")
 
262
 
 
263
    def test_file_diff_added(self):
 
264
        output = StringIO()
 
265
        self.file_1.diff(internal_diff, 
 
266
                          "new_label", self.tree_1,
 
267
                          "/dev/null", None, None,
 
268
                          output, reverse=True)
 
269
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
 
270
                                            "+++ new_label\n"
 
271
                                            "@@ -0,0 +1,1 @@\n"
 
272
                                            "+foo\n"
 
273
                                            "\n")
 
274
 
 
275
    def test_file_diff_changed(self):
 
276
        output = StringIO()
 
277
        self.file_1.diff(internal_diff, 
 
278
                          "/dev/null", self.tree_1, 
 
279
                          "new_label", self.file_2, self.tree_2,
 
280
                          output)
 
281
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
 
282
                                            "+++ new_label\n"
 
283
                                            "@@ -1,1 +1,1 @@\n"
 
284
                                            "-foo\n"
 
285
                                            "+bar\n"
 
286
                                            "\n")
 
287
        
 
288
    def test_file_diff_binary(self):
 
289
        output = StringIO()
 
290
        self.file_1.diff(internal_diff, 
 
291
                          "/dev/null", self.tree_1, 
 
292
                          "new_label", self.file_2b, self.tree_2,
 
293
                          output)
 
294
        self.assertEqual(output.getvalue(), 
 
295
                         "Binary files /dev/null and new_label differ\n")
 
296
    def test_link_diff_deleted(self):
 
297
        if not has_symlinks():
 
298
            return
 
299
        output = StringIO()
 
300
        self.link_1.diff(internal_diff, 
 
301
                          "old_label", self.tree_1,
 
302
                          "/dev/null", None, None,
 
303
                          output)
 
304
        self.assertEqual(output.getvalue(),
 
305
                         "=== target was 'target1'\n")
 
306
 
 
307
    def test_link_diff_added(self):
 
308
        if not has_symlinks():
 
309
            return
 
310
        output = StringIO()
 
311
        self.link_1.diff(internal_diff, 
 
312
                          "new_label", self.tree_1,
 
313
                          "/dev/null", None, None,
 
314
                          output, reverse=True)
 
315
        self.assertEqual(output.getvalue(),
 
316
                         "=== target is 'target1'\n")
 
317
 
 
318
    def test_link_diff_changed(self):
 
319
        if not has_symlinks():
 
320
            return
 
321
        output = StringIO()
 
322
        self.link_1.diff(internal_diff, 
 
323
                          "/dev/null", self.tree_1, 
 
324
                          "new_label", self.link_2, self.tree_2,
 
325
                          output)
 
326
        self.assertEqual(output.getvalue(),
 
327
                         "=== target changed 'target1' => 'target2'\n")
 
328
 
 
329
 
 
330
class TestSnapshot(TestCaseWithTransport):
 
331
 
 
332
    def setUp(self):
 
333
        # for full testing we'll need a branch
 
334
        # with a subdir to test parent changes.
 
335
        # and a file, link and dir under that.
 
336
        # but right now I only need one attribute
 
337
        # to change, and then test merge patterns
 
338
        # with fake parent entries.
 
339
        super(TestSnapshot, self).setUp()
 
340
        self.wt = self.make_branch_and_tree('.')
 
341
        self.branch = self.wt.branch
 
342
        self.build_tree(['subdir/', 'subdir/file'], line_endings='binary')
 
343
        self.wt.add(['subdir', 'subdir/file'],
 
344
                                       ['dirid', 'fileid'])
 
345
        if has_symlinks():
 
346
            pass
 
347
        self.wt.commit('message_1', rev_id = '1')
 
348
        self.tree_1 = self.branch.repository.revision_tree('1')
 
349
        self.inv_1 = self.branch.repository.get_inventory('1')
 
350
        self.file_1 = self.inv_1['fileid']
 
351
        self.file_active = self.wt.inventory['fileid']
 
352
        self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
 
353
 
 
354
    def test_snapshot_new_revision(self):
 
355
        # This tests that a simple commit with no parents makes a new
 
356
        # revision value in the inventory entry
 
357
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
 
358
        # expected outcome - file_1 has a revision id of '2', and we can get
 
359
        # its text of 'file contents' out of the weave.
 
360
        self.assertEqual(self.file_1.revision, '1')
 
361
        self.assertEqual(self.file_active.revision, '2')
 
362
        # this should be a separate test probably, but lets check it once..
 
363
        lines = self.branch.repository.weave_store.get_weave(
 
364
            'fileid', 
 
365
            self.branch.get_transaction()).get_lines('2')
 
366
        self.assertEqual(lines, ['contents of subdir/file\n'])
 
367
 
 
368
    def test_snapshot_unchanged(self):
 
369
        #This tests that a simple commit does not make a new entry for
 
370
        # an unchanged inventory entry
 
371
        self.file_active.snapshot('2', 'subdir/file', {'1':self.file_1},
 
372
                                  self.wt, self.builder)
 
373
        self.assertEqual(self.file_1.revision, '1')
 
374
        self.assertEqual(self.file_active.revision, '1')
 
375
        vf = self.branch.repository.weave_store.get_weave(
 
376
            'fileid', 
 
377
            self.branch.repository.get_transaction())
 
378
        self.assertRaises(errors.RevisionNotPresent,
 
379
                          vf.get_lines,
 
380
                          '2')
 
381
 
 
382
    def test_snapshot_merge_identical_different_revid(self):
 
383
        # This tests that a commit with two identical parents, one of which has
 
384
        # a different revision id, results in a new revision id in the entry.
 
385
        # 1->other, commit a merge of other against 1, results in 2.
 
386
        other_ie = inventory.InventoryFile('fileid', 'newname', self.file_1.parent_id)
 
387
        other_ie = inventory.InventoryFile('fileid', 'file', self.file_1.parent_id)
 
388
        other_ie.revision = '1'
 
389
        other_ie.text_sha1 = self.file_1.text_sha1
 
390
        other_ie.text_size = self.file_1.text_size
 
391
        self.assertEqual(self.file_1, other_ie)
 
392
        other_ie.revision = 'other'
 
393
        self.assertNotEqual(self.file_1, other_ie)
 
394
        versionfile = self.branch.repository.weave_store.get_weave(
 
395
            'fileid', self.branch.repository.get_transaction())
 
396
        versionfile.clone_text('other', '1', ['1'])
 
397
        self.file_active.snapshot('2', 'subdir/file', 
 
398
                                  {'1':self.file_1, 'other':other_ie},
 
399
                                  self.wt, self.builder)
 
400
        self.assertEqual(self.file_active.revision, '2')
 
401
 
 
402
    def test_snapshot_changed(self):
 
403
        # This tests that a commit with one different parent results in a new
 
404
        # revision id in the entry.
 
405
        self.file_active.name='newname'
 
406
        rename('subdir/file', 'subdir/newname')
 
407
        self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1}, 
 
408
                                  self.wt, self.builder)
 
409
        # expected outcome - file_1 has a revision id of '2'
 
410
        self.assertEqual(self.file_active.revision, '2')
 
411
 
 
412
 
 
413
class TestPreviousHeads(TestCaseWithTransport):
 
414
 
 
415
    def setUp(self):
 
416
        # we want several inventories, that respectively
 
417
        # give use the following scenarios:
 
418
        # A) fileid not in any inventory (A),
 
419
        # B) fileid present in one inventory (B) and (A,B)
 
420
        # C) fileid present in two inventories, and they
 
421
        #   are not mutual descendents (B, C)
 
422
        # D) fileid present in two inventories and one is
 
423
        #   a descendent of the other. (B, D)
 
424
        super(TestPreviousHeads, self).setUp()
 
425
        self.wt = self.make_branch_and_tree('.')
 
426
        self.branch = self.wt.branch
 
427
        self.build_tree(['file'])
 
428
        self.wt.commit('new branch', allow_pointless=True, rev_id='A')
 
429
        self.inv_A = self.branch.repository.get_inventory('A')
 
430
        self.wt.add(['file'], ['fileid'])
 
431
        self.wt.commit('add file', rev_id='B')
 
432
        self.inv_B = self.branch.repository.get_inventory('B')
 
433
        uncommit(self.branch, tree=self.wt)
 
434
        self.assertEqual(self.branch.revision_history(), ['A'])
 
435
        self.wt.commit('another add of file', rev_id='C')
 
436
        self.inv_C = self.branch.repository.get_inventory('C')
 
437
        self.wt.add_pending_merge('B')
 
438
        self.wt.commit('merge in B', rev_id='D')
 
439
        self.inv_D = self.branch.repository.get_inventory('D')
 
440
        self.file_active = self.wt.inventory['fileid']
 
441
        self.weave = self.branch.repository.weave_store.get_weave('fileid',
 
442
            self.branch.repository.get_transaction())
 
443
        
 
444
    def get_previous_heads(self, inventories):
 
445
        return self.file_active.find_previous_heads(
 
446
            inventories, 
 
447
            self.branch.repository.weave_store,
 
448
            self.branch.repository.get_transaction())
 
449
        
 
450
    def test_fileid_in_no_inventory(self):
 
451
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
 
452
 
 
453
    def test_fileid_in_one_inventory(self):
 
454
        self.assertEqual({'B':self.inv_B['fileid']},
 
455
                         self.get_previous_heads([self.inv_B]))
 
456
        self.assertEqual({'B':self.inv_B['fileid']},
 
457
                         self.get_previous_heads([self.inv_A, self.inv_B]))
 
458
        self.assertEqual({'B':self.inv_B['fileid']},
 
459
                         self.get_previous_heads([self.inv_B, self.inv_A]))
 
460
 
 
461
    def test_fileid_in_two_inventories_gives_both_entries(self):
 
462
        self.assertEqual({'B':self.inv_B['fileid'],
 
463
                          'C':self.inv_C['fileid']},
 
464
                          self.get_previous_heads([self.inv_B, self.inv_C]))
 
465
        self.assertEqual({'B':self.inv_B['fileid'],
 
466
                          'C':self.inv_C['fileid']},
 
467
                          self.get_previous_heads([self.inv_C, self.inv_B]))
 
468
 
 
469
    def test_fileid_in_two_inventories_already_merged_gives_head(self):
 
470
        self.assertEqual({'D':self.inv_D['fileid']},
 
471
                         self.get_previous_heads([self.inv_B, self.inv_D]))
 
472
        self.assertEqual({'D':self.inv_D['fileid']},
 
473
                         self.get_previous_heads([self.inv_D, self.inv_B]))
 
474
 
 
475
    # TODO: test two inventories with the same file revision 
 
476
 
 
477
 
113
478
class TestDescribeChanges(TestCase):
114
479
 
115
480
    def test_describe_change(self):
166
531
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
167
532
        change = InventoryEntry.describe_change(old_ie, new_ie)
168
533
        self.assertEqual(expected_change, change)
 
534
 
 
535
 
 
536
class TestRevert(TestCaseWithTransport):
 
537
 
 
538
    def test_dangling_id(self):
 
539
        wt = self.make_branch_and_tree('b1')
 
540
        self.assertEqual(len(wt.inventory), 1)
 
541
        open('b1/a', 'wb').write('a test\n')
 
542
        wt.add('a')
 
543
        self.assertEqual(len(wt.inventory), 2)
 
544
        os.unlink('b1/a')
 
545
        wt.revert([])
 
546
        self.assertEqual(len(wt.inventory), 1)