~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart_add.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-10-24 12:49:17 UTC
  • mfrom: (2935.1.1 ianc-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20071024124917-xb75eckyxx6vkrlg
Makefile fixes - hooks.html generation & allow python to be overridden (Ian Clatworthy)

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,
26
 
    smart_add_tree,
27
23
    )
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]'])
 
24
from bzrlib.tests import TestCase, TestCaseWithTransport
 
25
from bzrlib.inventory import Inventory
151
26
 
152
27
 
153
28
class AddCustomIDAction(AddAction):
155
30
    def __call__(self, inv, parent_ie, path, kind):
156
31
        # The first part just logs if appropriate
157
32
        # Now generate a custom id
158
 
        file_id = kind + '-' + path.raw_path.replace('/', '%')
 
33
        file_id = osutils.safe_file_id(kind + '-'
 
34
                                       + path.raw_path.replace('/', '%'),
 
35
                                       warn=False)
159
36
        if self.should_print:
160
 
            self._to_file.write('added %s with id %s\n' 
 
37
            self._to_file.write('added %s with id %s\n'
161
38
                                % (path.raw_path, file_id))
162
39
        return file_id
163
40
 
164
41
 
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
 
 
270
42
class TestAddFrom(TestCaseWithTransport):
271
43
    """Tests for AddFromBaseAction"""
272
44
 
291
63
                action = AddFromBaseAction(base_tree, base_path,
292
64
                                           to_file=to_file,
293
65
                                           should_print=should_print)
294
 
                smart_add_tree(new_tree, file_list, action=action)
 
66
                new_tree.smart_add(file_list, action=action)
295
67
            finally:
296
68
                new_tree.unlock()
297
69
        finally:
320
92
 
321
93
        self.build_tree(['new/a', 'new/b', 'new/c',
322
94
                         'new/subdir/', 'new/subdir/b', 'new/subdir/d'])
 
95
        new_tree.set_root_id(self.base_tree.get_root_id())
323
96
        self.add_helper(self.base_tree, 'dir', new_tree, ['new'])
324
97
 
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
 
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
327
100
        # 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'.
331
101
        self.assertEqual(self.base_tree.path2id('a'),
332
102
                         new_tree.path2id('a'))
333
103
        self.assertEqual(self.base_tree.path2id('b'),
344
114
        # These should get newly generated ids
345
115
        c_id = new_tree.path2id('c')
346
116
        self.assertNotEqual(None, c_id)
 
117
        self.base_tree.lock_read()
 
118
        self.addCleanup(self.base_tree.unlock)
347
119
        self.failIf(c_id in self.base_tree)
348
120
 
349
121
        d_id = new_tree.path2id('subdir/d')
367
139
        # matching path or child of 'subby'.
368
140
        a_id = new_tree.path2id('subby/a')
369
141
        self.assertNotEqual(None, a_id)
 
142
        self.base_tree.lock_read()
 
143
        self.addCleanup(self.base_tree.unlock)
370
144
        self.failIf(a_id in self.base_tree)
371
145
 
372
146
 
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
 
 
431
147
class TestAddActions(TestCase):
432
148
 
433
149
    def test_quiet(self):
437
153
        self.run_action("added path\n")
438
154
 
439
155
    def run_action(self, output):
440
 
        from bzrlib.add import AddAction, FastPath
 
156
        from bzrlib.add import AddAction
 
157
        from bzrlib.mutabletree import _FastPath
441
158
        inv = Inventory()
442
159
        stdout = StringIO()
443
160
        action = AddAction(to_file=stdout, should_print=bool(output))
444
161
 
445
 
        self.apply_redirected(None, stdout, None, action, inv, None, FastPath('path'), 'file')
 
162
        self.apply_redirected(None, stdout, None, action, inv, None,
 
163
            _FastPath('path'), 'file')
446
164
        self.assertEqual(stdout.getvalue(), output)