/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
from cStringIO import StringIO
1092.1.26 by Robert Collins
start writing star-topology test, realise we need smart-add change
18
import os
19
import unittest
20
1836.1.22 by John Arbash Meinel
[merge] bzr.dev 1861
21
from bzrlib import errors, ignores, osutils
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
22
from bzrlib.add import (
23
    AddAction,
24
    AddFromBaseAction,
25
    smart_add,
26
    smart_add_tree,
27
    )
1830.3.6 by John Arbash Meinel
Test that smart_add_tree does the right thing in the presence of non-normalized filenames
28
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
29
from bzrlib.errors import NoSuchFile
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
30
from bzrlib.inventory import InventoryFile, Inventory
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
31
from bzrlib.workingtree import WorkingTree
1092.1.26 by Robert Collins
start writing star-topology test, realise we need smart-add change
32
1830.3.4 by John Arbash Meinel
A couple no-op cleanups
33
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
34
class TestSmartAdd(TestCaseWithTransport):
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
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)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
41
        wt = self.make_branch_and_tree('.')
42
        smart_add_tree(wt, (u".",))
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
43
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
44
            self.assertNotEqual(wt.path2id(path), None)
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
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)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
51
        wt = self.make_branch_and_tree('.')
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
52
        os.chdir("original")
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
53
        smart_add_tree(wt, (u".",))
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
54
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
55
            self.assertNotEqual(wt.path2id(path), None)
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
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")
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
61
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
62
                        "branch/original/file2")
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
63
        self.build_tree(branch_paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
64
        wt = self.make_branch_and_tree('branch')
65
        smart_add_tree(wt, ("branch",))
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
66
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
67
            self.assertNotEqual(wt.path2id(path), None)
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
68
69
    def test_add_above_tree_preserves_tree(self):
70
        """Test nested trees are not affect by an add above them."""
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
71
        from bzrlib.add import smart_add
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
72
        paths = ("original/", "original/file1", "original/file2")
1143 by Martin Pool
- remove dead code and remove some small errors (pychecker)
73
        child_paths = ("path",)
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
74
        full_child_paths = ("original/child", "original/child/path")
75
        build_paths = ("original/", "original/file1", "original/file2", 
76
                       "original/child/", "original/child/path")
1143 by Martin Pool
- remove dead code and remove some small errors (pychecker)
77
        
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
78
        self.build_tree(build_paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
79
        wt = self.make_branch_and_tree('.')
80
        child_tree = self.make_branch_and_tree('original/child')
1757.2.9 by Robert Collins
Remove spurious u cast from test_smart_add.py
81
        smart_add_tree(wt, (".",))
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
82
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
83
            self.assertNotEqual((path, wt.path2id(path)),
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
84
                                (path, None))
85
        for path in full_child_paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
86
            self.assertEqual((path, wt.path2id(path)),
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
87
                             (path, None))
88
        for path in child_paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
89
            self.assertEqual(child_tree.path2id(path), None)
1092.1.28 by Robert Collins
test adding lists of paths
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)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
96
        wt = self.make_branch_and_tree('.')
97
        smart_add_tree(wt, paths)
1092.1.28 by Robert Collins
test adding lists of paths
98
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
99
            self.assertNotEqual(wt.path2id(path), None)
1757.2.5 by Robert Collins
De-dup the add list so we only walk subtrees once for add.
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)
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
111
1757.2.6 by Robert Collins
Steps towards a nicer smart add - unwind the conditional add logic - having parents not in the inventory was overly complicating the rest of the code.
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.assertEqual(wt.path2id('file'), None)
118
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
119
    def test_add_dry_run(self):
120
        """Test a dry run add, make sure nothing is added."""
121
        from bzrlib.commands import run_bzr
122
        eq = self.assertEqual
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
123
        wt = self.make_branch_and_tree('.')
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
124
        self.build_tree(['inertiatic/', 'inertiatic/esp'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
125
        eq(list(wt.unknowns()), ['inertiatic'])
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
126
        self.capture('add --dry-run .')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
127
        eq(list(wt.unknowns()), ['inertiatic'])
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
128
1185.56.2 by Michael Ellerman
Raise NoSuchFile when someone tries to add a non-existant file.
129
    def test_add_non_existant(self):
130
        """Test smart-adding a file that does not exist."""
131
        from bzrlib.add import smart_add
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
132
        wt = self.make_branch_and_tree('.')
133
        self.assertRaises(NoSuchFile, smart_add_tree, wt, 'non-existant-file')
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
134
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
135
    def test_returns_and_ignores(self):
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
136
        """Correctly returns added/ignored files"""
137
        from bzrlib.commands import run_bzr
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
138
        wt = self.make_branch_and_tree('.')
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
139
        # The default ignore list includes '*.py[co]', but not CVS
1987.1.2 by John Arbash Meinel
Remove the unneeded _set_user_ignores(['./.bazaar']) now that home has moved
140
        ignores._set_user_ignores(['*.py[co]'])
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
141
        self.build_tree(['inertiatic/', 'inertiatic/esp', 'inertiatic/CVS',
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
142
                        'inertiatic/foo.pyc'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
143
        added, ignored = smart_add_tree(wt, u'.')
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
144
        self.assertSubset(('inertiatic', 'inertiatic/esp', 'inertiatic/CVS'),
145
                          added)
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
146
        self.assertSubset(('*.py[co]',), ignored)
147
        self.assertSubset(('inertiatic/foo.pyc',), ignored['*.py[co]'])
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
148
149
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
150
class AddCustomIDAction(AddAction):
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
151
152
    def __call__(self, inv, parent_ie, path, kind):
153
        # The first part just logs if appropriate
154
        # Now generate a custom id
155
        file_id = kind + '-' + path.raw_path.replace('/', '%')
156
        if self.should_print:
157
            self._to_file.write('added %s with id %s\n' 
158
                                % (path.raw_path, file_id))
159
        return file_id
160
161
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
162
class TestSmartAddTree(TestCaseWithTransport):
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
163
    """Test smart adds with a specified branch."""
164
165
    def test_add_dot_from_root(self):
166
        """Test adding . from the root of the tree.""" 
167
        paths = ("original/", "original/file1", "original/file2")
168
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
169
        wt = self.make_branch_and_tree('.')
170
        smart_add_tree(wt, (u".",))
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
171
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
172
            self.assertNotEqual(wt.path2id(path), None)
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
173
174
    def test_add_dot_from_subdir(self):
175
        """Test adding . from a subdir of the tree.""" 
176
        paths = ("original/", "original/file1", "original/file2")
177
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
178
        wt = self.make_branch_and_tree('.')
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
179
        os.chdir("original")
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
180
        smart_add_tree(wt, (u".",))
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
181
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
182
            self.assertNotEqual(wt.path2id(path), None)
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
183
184
    def test_add_tree_from_above_tree(self):
185
        """Test adding a tree from above the tree.""" 
186
        paths = ("original/", "original/file1", "original/file2")
187
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
188
                        "branch/original/file2")
189
        self.build_tree(branch_paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
190
        tree = self.make_branch_and_tree('branch')
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
191
        smart_add_tree(tree, ("branch",))
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
192
        for path in paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
193
            self.assertNotEqual(tree.path2id(path), None)
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
194
195
    def test_add_above_tree_preserves_tree(self):
196
        """Test nested trees are not affect by an add above them."""
197
        paths = ("original/", "original/file1", "original/file2")
198
        child_paths = ("path")
199
        full_child_paths = ("original/child", "original/child/path")
200
        build_paths = ("original/", "original/file1", "original/file2", 
201
                       "original/child/", "original/child/path")
202
        self.build_tree(build_paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
203
        tree = self.make_branch_and_tree('.')
204
        child_tree = self.make_branch_and_tree("original/child")
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
205
        smart_add_tree(tree, (u".",))
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
206
        for path in paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
207
            self.assertNotEqual((path, tree.path2id(path)),
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
208
                                (path, None))
209
        for path in full_child_paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
210
            self.assertEqual((path, tree.path2id(path)),
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
211
                             (path, None))
212
        for path in child_paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
213
            self.assertEqual(child_tree.path2id(path), None)
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
214
215
    def test_add_paths(self):
216
        """Test smart-adding a list of paths."""
217
        paths = ("file1", "file2")
218
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
219
        wt = self.make_branch_and_tree('.')
220
        smart_add_tree(wt, paths)
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
221
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
222
            self.assertNotEqual(wt.path2id(path), None)
223
1850.2.1 by John Arbash Meinel
Fix bug #52578, smart-add wasn't recursing all supplied directories.
224
    def test_add_multiple_dirs(self):
225
        """Test smart adding multiple directories at once."""
226
        added_paths = ['file1', 'file2',
227
                       'dir1/', 'dir1/file3',
228
                       'dir1/subdir2/', 'dir1/subdir2/file4',
229
                       'dir2/', 'dir2/file5',
230
                      ]
231
        not_added = ['file6', 'dir3/', 'dir3/file7', 'dir3/file8']
232
        self.build_tree(added_paths)
233
        self.build_tree(not_added)
234
235
        wt = self.make_branch_and_tree('.')
236
        smart_add_tree(wt, ['file1', 'file2', 'dir1', 'dir2'])
237
238
        for path in added_paths:
239
            self.assertNotEqual(None, wt.path2id(path.rstrip('/')),
240
                    'Failed to add path: %s' % (path,))
241
        for path in not_added:
242
            self.assertEqual(None, wt.path2id(path.rstrip('/')),
243
                    'Accidentally added path: %s' % (path,))
244
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
245
    def test_custom_ids(self):
246
        sio = StringIO()
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
247
        action = AddCustomIDAction(to_file=sio, should_print=True)
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
248
        self.build_tree(['file1', 'dir1/', 'dir1/file2'])
249
250
        wt = self.make_branch_and_tree('.')
251
        smart_add_tree(wt, ['.'], action=action)
1911.3.5 by John Arbash Meinel
There is no strict ordering file addition, other than directories are added before child files
252
        # The order of adds is not strictly fixed:
253
        sio.seek(0)
254
        lines = sorted(sio.readlines())
255
        self.assertEqualDiff(['added dir1 with id directory-dir1\n',
256
                              'added dir1/file2 with id file-dir1%file2\n',
257
                              'added file1 with id file-file1\n',
258
                             ], lines)
2255.7.57 by Robert Collins
Fix test_smart_add tests for dirstate - mainly inventory outside locks issues.
259
        wt.lock_read()
260
        self.addCleanup(wt.unlock)
261
        self.assertEqual([('', wt.path2id('')),
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
262
                          ('dir1', 'directory-dir1'),
263
                          ('dir1/file2', 'file-dir1%file2'),
264
                          ('file1', 'file-file1'),
265
                         ], [(path, ie.file_id) for path, ie
266
                                in wt.inventory.iter_entries()])
267
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
268
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
269
class TestAddFrom(TestCaseWithTransport):
270
    """Tests for AddFromBaseAction"""
271
272
    def make_base_tree(self):
273
        self.base_tree = self.make_branch_and_tree('base')
274
        self.build_tree(['base/a', 'base/b',
275
                         'base/dir/', 'base/dir/a',
276
                         'base/dir/subdir/',
277
                         'base/dir/subdir/b',
278
                        ])
279
        self.base_tree.add(['a', 'b', 'dir', 'dir/a',
280
                            'dir/subdir', 'dir/subdir/b'])
281
        self.base_tree.commit('creating initial tree.')
282
283
    def add_helper(self, base_tree, base_path, new_tree, file_list,
284
                   should_print=False):
285
        to_file = StringIO()
286
        base_tree.lock_read()
287
        try:
288
            new_tree.lock_write()
289
            try:
290
                action = AddFromBaseAction(base_tree, base_path,
291
                                           to_file=to_file,
292
                                           should_print=should_print)
293
                smart_add_tree(new_tree, file_list, action=action)
294
            finally:
295
                new_tree.unlock()
296
        finally:
297
            base_tree.unlock()
298
        return to_file.getvalue()
299
300
    def test_copy_all(self):
301
        self.make_base_tree()
302
        new_tree = self.make_branch_and_tree('new')
303
        files = ['a', 'b',
304
                 'dir/', 'dir/a',
305
                 'dir/subdir/',
306
                 'dir/subdir/b',
307
                ]
308
        self.build_tree(['new/' + fn for fn in files])
309
        self.add_helper(self.base_tree, '', new_tree, ['new'])
310
311
        for fn in files:
312
            base_file_id = self.base_tree.path2id(fn)
313
            new_file_id = new_tree.path2id(fn)
314
            self.assertEqual(base_file_id, new_file_id)
315
316
    def test_copy_from_dir(self):
317
        self.make_base_tree()
318
        new_tree = self.make_branch_and_tree('new')
319
320
        self.build_tree(['new/a', 'new/b', 'new/c',
321
                         'new/subdir/', 'new/subdir/b', 'new/subdir/d'])
1731.1.46 by Aaron Bentley
merge from bzr.dev
322
        new_tree.set_root_id(self.base_tree.get_root_id())
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
323
        self.add_helper(self.base_tree, 'dir', new_tree, ['new'])
324
1731.1.46 by Aaron Bentley
merge from bzr.dev
325
        # We know 'a' and 'b' exist in the root, and they are being added
326
        # in a new 'root'. Since ROOT ids have been set as the same, we will
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
327
        # use those ids
328
        self.assertEqual(self.base_tree.path2id('a'),
329
                         new_tree.path2id('a'))
330
        self.assertEqual(self.base_tree.path2id('b'),
331
                         new_tree.path2id('b'))
332
333
        # Because we specified 'dir/' as the base path, and we have
334
        # nothing named 'subdir' in the base tree, we should grab the
335
        # ids from there
336
        self.assertEqual(self.base_tree.path2id('dir/subdir'),
337
                         new_tree.path2id('subdir'))
338
        self.assertEqual(self.base_tree.path2id('dir/subdir/b'),
339
                         new_tree.path2id('subdir/b'))
340
341
        # These should get newly generated ids
342
        c_id = new_tree.path2id('c')
343
        self.assertNotEqual(None, c_id)
2255.7.57 by Robert Collins
Fix test_smart_add tests for dirstate - mainly inventory outside locks issues.
344
        self.base_tree.lock_read()
345
        self.addCleanup(self.base_tree.unlock)
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
346
        self.failIf(c_id in self.base_tree)
347
348
        d_id = new_tree.path2id('subdir/d')
349
        self.assertNotEqual(None, d_id)
350
        self.failIf(d_id in self.base_tree)
351
352
    def test_copy_existing_dir(self):
353
        self.make_base_tree()
354
        new_tree = self.make_branch_and_tree('new')
355
        self.build_tree(['new/subby/', 'new/subby/a', 'new/subby/b'])
356
357
        subdir_file_id = self.base_tree.path2id('dir/subdir')
358
        new_tree.add(['subby'], [subdir_file_id])
359
        self.add_helper(self.base_tree, '', new_tree, ['new'])
360
        # Because 'subby' already points to subdir, we should add
361
        # 'b' with the same id
362
        self.assertEqual(self.base_tree.path2id('dir/subdir/b'),
363
                         new_tree.path2id('subby/b'))
364
365
        # 'subby/a' should be added with a new id because there is no
366
        # matching path or child of 'subby'.
367
        a_id = new_tree.path2id('subby/a')
368
        self.assertNotEqual(None, a_id)
2255.7.57 by Robert Collins
Fix test_smart_add tests for dirstate - mainly inventory outside locks issues.
369
        self.base_tree.lock_read()
370
        self.addCleanup(self.base_tree.unlock)
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
371
        self.failIf(a_id in self.base_tree)
372
373
1830.3.6 by John Arbash Meinel
Test that smart_add_tree does the right thing in the presence of non-normalized filenames
374
class TestAddNonNormalized(TestCaseWithTransport):
375
376
    def make(self):
377
        try:
378
            self.build_tree([u'a\u030a'])
379
        except UnicodeError:
380
            raise TestSkipped('Filesystem cannot create unicode filenames')
381
382
        self.wt = self.make_branch_and_tree('.')
383
384
    def test_accessible_explicit(self):
385
        self.make()
386
        orig = osutils.normalized_filename
387
        osutils.normalized_filename = osutils._accessible_normalized_filename
388
        try:
389
            smart_add_tree(self.wt, [u'a\u030a'])
2255.7.57 by Robert Collins
Fix test_smart_add tests for dirstate - mainly inventory outside locks issues.
390
            self.wt.lock_read()
391
            self.addCleanup(self.wt.unlock)
1907.1.3 by Aaron Bentley
Fixed unicode test cases
392
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
393
                    [(path, ie.kind) for path,ie in 
394
                        self.wt.inventory.iter_entries()])
1830.3.6 by John Arbash Meinel
Test that smart_add_tree does the right thing in the presence of non-normalized filenames
395
        finally:
396
            osutils.normalized_filename = orig
397
398
    def test_accessible_implicit(self):
399
        self.make()
400
        orig = osutils.normalized_filename
401
        osutils.normalized_filename = osutils._accessible_normalized_filename
402
        try:
403
            smart_add_tree(self.wt, [])
2255.7.57 by Robert Collins
Fix test_smart_add tests for dirstate - mainly inventory outside locks issues.
404
            self.wt.lock_read()
405
            self.addCleanup(self.wt.unlock)
1907.1.3 by Aaron Bentley
Fixed unicode test cases
406
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
407
                    [(path, ie.kind) for path,ie in 
408
                        self.wt.inventory.iter_entries()])
1830.3.6 by John Arbash Meinel
Test that smart_add_tree does the right thing in the presence of non-normalized filenames
409
        finally:
410
            osutils.normalized_filename = orig
411
412
    def test_inaccessible_explicit(self):
413
        self.make()
414
        orig = osutils.normalized_filename
415
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
416
        try:
417
            self.assertRaises(errors.InvalidNormalization,
418
                    smart_add_tree, self.wt, [u'a\u030a'])
419
        finally:
420
            osutils.normalized_filename = orig
421
422
    def test_inaccessible_implicit(self):
423
        self.make()
424
        orig = osutils.normalized_filename
425
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
426
        try:
427
            # TODO: jam 20060701 In the future, this should probably
428
            #       just ignore files that don't fit the normalization
429
            #       rules, rather than exploding
430
            self.assertRaises(errors.InvalidNormalization,
431
                    smart_add_tree, self.wt, [])
432
        finally:
433
            osutils.normalized_filename = orig
434
435
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
436
class TestAddActions(TestCase):
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
437
1757.2.6 by Robert Collins
Steps towards a nicer smart add - unwind the conditional add logic - having parents not in the inventory was overly complicating the rest of the code.
438
    def test_quiet(self):
439
        self.run_action("")
440
441
    def test__print(self):
442
        self.run_action("added path\n")
443
444
    def run_action(self, output):
1757.2.3 by Robert Collins
Get add tests passing.
445
        from bzrlib.add import AddAction, FastPath
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
446
        inv = Inventory()
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
447
        stdout = StringIO()
1757.2.6 by Robert Collins
Steps towards a nicer smart add - unwind the conditional add logic - having parents not in the inventory was overly complicating the rest of the code.
448
        action = AddAction(to_file=stdout, should_print=bool(output))
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
449
1757.2.3 by Robert Collins
Get add tests passing.
450
        self.apply_redirected(None, stdout, None, action, inv, None, FastPath('path'), 'file')
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
451
        self.assertEqual(stdout.getvalue(), output)