~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: Alexander Belchenko
  • Date: 2007-01-04 23:36:44 UTC
  • mfrom: (2224 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2225.
  • Revision ID: bialix@ukr.net-20070104233644-7znkxoj9b0y7ev28
merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
from bzrlib import errors, inventory, osutils
 
22
from bzrlib.branch import Branch
 
23
from bzrlib.diff import internal_diff
18
24
from bzrlib.inventory import (Inventory, ROOT_ID, InventoryFile,
19
 
    InventoryDirectory, InventoryEntry, TreeReference)
20
 
from bzrlib.osutils import (pathjoin, is_inside_any, 
 
25
    InventoryDirectory, InventoryEntry)
 
26
from bzrlib.osutils import (has_symlinks, rename, pathjoin, is_inside_any, 
21
27
    is_inside_or_parent_of_any)
22
 
from bzrlib.tests import TestCase
 
28
from bzrlib.tests import TestCase, TestCaseWithTransport
 
29
from bzrlib.transform import TreeTransform
 
30
from bzrlib.uncommit import uncommit
23
31
 
24
32
 
25
33
class TestInventory(TestCase):
131
139
            ('src/sub/a', 'a-id'),
132
140
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir()])
133
141
            
134
 
        self.assertEqual([
135
 
            ('', ROOT_ID),
136
 
            ('Makefile', 'makefile-id'),
137
 
            ('doc', 'doc-id'),
138
 
            ('src', 'src-id'),
139
 
            ('zz', 'zz-id'),
140
 
            ('src/bye.c', 'bye-id'),
141
 
            ('src/hello.c', 'hello-id'),
142
 
            ('src/sub', 'sub-id'),
143
 
            ('src/zz.c', 'zzc-id'),
144
 
            ('src/sub/a', 'a-id'),
145
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
146
 
                specific_file_ids=('a-id', 'zzc-id', 'doc-id', ROOT_ID,
147
 
                'hello-id', 'bye-id', 'zz-id', 'src-id', 'makefile-id', 
148
 
                'sub-id'))])
149
 
 
150
 
        self.assertEqual([
151
 
            ('Makefile', 'makefile-id'),
152
 
            ('doc', 'doc-id'),
153
 
            ('zz', 'zz-id'),
154
 
            ('src/bye.c', 'bye-id'),
155
 
            ('src/hello.c', 'hello-id'),
156
 
            ('src/zz.c', 'zzc-id'),
157
 
            ('src/sub/a', 'a-id'),
158
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
159
 
                specific_file_ids=('a-id', 'zzc-id', 'doc-id',
160
 
                'hello-id', 'bye-id', 'zz-id', 'makefile-id'))])
161
 
 
162
 
        self.assertEqual([
163
 
            ('Makefile', 'makefile-id'),
164
 
            ('src/bye.c', 'bye-id'),
165
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
166
 
                specific_file_ids=('bye-id', 'makefile-id'))])
167
 
 
168
 
        self.assertEqual([
169
 
            ('Makefile', 'makefile-id'),
170
 
            ('src/bye.c', 'bye-id'),
171
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
172
 
                specific_file_ids=('bye-id', 'makefile-id'))])
173
 
 
174
 
        self.assertEqual([
175
 
            ('src/bye.c', 'bye-id'),
176
 
            ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
177
 
                specific_file_ids=('bye-id',))])
178
 
 
179
 
    def test_add_recursive(self):
180
 
        parent = InventoryDirectory('src-id', 'src', ROOT_ID)
181
 
        child = InventoryFile('hello-id', 'hello.c', 'src-id')
182
 
        parent.children[child.file_id] = child
 
142
    def test_version(self):
 
143
        """Inventory remembers the text's version."""
183
144
        inv = Inventory()
184
 
        inv.add(parent)
185
 
        self.assertEqual('src/hello.c', inv.id2path('hello-id'))
 
145
        ie = inv.add_path('foo.txt', 'file')
 
146
        ## XXX
186
147
 
187
148
 
188
149
class TestInventoryEntry(TestCase):
274
235
            osutils.normalized_filename = orig_normalized_filename
275
236
 
276
237
 
 
238
class TestEntryDiffing(TestCaseWithTransport):
 
239
 
 
240
    def setUp(self):
 
241
        super(TestEntryDiffing, self).setUp()
 
242
        self.wt = self.make_branch_and_tree('.')
 
243
        self.branch = self.wt.branch
 
244
        print >> open('file', 'wb'), 'foo'
 
245
        print >> open('binfile', 'wb'), 'foo'
 
246
        self.wt.add(['file'], ['fileid'])
 
247
        self.wt.add(['binfile'], ['binfileid'])
 
248
        if has_symlinks():
 
249
            os.symlink('target1', 'symlink')
 
250
            self.wt.add(['symlink'], ['linkid'])
 
251
        self.wt.commit('message_1', rev_id = '1')
 
252
        print >> open('file', 'wb'), 'bar'
 
253
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
 
254
        if has_symlinks():
 
255
            os.unlink('symlink')
 
256
            os.symlink('target2', 'symlink')
 
257
        self.tree_1 = self.branch.repository.revision_tree('1')
 
258
        self.inv_1 = self.branch.repository.get_inventory('1')
 
259
        self.file_1 = self.inv_1['fileid']
 
260
        self.file_1b = self.inv_1['binfileid']
 
261
        self.tree_2 = self.wt
 
262
        self.inv_2 = self.tree_2.read_working_inventory()
 
263
        self.file_2 = self.inv_2['fileid']
 
264
        self.file_2b = self.inv_2['binfileid']
 
265
        if has_symlinks():
 
266
            self.link_1 = self.inv_1['linkid']
 
267
            self.link_2 = self.inv_2['linkid']
 
268
 
 
269
    def test_file_diff_deleted(self):
 
270
        output = StringIO()
 
271
        self.file_1.diff(internal_diff, 
 
272
                          "old_label", self.tree_1,
 
273
                          "/dev/null", None, None,
 
274
                          output)
 
275
        self.assertEqual(output.getvalue(), "--- old_label\n"
 
276
                                            "+++ /dev/null\n"
 
277
                                            "@@ -1,1 +0,0 @@\n"
 
278
                                            "-foo\n"
 
279
                                            "\n")
 
280
 
 
281
    def test_file_diff_added(self):
 
282
        output = StringIO()
 
283
        self.file_1.diff(internal_diff, 
 
284
                          "new_label", self.tree_1,
 
285
                          "/dev/null", None, None,
 
286
                          output, reverse=True)
 
287
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
 
288
                                            "+++ new_label\n"
 
289
                                            "@@ -0,0 +1,1 @@\n"
 
290
                                            "+foo\n"
 
291
                                            "\n")
 
292
 
 
293
    def test_file_diff_changed(self):
 
294
        output = StringIO()
 
295
        self.file_1.diff(internal_diff, 
 
296
                          "/dev/null", self.tree_1, 
 
297
                          "new_label", self.file_2, self.tree_2,
 
298
                          output)
 
299
        self.assertEqual(output.getvalue(), "--- /dev/null\n"
 
300
                                            "+++ new_label\n"
 
301
                                            "@@ -1,1 +1,1 @@\n"
 
302
                                            "-foo\n"
 
303
                                            "+bar\n"
 
304
                                            "\n")
 
305
        
 
306
    def test_file_diff_binary(self):
 
307
        output = StringIO()
 
308
        self.file_1.diff(internal_diff, 
 
309
                          "/dev/null", self.tree_1, 
 
310
                          "new_label", self.file_2b, self.tree_2,
 
311
                          output)
 
312
        self.assertEqual(output.getvalue(), 
 
313
                         "Binary files /dev/null and new_label differ\n")
 
314
    def test_link_diff_deleted(self):
 
315
        if not has_symlinks():
 
316
            return
 
317
        output = StringIO()
 
318
        self.link_1.diff(internal_diff, 
 
319
                          "old_label", self.tree_1,
 
320
                          "/dev/null", None, None,
 
321
                          output)
 
322
        self.assertEqual(output.getvalue(),
 
323
                         "=== target was 'target1'\n")
 
324
 
 
325
    def test_link_diff_added(self):
 
326
        if not has_symlinks():
 
327
            return
 
328
        output = StringIO()
 
329
        self.link_1.diff(internal_diff, 
 
330
                          "new_label", self.tree_1,
 
331
                          "/dev/null", None, None,
 
332
                          output, reverse=True)
 
333
        self.assertEqual(output.getvalue(),
 
334
                         "=== target is 'target1'\n")
 
335
 
 
336
    def test_link_diff_changed(self):
 
337
        if not has_symlinks():
 
338
            return
 
339
        output = StringIO()
 
340
        self.link_1.diff(internal_diff, 
 
341
                          "/dev/null", self.tree_1, 
 
342
                          "new_label", self.link_2, self.tree_2,
 
343
                          output)
 
344
        self.assertEqual(output.getvalue(),
 
345
                         "=== target changed 'target1' => 'target2'\n")
 
346
 
 
347
 
 
348
class TestSnapshot(TestCaseWithTransport):
 
349
 
 
350
    def setUp(self):
 
351
        # for full testing we'll need a branch
 
352
        # with a subdir to test parent changes.
 
353
        # and a file, link and dir under that.
 
354
        # but right now I only need one attribute
 
355
        # to change, and then test merge patterns
 
356
        # with fake parent entries.
 
357
        super(TestSnapshot, self).setUp()
 
358
        self.wt = self.make_branch_and_tree('.')
 
359
        self.branch = self.wt.branch
 
360
        self.build_tree(['subdir/', 'subdir/file'], line_endings='binary')
 
361
        self.wt.add(['subdir', 'subdir/file'],
 
362
                                       ['dirid', 'fileid'])
 
363
        if has_symlinks():
 
364
            pass
 
365
        self.wt.commit('message_1', rev_id = '1')
 
366
        self.tree_1 = self.branch.repository.revision_tree('1')
 
367
        self.inv_1 = self.branch.repository.get_inventory('1')
 
368
        self.file_1 = self.inv_1['fileid']
 
369
        self.file_active = self.wt.inventory['fileid']
 
370
        self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
 
371
 
 
372
    def test_snapshot_new_revision(self):
 
373
        # This tests that a simple commit with no parents makes a new
 
374
        # revision value in the inventory entry
 
375
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
 
376
        # expected outcome - file_1 has a revision id of '2', and we can get
 
377
        # its text of 'file contents' out of the weave.
 
378
        self.assertEqual(self.file_1.revision, '1')
 
379
        self.assertEqual(self.file_active.revision, '2')
 
380
        # this should be a separate test probably, but lets check it once..
 
381
        lines = self.branch.repository.weave_store.get_weave(
 
382
            'fileid', 
 
383
            self.branch.get_transaction()).get_lines('2')
 
384
        self.assertEqual(lines, ['contents of subdir/file\n'])
 
385
 
 
386
    def test_snapshot_unchanged(self):
 
387
        #This tests that a simple commit does not make a new entry for
 
388
        # an unchanged inventory entry
 
389
        self.file_active.snapshot('2', 'subdir/file', {'1':self.file_1},
 
390
                                  self.wt, self.builder)
 
391
        self.assertEqual(self.file_1.revision, '1')
 
392
        self.assertEqual(self.file_active.revision, '1')
 
393
        vf = self.branch.repository.weave_store.get_weave(
 
394
            'fileid', 
 
395
            self.branch.repository.get_transaction())
 
396
        self.assertRaises(errors.RevisionNotPresent,
 
397
                          vf.get_lines,
 
398
                          '2')
 
399
 
 
400
    def test_snapshot_merge_identical_different_revid(self):
 
401
        # This tests that a commit with two identical parents, one of which has
 
402
        # a different revision id, results in a new revision id in the entry.
 
403
        # 1->other, commit a merge of other against 1, results in 2.
 
404
        other_ie = inventory.InventoryFile('fileid', 'newname', self.file_1.parent_id)
 
405
        other_ie = inventory.InventoryFile('fileid', 'file', self.file_1.parent_id)
 
406
        other_ie.revision = '1'
 
407
        other_ie.text_sha1 = self.file_1.text_sha1
 
408
        other_ie.text_size = self.file_1.text_size
 
409
        self.assertEqual(self.file_1, other_ie)
 
410
        other_ie.revision = 'other'
 
411
        self.assertNotEqual(self.file_1, other_ie)
 
412
        versionfile = self.branch.repository.weave_store.get_weave(
 
413
            'fileid', self.branch.repository.get_transaction())
 
414
        versionfile.clone_text('other', '1', ['1'])
 
415
        self.file_active.snapshot('2', 'subdir/file', 
 
416
                                  {'1':self.file_1, 'other':other_ie},
 
417
                                  self.wt, self.builder)
 
418
        self.assertEqual(self.file_active.revision, '2')
 
419
 
 
420
    def test_snapshot_changed(self):
 
421
        # This tests that a commit with one different parent results in a new
 
422
        # revision id in the entry.
 
423
        self.file_active.name='newname'
 
424
        rename('subdir/file', 'subdir/newname')
 
425
        self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1}, 
 
426
                                  self.wt, self.builder)
 
427
        # expected outcome - file_1 has a revision id of '2'
 
428
        self.assertEqual(self.file_active.revision, '2')
 
429
 
 
430
 
 
431
class TestPreviousHeads(TestCaseWithTransport):
 
432
 
 
433
    def setUp(self):
 
434
        # we want several inventories, that respectively
 
435
        # give use the following scenarios:
 
436
        # A) fileid not in any inventory (A),
 
437
        # B) fileid present in one inventory (B) and (A,B)
 
438
        # C) fileid present in two inventories, and they
 
439
        #   are not mutual descendents (B, C)
 
440
        # D) fileid present in two inventories and one is
 
441
        #   a descendent of the other. (B, D)
 
442
        super(TestPreviousHeads, self).setUp()
 
443
        self.wt = self.make_branch_and_tree('.')
 
444
        self.branch = self.wt.branch
 
445
        self.build_tree(['file'])
 
446
        self.wt.commit('new branch', allow_pointless=True, rev_id='A')
 
447
        self.inv_A = self.branch.repository.get_inventory('A')
 
448
        self.wt.add(['file'], ['fileid'])
 
449
        self.wt.commit('add file', rev_id='B')
 
450
        self.inv_B = self.branch.repository.get_inventory('B')
 
451
        uncommit(self.branch, tree=self.wt)
 
452
        self.assertEqual(self.branch.revision_history(), ['A'])
 
453
        self.wt.commit('another add of file', rev_id='C')
 
454
        self.inv_C = self.branch.repository.get_inventory('C')
 
455
        self.wt.add_parent_tree_id('B')
 
456
        self.wt.commit('merge in B', rev_id='D')
 
457
        self.inv_D = self.branch.repository.get_inventory('D')
 
458
        self.file_active = self.wt.inventory['fileid']
 
459
        self.weave = self.branch.repository.weave_store.get_weave('fileid',
 
460
            self.branch.repository.get_transaction())
 
461
        
 
462
    def get_previous_heads(self, inventories):
 
463
        return self.file_active.find_previous_heads(
 
464
            inventories, 
 
465
            self.branch.repository.weave_store,
 
466
            self.branch.repository.get_transaction())
 
467
        
 
468
    def test_fileid_in_no_inventory(self):
 
469
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
 
470
 
 
471
    def test_fileid_in_one_inventory(self):
 
472
        self.assertEqual({'B':self.inv_B['fileid']},
 
473
                         self.get_previous_heads([self.inv_B]))
 
474
        self.assertEqual({'B':self.inv_B['fileid']},
 
475
                         self.get_previous_heads([self.inv_A, self.inv_B]))
 
476
        self.assertEqual({'B':self.inv_B['fileid']},
 
477
                         self.get_previous_heads([self.inv_B, self.inv_A]))
 
478
 
 
479
    def test_fileid_in_two_inventories_gives_both_entries(self):
 
480
        self.assertEqual({'B':self.inv_B['fileid'],
 
481
                          'C':self.inv_C['fileid']},
 
482
                          self.get_previous_heads([self.inv_B, self.inv_C]))
 
483
        self.assertEqual({'B':self.inv_B['fileid'],
 
484
                          'C':self.inv_C['fileid']},
 
485
                          self.get_previous_heads([self.inv_C, self.inv_B]))
 
486
 
 
487
    def test_fileid_in_two_inventories_already_merged_gives_head(self):
 
488
        self.assertEqual({'D':self.inv_D['fileid']},
 
489
                         self.get_previous_heads([self.inv_B, self.inv_D]))
 
490
        self.assertEqual({'D':self.inv_D['fileid']},
 
491
                         self.get_previous_heads([self.inv_D, self.inv_B]))
 
492
 
 
493
    # TODO: test two inventories with the same file revision 
 
494
 
 
495
 
277
496
class TestDescribeChanges(TestCase):
278
497
 
279
498
    def test_describe_change(self):
332
551
        self.assertEqual(expected_change, change)
333
552
 
334
553
 
 
554
class TestRevert(TestCaseWithTransport):
 
555
 
 
556
    def test_dangling_id(self):
 
557
        wt = self.make_branch_and_tree('b1')
 
558
        self.assertEqual(len(wt.inventory), 1)
 
559
        open('b1/a', 'wb').write('a test\n')
 
560
        wt.add('a')
 
561
        self.assertEqual(len(wt.inventory), 2)
 
562
        os.unlink('b1/a')
 
563
        wt.revert([])
 
564
        self.assertEqual(len(wt.inventory), 1)
 
565
 
 
566
 
335
567
class TestIsRoot(TestCase):
336
568
    """Ensure our root-checking code is accurate."""
337
569
 
346
578
        inv.root = None
347
579
        self.assertFalse(inv.is_root('TREE_ROOT'))
348
580
        self.assertFalse(inv.is_root('booga'))
349
 
 
350
 
 
351
 
class TestTreeReference(TestCase):
352
 
    
353
 
    def test_create(self):
354
 
        inv = Inventory('tree-root-123')
355
 
        inv.add(TreeReference('nested-id', 'nested', parent_id='tree-root-123',
356
 
                              revision='rev', reference_revision='rev2'))
357
 
 
358
 
 
359
 
class TestEncoding(TestCase):
360
 
 
361
 
    def test_error_encoding(self):
362
 
        inv = Inventory('tree-root')
363
 
        inv.add(InventoryFile('a-id', u'\u1234', 'tree-root'))
364
 
        try:
365
 
            inv.add(InventoryFile('b-id', u'\u1234', 'tree-root'))
366
 
        except errors.BzrError, e:
367
 
            self.assertContainsRe(str(e), u'\u1234'.encode('utf-8'))
368
 
        else:
369
 
            self.fail('BzrError not raised')