~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart_add.py

  • Committer: John Arbash Meinel
  • Date: 2006-08-23 22:18:16 UTC
  • mto: This revision was merged to the branch mainline in revision 1955.
  • Revision ID: john@arbash-meinel.com-20060823221816-832d30e909734e97
Rename test_aftp_transport to test_ftp_tranpsport

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 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
18
20
 
19
 
from bzrlib import osutils
 
21
from bzrlib import errors, ignores, osutils
20
22
from bzrlib.add import (
21
23
    AddAction,
22
24
    AddFromBaseAction,
 
25
    smart_add,
 
26
    smart_add_tree,
23
27
    )
24
 
from bzrlib.tests import TestCase, TestCaseWithTransport
25
 
from bzrlib.inventory import Inventory
 
28
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
 
29
from bzrlib.errors import NoSuchFile
 
30
from bzrlib.inventory import InventoryFile, Inventory
 
31
from bzrlib.workingtree import WorkingTree
 
32
 
 
33
 
 
34
class TestSmartAdd(TestCaseWithTransport):
 
35
 
 
36
    def test_add_dot_from_root(self):
 
37
        """Test adding . from the root of the tree.""" 
 
38
        from bzrlib.add import smart_add
 
39
        paths = ("original/", "original/file1", "original/file2")
 
40
        self.build_tree(paths)
 
41
        wt = self.make_branch_and_tree('.')
 
42
        smart_add_tree(wt, (u".",))
 
43
        for path in paths:
 
44
            self.assertNotEqual(wt.path2id(path), None)
 
45
 
 
46
    def test_add_dot_from_subdir(self):
 
47
        """Test adding . from a subdir of the tree.""" 
 
48
        from bzrlib.add import smart_add
 
49
        paths = ("original/", "original/file1", "original/file2")
 
50
        self.build_tree(paths)
 
51
        wt = self.make_branch_and_tree('.')
 
52
        os.chdir("original")
 
53
        smart_add_tree(wt, (u".",))
 
54
        for path in paths:
 
55
            self.assertNotEqual(wt.path2id(path), None)
 
56
 
 
57
    def test_add_tree_from_above_tree(self):
 
58
        """Test adding a tree from above the tree.""" 
 
59
        from bzrlib.add import smart_add
 
60
        paths = ("original/", "original/file1", "original/file2")
 
61
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
 
62
                        "branch/original/file2")
 
63
        self.build_tree(branch_paths)
 
64
        wt = self.make_branch_and_tree('branch')
 
65
        smart_add_tree(wt, ("branch",))
 
66
        for path in paths:
 
67
            self.assertNotEqual(wt.path2id(path), None)
 
68
 
 
69
    def test_add_above_tree_preserves_tree(self):
 
70
        """Test nested trees are not affect by an add above them."""
 
71
        from bzrlib.add import smart_add
 
72
        paths = ("original/", "original/file1", "original/file2")
 
73
        child_paths = ("path",)
 
74
        full_child_paths = ("original/child", "original/child/path")
 
75
        build_paths = ("original/", "original/file1", "original/file2", 
 
76
                       "original/child/", "original/child/path")
 
77
        
 
78
        self.build_tree(build_paths)
 
79
        wt = self.make_branch_and_tree('.')
 
80
        child_tree = self.make_branch_and_tree('original/child')
 
81
        smart_add_tree(wt, (".",))
 
82
        for path in paths:
 
83
            self.assertNotEqual((path, wt.path2id(path)),
 
84
                                (path, None))
 
85
        for path in full_child_paths:
 
86
            self.assertEqual((path, wt.path2id(path)),
 
87
                             (path, None))
 
88
        for path in child_paths:
 
89
            self.assertEqual(child_tree.path2id(path), None)
 
90
 
 
91
    def test_add_paths(self):
 
92
        """Test smart-adding a list of paths."""
 
93
        from bzrlib.add import smart_add
 
94
        paths = ("file1", "file2")
 
95
        self.build_tree(paths)
 
96
        wt = self.make_branch_and_tree('.')
 
97
        smart_add_tree(wt, paths)
 
98
        for path in paths:
 
99
            self.assertNotEqual(wt.path2id(path), None)
 
100
    
 
101
    def test_add_ignored_nested_paths(self):
 
102
        """Test smart-adding a list of paths which includes ignored ones."""
 
103
        wt = self.make_branch_and_tree('.')
 
104
        tree_shape = ("adir/", "adir/CVS/", "adir/CVS/afile", "adir/CVS/afile2")
 
105
        add_paths = ("adir/CVS", "adir/CVS/afile", "adir")
 
106
        expected_paths = ("adir", "adir/CVS", "adir/CVS/afile", "adir/CVS/afile2")
 
107
        self.build_tree(tree_shape)
 
108
        smart_add_tree(wt, add_paths)
 
109
        for path in expected_paths:
 
110
            self.assertNotEqual(wt.path2id(path), None, "No id added for %s" % path)
 
111
 
 
112
    def test_save_false(self):
 
113
        """Test smart-adding a path with save set to false."""
 
114
        wt = self.make_branch_and_tree('.')
 
115
        self.build_tree(['file'])
 
116
        smart_add_tree(wt, ['file'], save=False)
 
117
        self.assertNotEqual(wt.path2id('file'), None, "No id added for 'file'")
 
118
        wt.read_working_inventory()
 
119
        self.assertEqual(wt.path2id('file'), None)
 
120
 
 
121
    def test_add_dry_run(self):
 
122
        """Test a dry run add, make sure nothing is added."""
 
123
        from bzrlib.commands import run_bzr
 
124
        ignores._set_user_ignores(['./.bazaar'])
 
125
        eq = self.assertEqual
 
126
        wt = self.make_branch_and_tree('.')
 
127
        self.build_tree(['inertiatic/', 'inertiatic/esp'])
 
128
        eq(list(wt.unknowns()), ['inertiatic'])
 
129
        self.capture('add --dry-run .')
 
130
        eq(list(wt.unknowns()), ['inertiatic'])
 
131
 
 
132
    def test_add_non_existant(self):
 
133
        """Test smart-adding a file that does not exist."""
 
134
        from bzrlib.add import smart_add
 
135
        wt = self.make_branch_and_tree('.')
 
136
        self.assertRaises(NoSuchFile, smart_add_tree, wt, 'non-existant-file')
 
137
 
 
138
    def test_returns_and_ignores(self):
 
139
        """Correctly returns added/ignored files"""
 
140
        from bzrlib.commands import run_bzr
 
141
        wt = self.make_branch_and_tree('.')
 
142
        # The default ignore list includes '*.py[co]', but not CVS
 
143
        ignores._set_user_ignores(['./.bazaar', '*.py[co]'])
 
144
        self.build_tree(['inertiatic/', 'inertiatic/esp', 'inertiatic/CVS',
 
145
                        'inertiatic/foo.pyc'])
 
146
        added, ignored = smart_add_tree(wt, u'.')
 
147
        self.assertSubset(('inertiatic', 'inertiatic/esp', 'inertiatic/CVS'),
 
148
                          added)
 
149
        self.assertSubset(('*.py[co]',), ignored)
 
150
        self.assertSubset(('inertiatic/foo.pyc',), ignored['*.py[co]'])
26
151
 
27
152
 
28
153
class AddCustomIDAction(AddAction):
30
155
    def __call__(self, inv, parent_ie, path, kind):
31
156
        # The first part just logs if appropriate
32
157
        # Now generate a custom id
33
 
        file_id = osutils.safe_file_id(kind + '-'
34
 
                                       + path.raw_path.replace('/', '%'),
35
 
                                       warn=False)
 
158
        file_id = kind + '-' + path.raw_path.replace('/', '%')
36
159
        if self.should_print:
37
 
            self._to_file.write('added %s with id %s\n'
 
160
            self._to_file.write('added %s with id %s\n' 
38
161
                                % (path.raw_path, file_id))
39
162
        return file_id
40
163
 
41
164
 
 
165
class TestSmartAddTree(TestCaseWithTransport):
 
166
    """Test smart adds with a specified branch."""
 
167
 
 
168
    def test_add_dot_from_root(self):
 
169
        """Test adding . from the root of the tree.""" 
 
170
        paths = ("original/", "original/file1", "original/file2")
 
171
        self.build_tree(paths)
 
172
        wt = self.make_branch_and_tree('.')
 
173
        smart_add_tree(wt, (u".",))
 
174
        for path in paths:
 
175
            self.assertNotEqual(wt.path2id(path), None)
 
176
 
 
177
    def test_add_dot_from_subdir(self):
 
178
        """Test adding . from a subdir of the tree.""" 
 
179
        paths = ("original/", "original/file1", "original/file2")
 
180
        self.build_tree(paths)
 
181
        wt = self.make_branch_and_tree('.')
 
182
        os.chdir("original")
 
183
        smart_add_tree(wt, (u".",))
 
184
        for path in paths:
 
185
            self.assertNotEqual(wt.path2id(path), None)
 
186
 
 
187
    def test_add_tree_from_above_tree(self):
 
188
        """Test adding a tree from above the tree.""" 
 
189
        paths = ("original/", "original/file1", "original/file2")
 
190
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
 
191
                        "branch/original/file2")
 
192
        self.build_tree(branch_paths)
 
193
        tree = self.make_branch_and_tree('branch')
 
194
        smart_add_tree(tree, ("branch",))
 
195
        for path in paths:
 
196
            self.assertNotEqual(tree.path2id(path), None)
 
197
 
 
198
    def test_add_above_tree_preserves_tree(self):
 
199
        """Test nested trees are not affect by an add above them."""
 
200
        paths = ("original/", "original/file1", "original/file2")
 
201
        child_paths = ("path")
 
202
        full_child_paths = ("original/child", "original/child/path")
 
203
        build_paths = ("original/", "original/file1", "original/file2", 
 
204
                       "original/child/", "original/child/path")
 
205
        self.build_tree(build_paths)
 
206
        tree = self.make_branch_and_tree('.')
 
207
        child_tree = self.make_branch_and_tree("original/child")
 
208
        smart_add_tree(tree, (u".",))
 
209
        for path in paths:
 
210
            self.assertNotEqual((path, tree.path2id(path)),
 
211
                                (path, None))
 
212
        for path in full_child_paths:
 
213
            self.assertEqual((path, tree.path2id(path)),
 
214
                             (path, None))
 
215
        for path in child_paths:
 
216
            self.assertEqual(child_tree.path2id(path), None)
 
217
 
 
218
    def test_add_paths(self):
 
219
        """Test smart-adding a list of paths."""
 
220
        paths = ("file1", "file2")
 
221
        self.build_tree(paths)
 
222
        wt = self.make_branch_and_tree('.')
 
223
        smart_add_tree(wt, paths)
 
224
        for path in paths:
 
225
            self.assertNotEqual(wt.path2id(path), None)
 
226
 
 
227
    def test_add_multiple_dirs(self):
 
228
        """Test smart adding multiple directories at once."""
 
229
        added_paths = ['file1', 'file2',
 
230
                       'dir1/', 'dir1/file3',
 
231
                       'dir1/subdir2/', 'dir1/subdir2/file4',
 
232
                       'dir2/', 'dir2/file5',
 
233
                      ]
 
234
        not_added = ['file6', 'dir3/', 'dir3/file7', 'dir3/file8']
 
235
        self.build_tree(added_paths)
 
236
        self.build_tree(not_added)
 
237
 
 
238
        wt = self.make_branch_and_tree('.')
 
239
        smart_add_tree(wt, ['file1', 'file2', 'dir1', 'dir2'])
 
240
 
 
241
        for path in added_paths:
 
242
            self.assertNotEqual(None, wt.path2id(path.rstrip('/')),
 
243
                    'Failed to add path: %s' % (path,))
 
244
        for path in not_added:
 
245
            self.assertEqual(None, wt.path2id(path.rstrip('/')),
 
246
                    'Accidentally added path: %s' % (path,))
 
247
 
 
248
    def test_custom_ids(self):
 
249
        sio = StringIO()
 
250
        action = AddCustomIDAction(to_file=sio, should_print=True)
 
251
        self.build_tree(['file1', 'dir1/', 'dir1/file2'])
 
252
 
 
253
        wt = self.make_branch_and_tree('.')
 
254
        smart_add_tree(wt, ['.'], action=action)
 
255
        # The order of adds is not strictly fixed:
 
256
        sio.seek(0)
 
257
        lines = sorted(sio.readlines())
 
258
        self.assertEqualDiff(['added dir1 with id directory-dir1\n',
 
259
                              'added dir1/file2 with id file-dir1%file2\n',
 
260
                              'added file1 with id file-file1\n',
 
261
                             ], lines)
 
262
        self.assertEqual([('', wt.inventory.root.file_id),
 
263
                          ('dir1', 'directory-dir1'),
 
264
                          ('dir1/file2', 'file-dir1%file2'),
 
265
                          ('file1', 'file-file1'),
 
266
                         ], [(path, ie.file_id) for path, ie
 
267
                                in wt.inventory.iter_entries()])
 
268
 
 
269
 
42
270
class TestAddFrom(TestCaseWithTransport):
43
271
    """Tests for AddFromBaseAction"""
44
272
 
63
291
                action = AddFromBaseAction(base_tree, base_path,
64
292
                                           to_file=to_file,
65
293
                                           should_print=should_print)
66
 
                new_tree.smart_add(file_list, action=action)
 
294
                smart_add_tree(new_tree, file_list, action=action)
67
295
            finally:
68
296
                new_tree.unlock()
69
297
        finally:
92
320
 
93
321
        self.build_tree(['new/a', 'new/b', 'new/c',
94
322
                         'new/subdir/', 'new/subdir/b', 'new/subdir/d'])
95
 
        new_tree.set_root_id(self.base_tree.get_root_id())
96
323
        self.add_helper(self.base_tree, 'dir', new_tree, ['new'])
97
324
 
98
 
        # We know 'a' and 'b' exist in the root, and they are being added
99
 
        # in a new 'root'. Since ROOT ids have been set as the same, we will
 
325
        # We 'a' and 'b' exist in the root, and they are being added
 
326
        # in a new 'root'. Since ROOT ids are not unique, we will
100
327
        # use those ids
 
328
        # TODO: This will probably change once trees have a unique root id
 
329
        # It is definitely arguable that 'a' should get the id of
 
330
        # 'dir/a' not of 'a'.
101
331
        self.assertEqual(self.base_tree.path2id('a'),
102
332
                         new_tree.path2id('a'))
103
333
        self.assertEqual(self.base_tree.path2id('b'),
114
344
        # These should get newly generated ids
115
345
        c_id = new_tree.path2id('c')
116
346
        self.assertNotEqual(None, c_id)
117
 
        self.base_tree.lock_read()
118
 
        self.addCleanup(self.base_tree.unlock)
119
347
        self.failIf(c_id in self.base_tree)
120
348
 
121
349
        d_id = new_tree.path2id('subdir/d')
139
367
        # matching path or child of 'subby'.
140
368
        a_id = new_tree.path2id('subby/a')
141
369
        self.assertNotEqual(None, a_id)
142
 
        self.base_tree.lock_read()
143
 
        self.addCleanup(self.base_tree.unlock)
144
370
        self.failIf(a_id in self.base_tree)
145
371
 
146
372
 
 
373
class TestAddNonNormalized(TestCaseWithTransport):
 
374
 
 
375
    def make(self):
 
376
        try:
 
377
            self.build_tree([u'a\u030a'])
 
378
        except UnicodeError:
 
379
            raise TestSkipped('Filesystem cannot create unicode filenames')
 
380
 
 
381
        self.wt = self.make_branch_and_tree('.')
 
382
 
 
383
    def test_accessible_explicit(self):
 
384
        self.make()
 
385
        orig = osutils.normalized_filename
 
386
        osutils.normalized_filename = osutils._accessible_normalized_filename
 
387
        try:
 
388
            smart_add_tree(self.wt, [u'a\u030a'])
 
389
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
 
390
                    [(path, ie.kind) for path,ie in 
 
391
                        self.wt.inventory.iter_entries()])
 
392
        finally:
 
393
            osutils.normalized_filename = orig
 
394
 
 
395
    def test_accessible_implicit(self):
 
396
        self.make()
 
397
        orig = osutils.normalized_filename
 
398
        osutils.normalized_filename = osutils._accessible_normalized_filename
 
399
        try:
 
400
            smart_add_tree(self.wt, [])
 
401
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
 
402
                    [(path, ie.kind) for path,ie in 
 
403
                        self.wt.inventory.iter_entries()])
 
404
        finally:
 
405
            osutils.normalized_filename = orig
 
406
 
 
407
    def test_inaccessible_explicit(self):
 
408
        self.make()
 
409
        orig = osutils.normalized_filename
 
410
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
 
411
        try:
 
412
            self.assertRaises(errors.InvalidNormalization,
 
413
                    smart_add_tree, self.wt, [u'a\u030a'])
 
414
        finally:
 
415
            osutils.normalized_filename = orig
 
416
 
 
417
    def test_inaccessible_implicit(self):
 
418
        self.make()
 
419
        orig = osutils.normalized_filename
 
420
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
 
421
        try:
 
422
            # TODO: jam 20060701 In the future, this should probably
 
423
            #       just ignore files that don't fit the normalization
 
424
            #       rules, rather than exploding
 
425
            self.assertRaises(errors.InvalidNormalization,
 
426
                    smart_add_tree, self.wt, [])
 
427
        finally:
 
428
            osutils.normalized_filename = orig
 
429
 
 
430
 
147
431
class TestAddActions(TestCase):
148
432
 
149
433
    def test_quiet(self):
153
437
        self.run_action("added path\n")
154
438
 
155
439
    def run_action(self, output):
156
 
        from bzrlib.add import AddAction
157
 
        from bzrlib.mutabletree import _FastPath
 
440
        from bzrlib.add import AddAction, FastPath
158
441
        inv = Inventory()
159
442
        stdout = StringIO()
160
443
        action = AddAction(to_file=stdout, should_print=bool(output))
161
444
 
162
 
        self.apply_redirected(None, stdout, None, action, inv, None,
163
 
            _FastPath('path'), 'file')
 
445
        self.apply_redirected(None, stdout, None, action, inv, None, FastPath('path'), 'file')
164
446
        self.assertEqual(stdout.getvalue(), output)