~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: John Arbash Meinel
  • Date: 2006-11-10 15:38:16 UTC
  • mto: This revision was merged to the branch mainline in revision 2129.
  • Revision ID: john@arbash-meinel.com-20061110153816-46acf76fc86a512b
use try/finally to clean up a nested progress bar during weave fetching

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