~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart_add.py

  • Committer: Robert Collins
  • Date: 2007-07-03 02:33:32 UTC
  • mto: This revision was merged to the branch mainline in revision 2581.
  • Revision ID: robertc@robertcollins.net-20070703023332-jz0qdt2dwhzjuhlc
* ``bzrlib.add.smart_add`` and ``bzrlib.add.smart_add_tree`` are now
  deprecated in favour of ``MutableTree.smart_add``. (Robert Collins,
  Martin Pool)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 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
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
from cStringIO import StringIO
18
 
import os
19
 
import unittest
20
18
 
21
 
from bzrlib import errors, ignores, osutils
 
19
from bzrlib import osutils
22
20
from bzrlib.add import (
23
21
    AddAction,
24
22
    AddFromBaseAction,
25
 
    smart_add_tree,
26
23
    )
27
 
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
28
 
from bzrlib.errors import NoSuchFile
29
 
from bzrlib.inventory import InventoryFile, Inventory
30
 
from bzrlib.workingtree import WorkingTree
31
 
 
32
 
 
33
 
class TestSmartAdd(TestCaseWithTransport):
34
 
 
35
 
    def test_add_dot_from_root(self):
36
 
        """Test adding . from the root of the tree.""" 
37
 
        paths = ("original/", "original/file1", "original/file2")
38
 
        self.build_tree(paths)
39
 
        wt = self.make_branch_and_tree('.')
40
 
        smart_add_tree(wt, (u".",))
41
 
        for path in paths:
42
 
            self.assertNotEqual(wt.path2id(path), None)
43
 
 
44
 
    def test_add_dot_from_subdir(self):
45
 
        """Test adding . from a subdir of the tree.""" 
46
 
        paths = ("original/", "original/file1", "original/file2")
47
 
        self.build_tree(paths)
48
 
        wt = self.make_branch_and_tree('.')
49
 
        os.chdir("original")
50
 
        smart_add_tree(wt, (u".",))
51
 
        for path in paths:
52
 
            self.assertNotEqual(wt.path2id(path), None)
53
 
 
54
 
    def test_add_tree_from_above_tree(self):
55
 
        """Test adding a tree from above the tree.""" 
56
 
        paths = ("original/", "original/file1", "original/file2")
57
 
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
58
 
                        "branch/original/file2")
59
 
        self.build_tree(branch_paths)
60
 
        wt = self.make_branch_and_tree('branch')
61
 
        smart_add_tree(wt, ("branch",))
62
 
        for path in paths:
63
 
            self.assertNotEqual(wt.path2id(path), None)
64
 
 
65
 
    def test_add_above_tree_preserves_tree(self):
66
 
        """Test nested trees are not affect by an add above them."""
67
 
        paths = ("original/", "original/file1", "original/file2")
68
 
        child_paths = ("path",)
69
 
        full_child_paths = ("original/child", "original/child/path")
70
 
        build_paths = ("original/", "original/file1", "original/file2", 
71
 
                       "original/child/", "original/child/path")
72
 
        
73
 
        self.build_tree(build_paths)
74
 
        wt = self.make_branch_and_tree('.')
75
 
        child_tree = self.make_branch_and_tree('original/child')
76
 
        smart_add_tree(wt, (".",))
77
 
        for path in paths:
78
 
            self.assertNotEqual((path, wt.path2id(path)),
79
 
                                (path, None))
80
 
        for path in full_child_paths:
81
 
            self.assertEqual((path, wt.path2id(path)),
82
 
                             (path, None))
83
 
        for path in child_paths:
84
 
            self.assertEqual(child_tree.path2id(path), None)
85
 
 
86
 
    def test_add_paths(self):
87
 
        """Test smart-adding a list of paths."""
88
 
        paths = ("file1", "file2")
89
 
        self.build_tree(paths)
90
 
        wt = self.make_branch_and_tree('.')
91
 
        smart_add_tree(wt, paths)
92
 
        for path in paths:
93
 
            self.assertNotEqual(wt.path2id(path), None)
94
 
    
95
 
    def test_add_ignored_nested_paths(self):
96
 
        """Test smart-adding a list of paths which includes ignored ones."""
97
 
        wt = self.make_branch_and_tree('.')
98
 
        tree_shape = ("adir/", "adir/CVS/", "adir/CVS/afile", "adir/CVS/afile2")
99
 
        add_paths = ("adir/CVS", "adir/CVS/afile", "adir")
100
 
        expected_paths = ("adir", "adir/CVS", "adir/CVS/afile", "adir/CVS/afile2")
101
 
        self.build_tree(tree_shape)
102
 
        smart_add_tree(wt, add_paths)
103
 
        for path in expected_paths:
104
 
            self.assertNotEqual(wt.path2id(path), None, "No id added for %s" % path)
105
 
 
106
 
    def test_add_dry_run(self):
107
 
        """Test a dry run add, make sure nothing is added."""
108
 
        from bzrlib.commands import run_bzr
109
 
        eq = self.assertEqual
110
 
        wt = self.make_branch_and_tree('.')
111
 
        self.build_tree(['inertiatic/', 'inertiatic/esp'])
112
 
        eq(list(wt.unknowns()), ['inertiatic'])
113
 
        self.run_bzr('add --dry-run .')
114
 
        eq(list(wt.unknowns()), ['inertiatic'])
115
 
 
116
 
    def test_add_non_existant(self):
117
 
        """Test smart-adding a file that does not exist."""
118
 
        wt = self.make_branch_and_tree('.')
119
 
        self.assertRaises(NoSuchFile, smart_add_tree, wt, 'non-existant-file')
120
 
 
121
 
    def test_returns_and_ignores(self):
122
 
        """Correctly returns added/ignored files"""
123
 
        from bzrlib.commands import run_bzr
124
 
        wt = self.make_branch_and_tree('.')
125
 
        # The default ignore list includes '*.py[co]', but not CVS
126
 
        ignores._set_user_ignores(['*.py[co]'])
127
 
        self.build_tree(['inertiatic/', 'inertiatic/esp', 'inertiatic/CVS',
128
 
                        'inertiatic/foo.pyc'])
129
 
        added, ignored = smart_add_tree(wt, u'.')
130
 
        self.assertSubset(('inertiatic', 'inertiatic/esp', 'inertiatic/CVS'),
131
 
                          added)
132
 
        self.assertSubset(('*.py[co]',), ignored)
133
 
        self.assertSubset(('inertiatic/foo.pyc',), ignored['*.py[co]'])
 
24
from bzrlib.tests import TestCase, TestCaseWithTransport
 
25
from bzrlib.inventory import Inventory
134
26
 
135
27
 
136
28
class AddCustomIDAction(AddAction):
147
39
        return file_id
148
40
 
149
41
 
150
 
class TestSmartAddTree(TestCaseWithTransport):
151
 
    """Test smart adds with a specified branch."""
152
 
 
153
 
    def test_add_dot_from_root(self):
154
 
        """Test adding . from the root of the tree.""" 
155
 
        paths = ("original/", "original/file1", "original/file2")
156
 
        self.build_tree(paths)
157
 
        wt = self.make_branch_and_tree('.')
158
 
        smart_add_tree(wt, (u".",))
159
 
        for path in paths:
160
 
            self.assertNotEqual(wt.path2id(path), None)
161
 
 
162
 
    def test_add_dot_from_subdir(self):
163
 
        """Test adding . from a subdir of the tree.""" 
164
 
        paths = ("original/", "original/file1", "original/file2")
165
 
        self.build_tree(paths)
166
 
        wt = self.make_branch_and_tree('.')
167
 
        os.chdir("original")
168
 
        smart_add_tree(wt, (u".",))
169
 
        for path in paths:
170
 
            self.assertNotEqual(wt.path2id(path), None)
171
 
 
172
 
    def test_add_tree_from_above_tree(self):
173
 
        """Test adding a tree from above the tree.""" 
174
 
        paths = ("original/", "original/file1", "original/file2")
175
 
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
176
 
                        "branch/original/file2")
177
 
        self.build_tree(branch_paths)
178
 
        tree = self.make_branch_and_tree('branch')
179
 
        smart_add_tree(tree, ("branch",))
180
 
        for path in paths:
181
 
            self.assertNotEqual(tree.path2id(path), None)
182
 
 
183
 
    def test_add_above_tree_preserves_tree(self):
184
 
        """Test nested trees are not affect by an add above them."""
185
 
        paths = ("original/", "original/file1", "original/file2")
186
 
        child_paths = ("path")
187
 
        full_child_paths = ("original/child", "original/child/path")
188
 
        build_paths = ("original/", "original/file1", "original/file2", 
189
 
                       "original/child/", "original/child/path")
190
 
        self.build_tree(build_paths)
191
 
        tree = self.make_branch_and_tree('.')
192
 
        child_tree = self.make_branch_and_tree("original/child")
193
 
        smart_add_tree(tree, (u".",))
194
 
        for path in paths:
195
 
            self.assertNotEqual((path, tree.path2id(path)),
196
 
                                (path, None))
197
 
        for path in full_child_paths:
198
 
            self.assertEqual((path, tree.path2id(path)),
199
 
                             (path, None))
200
 
        for path in child_paths:
201
 
            self.assertEqual(child_tree.path2id(path), None)
202
 
 
203
 
    def test_add_paths(self):
204
 
        """Test smart-adding a list of paths."""
205
 
        paths = ("file1", "file2")
206
 
        self.build_tree(paths)
207
 
        wt = self.make_branch_and_tree('.')
208
 
        smart_add_tree(wt, paths)
209
 
        for path in paths:
210
 
            self.assertNotEqual(wt.path2id(path), None)
211
 
 
212
 
    def test_add_multiple_dirs(self):
213
 
        """Test smart adding multiple directories at once."""
214
 
        added_paths = ['file1', 'file2',
215
 
                       'dir1/', 'dir1/file3',
216
 
                       'dir1/subdir2/', 'dir1/subdir2/file4',
217
 
                       'dir2/', 'dir2/file5',
218
 
                      ]
219
 
        not_added = ['file6', 'dir3/', 'dir3/file7', 'dir3/file8']
220
 
        self.build_tree(added_paths)
221
 
        self.build_tree(not_added)
222
 
 
223
 
        wt = self.make_branch_and_tree('.')
224
 
        smart_add_tree(wt, ['file1', 'file2', 'dir1', 'dir2'])
225
 
 
226
 
        for path in added_paths:
227
 
            self.assertNotEqual(None, wt.path2id(path.rstrip('/')),
228
 
                    'Failed to add path: %s' % (path,))
229
 
        for path in not_added:
230
 
            self.assertEqual(None, wt.path2id(path.rstrip('/')),
231
 
                    'Accidentally added path: %s' % (path,))
232
 
 
233
 
    def test_custom_ids(self):
234
 
        sio = StringIO()
235
 
        action = AddCustomIDAction(to_file=sio, should_print=True)
236
 
        self.build_tree(['file1', 'dir1/', 'dir1/file2'])
237
 
 
238
 
        wt = self.make_branch_and_tree('.')
239
 
        smart_add_tree(wt, ['.'], action=action)
240
 
        # The order of adds is not strictly fixed:
241
 
        sio.seek(0)
242
 
        lines = sorted(sio.readlines())
243
 
        self.assertEqualDiff(['added dir1 with id directory-dir1\n',
244
 
                              'added dir1/file2 with id file-dir1%file2\n',
245
 
                              'added file1 with id file-file1\n',
246
 
                             ], lines)
247
 
        wt.lock_read()
248
 
        self.addCleanup(wt.unlock)
249
 
        self.assertEqual([('', wt.path2id('')),
250
 
                          ('dir1', 'directory-dir1'),
251
 
                          ('dir1/file2', 'file-dir1%file2'),
252
 
                          ('file1', 'file-file1'),
253
 
                         ], [(path, ie.file_id) for path, ie
254
 
                                in wt.inventory.iter_entries()])
255
 
 
256
 
 
257
42
class TestAddFrom(TestCaseWithTransport):
258
43
    """Tests for AddFromBaseAction"""
259
44
 
278
63
                action = AddFromBaseAction(base_tree, base_path,
279
64
                                           to_file=to_file,
280
65
                                           should_print=should_print)
281
 
                smart_add_tree(new_tree, file_list, action=action)
 
66
                new_tree.smart_add(file_list, action=action)
282
67
            finally:
283
68
                new_tree.unlock()
284
69
        finally:
359
144
        self.failIf(a_id in self.base_tree)
360
145
 
361
146
 
362
 
class TestAddNonNormalized(TestCaseWithTransport):
363
 
 
364
 
    def make(self):
365
 
        try:
366
 
            self.build_tree([u'a\u030a'])
367
 
        except UnicodeError:
368
 
            raise TestSkipped('Filesystem cannot create unicode filenames')
369
 
 
370
 
        self.wt = self.make_branch_and_tree('.')
371
 
 
372
 
    def test_accessible_explicit(self):
373
 
        self.make()
374
 
        orig = osutils.normalized_filename
375
 
        osutils.normalized_filename = osutils._accessible_normalized_filename
376
 
        try:
377
 
            smart_add_tree(self.wt, [u'a\u030a'])
378
 
            self.wt.lock_read()
379
 
            self.addCleanup(self.wt.unlock)
380
 
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
381
 
                    [(path, ie.kind) for path,ie in 
382
 
                        self.wt.inventory.iter_entries()])
383
 
        finally:
384
 
            osutils.normalized_filename = orig
385
 
 
386
 
    def test_accessible_implicit(self):
387
 
        self.make()
388
 
        orig = osutils.normalized_filename
389
 
        osutils.normalized_filename = osutils._accessible_normalized_filename
390
 
        try:
391
 
            smart_add_tree(self.wt, [])
392
 
            self.wt.lock_read()
393
 
            self.addCleanup(self.wt.unlock)
394
 
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
395
 
                    [(path, ie.kind) for path,ie in 
396
 
                        self.wt.inventory.iter_entries()])
397
 
        finally:
398
 
            osutils.normalized_filename = orig
399
 
 
400
 
    def test_inaccessible_explicit(self):
401
 
        self.make()
402
 
        orig = osutils.normalized_filename
403
 
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
404
 
        try:
405
 
            self.assertRaises(errors.InvalidNormalization,
406
 
                    smart_add_tree, self.wt, [u'a\u030a'])
407
 
        finally:
408
 
            osutils.normalized_filename = orig
409
 
 
410
 
    def test_inaccessible_implicit(self):
411
 
        self.make()
412
 
        orig = osutils.normalized_filename
413
 
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
414
 
        try:
415
 
            # TODO: jam 20060701 In the future, this should probably
416
 
            #       just ignore files that don't fit the normalization
417
 
            #       rules, rather than exploding
418
 
            self.assertRaises(errors.InvalidNormalization,
419
 
                    smart_add_tree, self.wt, [])
420
 
        finally:
421
 
            osutils.normalized_filename = orig
422
 
 
423
 
 
424
147
class TestAddActions(TestCase):
425
148
 
426
149
    def test_quiet(self):
430
153
        self.run_action("added path\n")
431
154
 
432
155
    def run_action(self, output):
433
 
        from bzrlib.add import AddAction, FastPath
 
156
        from bzrlib.add import AddAction
 
157
        from bzrlib.mutabletree import FastPath
434
158
        inv = Inventory()
435
159
        stdout = StringIO()
436
160
        action = AddAction(to_file=stdout, should_print=bool(output))