~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_inv.py

  • Committer: v.ladeuil+lp at free
  • Date: 2006-10-23 11:04:46 UTC
  • mto: (2145.1.1 keepalive)
  • mto: This revision was merged to the branch mainline in revision 2146.
  • Revision ID: v.ladeuil+lp@free.fr-20061023110446-1fddf0ae083c0c1d
Cosmetic fix for bug #57644.

* bzrlib/transport/http/_pycurl.py:
(PyCurlTransport._raise_curl_http_error): Mention url in aerror
message.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
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
17
from cStringIO import StringIO
18
18
import os
 
19
import time
19
20
 
 
21
from bzrlib import errors, inventory, osutils
20
22
from bzrlib.branch import Branch
21
 
from bzrlib.clone import copy_branch
22
 
import bzrlib.errors as errors
23
23
from bzrlib.diff import internal_diff
24
 
from bzrlib.inventory import Inventory, ROOT_ID
25
 
import bzrlib.inventory as inventory
26
 
from bzrlib.osutils import has_symlinks, rename
27
 
from bzrlib.selftest import TestCase, TestCaseInTempDir
 
24
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
28
31
 
29
32
 
30
33
class TestInventory(TestCase):
31
34
 
32
35
    def test_is_within(self):
33
 
        from bzrlib.osutils import is_inside_any
34
36
 
35
 
        SRC_FOO_C = os.path.join('src', 'foo.c')
 
37
        SRC_FOO_C = pathjoin('src', 'foo.c')
36
38
        for dirs, fn in [(['src', 'doc'], SRC_FOO_C),
37
39
                         (['src'], SRC_FOO_C),
38
40
                         (['src'], 'src'),
42
44
        for dirs, fn in [(['src'], 'srccontrol'),
43
45
                         (['src'], 'srccontrol/foo')]:
44
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))
45
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
 
46
62
    def test_ids(self):
47
63
        """Test detection of files within selected directories."""
48
64
        inv = Inventory()
59
75
        
60
76
        self.assert_('src-id' in inv)
61
77
 
62
 
 
 
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
            
63
124
    def test_version(self):
64
125
        """Inventory remembers the text's version."""
65
126
        inv = Inventory()
132
193
        link = inventory.InventoryLink('123', 'hello.c', ROOT_ID)
133
194
        self.failIf(link.has_text())
134
195
 
135
 
 
136
 
class TestEntryDiffing(TestCaseInTempDir):
 
196
    def test_make_entry(self):
 
197
        self.assertIsInstance(inventory.make_entry("file", "name", ROOT_ID),
 
198
            inventory.InventoryFile)
 
199
        self.assertIsInstance(inventory.make_entry("symlink", "name", ROOT_ID),
 
200
            inventory.InventoryLink)
 
201
        self.assertIsInstance(inventory.make_entry("directory", "name", ROOT_ID),
 
202
            inventory.InventoryDirectory)
 
203
 
 
204
    def test_make_entry_non_normalized(self):
 
205
        orig_normalized_filename = osutils.normalized_filename
 
206
 
 
207
        try:
 
208
            osutils.normalized_filename = osutils._accessible_normalized_filename
 
209
            entry = inventory.make_entry("file", u'a\u030a', ROOT_ID)
 
210
            self.assertEqual(u'\xe5', entry.name)
 
211
            self.assertIsInstance(entry, inventory.InventoryFile)
 
212
 
 
213
            osutils.normalized_filename = osutils._inaccessible_normalized_filename
 
214
            self.assertRaises(errors.InvalidNormalization,
 
215
                    inventory.make_entry, 'file', u'a\u030a', ROOT_ID)
 
216
        finally:
 
217
            osutils.normalized_filename = orig_normalized_filename
 
218
 
 
219
 
 
220
class TestEntryDiffing(TestCaseWithTransport):
137
221
 
138
222
    def setUp(self):
139
223
        super(TestEntryDiffing, self).setUp()
140
 
        self.branch = Branch.initialize('.')
 
224
        self.wt = self.make_branch_and_tree('.')
 
225
        self.branch = self.wt.branch
141
226
        print >> open('file', 'wb'), 'foo'
142
 
        self.branch.add(['file'], ['fileid'])
 
227
        print >> open('binfile', 'wb'), 'foo'
 
228
        self.wt.add(['file'], ['fileid'])
 
229
        self.wt.add(['binfile'], ['binfileid'])
143
230
        if has_symlinks():
144
231
            os.symlink('target1', 'symlink')
145
 
            self.branch.add(['symlink'], ['linkid'])
146
 
        self.branch.commit('message_1', rev_id = '1')
 
232
            self.wt.add(['symlink'], ['linkid'])
 
233
        self.wt.commit('message_1', rev_id = '1')
147
234
        print >> open('file', 'wb'), 'bar'
 
235
        print >> open('binfile', 'wb'), 'x' * 1023 + '\x00'
148
236
        if has_symlinks():
149
237
            os.unlink('symlink')
150
238
            os.symlink('target2', 'symlink')
151
 
        self.tree_1 = self.branch.revision_tree('1')
152
 
        self.inv_1 = self.branch.get_inventory('1')
 
239
        self.tree_1 = self.branch.repository.revision_tree('1')
 
240
        self.inv_1 = self.branch.repository.get_inventory('1')
153
241
        self.file_1 = self.inv_1['fileid']
154
 
        self.tree_2 = self.branch.working_tree()
155
 
        self.inv_2 = self.branch.inventory
 
242
        self.file_1b = self.inv_1['binfileid']
 
243
        self.tree_2 = self.wt
 
244
        self.inv_2 = self.tree_2.read_working_inventory()
156
245
        self.file_2 = self.inv_2['fileid']
 
246
        self.file_2b = self.inv_2['binfileid']
157
247
        if has_symlinks():
158
248
            self.link_1 = self.inv_1['linkid']
159
249
            self.link_2 = self.inv_2['linkid']
195
285
                                            "+bar\n"
196
286
                                            "\n")
197
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")
198
296
    def test_link_diff_deleted(self):
 
297
        if not has_symlinks():
 
298
            return
199
299
        output = StringIO()
200
300
        self.link_1.diff(internal_diff, 
201
301
                          "old_label", self.tree_1,
205
305
                         "=== target was 'target1'\n")
206
306
 
207
307
    def test_link_diff_added(self):
 
308
        if not has_symlinks():
 
309
            return
208
310
        output = StringIO()
209
311
        self.link_1.diff(internal_diff, 
210
312
                          "new_label", self.tree_1,
214
316
                         "=== target is 'target1'\n")
215
317
 
216
318
    def test_link_diff_changed(self):
 
319
        if not has_symlinks():
 
320
            return
217
321
        output = StringIO()
218
322
        self.link_1.diff(internal_diff, 
219
323
                          "/dev/null", self.tree_1, 
223
327
                         "=== target changed 'target1' => 'target2'\n")
224
328
 
225
329
 
226
 
class TestSnapshot(TestCaseInTempDir):
 
330
class TestSnapshot(TestCaseWithTransport):
227
331
 
228
332
    def setUp(self):
229
333
        # for full testing we'll need a branch
233
337
        # to change, and then test merge patterns
234
338
        # with fake parent entries.
235
339
        super(TestSnapshot, self).setUp()
236
 
        self.branch = Branch.initialize('.')
237
 
        self.build_tree(['subdir/', 'subdir/file'])
238
 
        self.branch.add(['subdir', 'subdir/file'], ['dirid', 'fileid'])
 
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'])
239
345
        if has_symlinks():
240
346
            pass
241
 
        self.branch.commit('message_1', rev_id = '1')
242
 
        self.tree_1 = self.branch.revision_tree('1')
243
 
        self.inv_1 = self.branch.get_inventory('1')
 
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')
244
350
        self.file_1 = self.inv_1['fileid']
245
 
        self.work_tree = self.branch.working_tree()
246
 
        self.file_active = self.work_tree.inventory['fileid']
 
351
        self.file_active = self.wt.inventory['fileid']
 
352
        self.builder = self.branch.get_commit_builder([], timestamp=time.time(), revision_id='2')
247
353
 
248
354
    def test_snapshot_new_revision(self):
249
355
        # This tests that a simple commit with no parents makes a new
250
356
        # revision value in the inventory entry
251
 
        self.file_active.snapshot('2', 'subdir/file', {}, self.work_tree, 
252
 
                                  self.branch.weave_store)
 
357
        self.file_active.snapshot('2', 'subdir/file', {}, self.wt, self.builder)
253
358
        # expected outcome - file_1 has a revision id of '2', and we can get
254
359
        # its text of 'file contents' out of the weave.
255
360
        self.assertEqual(self.file_1.revision, '1')
256
361
        self.assertEqual(self.file_active.revision, '2')
257
362
        # this should be a separate test probably, but lets check it once..
258
 
        lines = self.branch.weave_store.get_lines('fileid','2')
 
363
        lines = self.branch.repository.weave_store.get_weave(
 
364
            'fileid', 
 
365
            self.branch.get_transaction()).get_lines('2')
259
366
        self.assertEqual(lines, ['contents of subdir/file\n'])
260
367
 
261
368
    def test_snapshot_unchanged(self):
262
369
        #This tests that a simple commit does not make a new entry for
263
370
        # an unchanged inventory entry
264
371
        self.file_active.snapshot('2', 'subdir/file', {'1':self.file_1},
265
 
                                  self.work_tree, self.branch.weave_store)
 
372
                                  self.wt, self.builder)
266
373
        self.assertEqual(self.file_1.revision, '1')
267
374
        self.assertEqual(self.file_active.revision, '1')
268
 
        self.assertRaises(errors.WeaveError,
269
 
                          self.branch.weave_store.get_lines, 'fileid', '2')
 
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')
270
381
 
271
382
    def test_snapshot_merge_identical_different_revid(self):
272
383
        # This tests that a commit with two identical parents, one of which has
280
391
        self.assertEqual(self.file_1, other_ie)
281
392
        other_ie.revision = 'other'
282
393
        self.assertNotEqual(self.file_1, other_ie)
283
 
        self.branch.weave_store.add_identical_text('fileid', '1', 'other', ['1'])
 
394
        versionfile = self.branch.repository.weave_store.get_weave(
 
395
            'fileid', self.branch.repository.get_transaction())
 
396
        versionfile.clone_text('other', '1', ['1'])
284
397
        self.file_active.snapshot('2', 'subdir/file', 
285
398
                                  {'1':self.file_1, 'other':other_ie},
286
 
                                  self.work_tree, self.branch.weave_store)
 
399
                                  self.wt, self.builder)
287
400
        self.assertEqual(self.file_active.revision, '2')
288
401
 
289
402
    def test_snapshot_changed(self):
292
405
        self.file_active.name='newname'
293
406
        rename('subdir/file', 'subdir/newname')
294
407
        self.file_active.snapshot('2', 'subdir/newname', {'1':self.file_1}, 
295
 
                                  self.work_tree, 
296
 
                                  self.branch.weave_store)
 
408
                                  self.wt, self.builder)
297
409
        # expected outcome - file_1 has a revision id of '2'
298
410
        self.assertEqual(self.file_active.revision, '2')
299
411
 
300
412
 
301
 
class TestPreviousHeads(TestCaseInTempDir):
 
413
class TestPreviousHeads(TestCaseWithTransport):
302
414
 
303
415
    def setUp(self):
304
416
        # we want several inventories, that respectively
310
422
        # D) fileid present in two inventories and one is
311
423
        #   a descendent of the other. (B, D)
312
424
        super(TestPreviousHeads, self).setUp()
 
425
        self.wt = self.make_branch_and_tree('.')
 
426
        self.branch = self.wt.branch
313
427
        self.build_tree(['file'])
314
 
        self.branch = Branch.initialize('.')
315
 
        self.branch.commit('new branch', allow_pointless=True, rev_id='A')
316
 
        self.inv_A = self.branch.get_inventory('A')
317
 
        self.branch.add(['file'], ['fileid'])
318
 
        self.branch.commit('add file', rev_id='B')
319
 
        self.inv_B = self.branch.get_inventory('B')
320
 
        self.branch.put_controlfile('revision-history', 'A\n')
 
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)
321
434
        self.assertEqual(self.branch.revision_history(), ['A'])
322
 
        self.branch.commit('another add of file', rev_id='C')
323
 
        self.inv_C = self.branch.get_inventory('C')
324
 
        self.branch.add_pending_merge('B')
325
 
        self.branch.commit('merge in B', rev_id='D')
326
 
        self.inv_D = self.branch.get_inventory('D')
327
 
        self.file_active = self.branch.working_tree().inventory['fileid']
328
 
        self.weave = self.branch.weave_store.get_weave('fileid')
 
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_parent_tree_id('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())
329
443
        
330
444
    def get_previous_heads(self, inventories):
331
 
        return self.file_active.find_previous_heads(inventories, self.weave)
 
445
        return self.file_active.find_previous_heads(
 
446
            inventories, 
 
447
            self.branch.repository.weave_store,
 
448
            self.branch.repository.get_transaction())
332
449
        
333
450
    def test_fileid_in_no_inventory(self):
334
451
        self.assertEqual({}, self.get_previous_heads([self.inv_A]))
356
473
                         self.get_previous_heads([self.inv_D, self.inv_B]))
357
474
 
358
475
    # TODO: test two inventories with the same file revision 
 
476
 
 
477
 
 
478
class TestDescribeChanges(TestCase):
 
479
 
 
480
    def test_describe_change(self):
 
481
        # we need to test the following change combinations:
 
482
        # rename
 
483
        # reparent
 
484
        # modify
 
485
        # gone
 
486
        # added
 
487
        # renamed/reparented and modified
 
488
        # change kind (perhaps can't be done yet?)
 
489
        # also, merged in combination with all of these?
 
490
        old_a = InventoryFile('a-id', 'a_file', ROOT_ID)
 
491
        old_a.text_sha1 = '123132'
 
492
        old_a.text_size = 0
 
493
        new_a = InventoryFile('a-id', 'a_file', ROOT_ID)
 
494
        new_a.text_sha1 = '123132'
 
495
        new_a.text_size = 0
 
496
 
 
497
        self.assertChangeDescription('unchanged', old_a, new_a)
 
498
 
 
499
        new_a.text_size = 10
 
500
        new_a.text_sha1 = 'abcabc'
 
501
        self.assertChangeDescription('modified', old_a, new_a)
 
502
 
 
503
        self.assertChangeDescription('added', None, new_a)
 
504
        self.assertChangeDescription('removed', old_a, None)
 
505
        # perhaps a bit questionable but seems like the most reasonable thing...
 
506
        self.assertChangeDescription('unchanged', None, None)
 
507
 
 
508
        # in this case it's both renamed and modified; show a rename and 
 
509
        # modification:
 
510
        new_a.name = 'newfilename'
 
511
        self.assertChangeDescription('modified and renamed', old_a, new_a)
 
512
 
 
513
        # reparenting is 'renaming'
 
514
        new_a.name = old_a.name
 
515
        new_a.parent_id = 'somedir-id'
 
516
        self.assertChangeDescription('modified and renamed', old_a, new_a)
 
517
 
 
518
        # reset the content values so its not modified
 
519
        new_a.text_size = old_a.text_size
 
520
        new_a.text_sha1 = old_a.text_sha1
 
521
        new_a.name = old_a.name
 
522
 
 
523
        new_a.name = 'newfilename'
 
524
        self.assertChangeDescription('renamed', old_a, new_a)
 
525
 
 
526
        # reparenting is 'renaming'
 
527
        new_a.name = old_a.name
 
528
        new_a.parent_id = 'somedir-id'
 
529
        self.assertChangeDescription('renamed', old_a, new_a)
 
530
 
 
531
    def assertChangeDescription(self, expected_change, old_ie, new_ie):
 
532
        change = InventoryEntry.describe_change(old_ie, new_ie)
 
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)
 
547
 
 
548
 
 
549
class TestIsRoot(TestCase):
 
550
    """Ensure our root-checking code is accurate."""
 
551
 
 
552
    def test_is_root(self):
 
553
        inv = Inventory('TREE_ROOT')
 
554
        self.assertTrue(inv.is_root('TREE_ROOT'))
 
555
        self.assertFalse(inv.is_root('booga'))
 
556
        inv.root.file_id = 'booga'
 
557
        self.assertFalse(inv.is_root('TREE_ROOT'))
 
558
        self.assertTrue(inv.is_root('booga'))
 
559
        # works properly even if no root is set
 
560
        inv.root = None
 
561
        self.assertFalse(inv.is_root('TREE_ROOT'))
 
562
        self.assertFalse(inv.is_root('booga'))