/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.assertNotEqual(wt.path2id('file'), None, "No id added for 'file'")
118
        wt.read_working_inventory()
119
        self.assertEqual(wt.path2id('file'), None)
120
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
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
        eq = self.assertEqual
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
125
        wt = self.make_branch_and_tree('.')
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
126
        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.
127
        eq(list(wt.unknowns()), ['inertiatic'])
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
128
        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.
129
        eq(list(wt.unknowns()), ['inertiatic'])
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
130
1185.56.2 by Michael Ellerman
Raise NoSuchFile when someone tries to add a non-existant file.
131
    def test_add_non_existant(self):
132
        """Test smart-adding a file that does not exist."""
133
        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.
134
        wt = self.make_branch_and_tree('.')
135
        self.assertRaises(NoSuchFile, smart_add_tree, wt, 'non-existant-file')
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
136
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
137
    def test_returns_and_ignores(self):
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
138
        """Correctly returns added/ignored files"""
139
        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.
140
        wt = self.make_branch_and_tree('.')
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
141
        # 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
142
        ignores._set_user_ignores(['*.py[co]'])
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
143
        self.build_tree(['inertiatic/', 'inertiatic/esp', 'inertiatic/CVS',
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
144
                        'inertiatic/foo.pyc'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
145
        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.
146
        self.assertSubset(('inertiatic', 'inertiatic/esp', 'inertiatic/CVS'),
147
                          added)
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
148
        self.assertSubset(('*.py[co]',), ignored)
149
        self.assertSubset(('inertiatic/foo.pyc',), ignored['*.py[co]'])
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
150
151
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
152
class AddCustomIDAction(AddAction):
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
153
154
    def __call__(self, inv, parent_ie, path, kind):
155
        # The first part just logs if appropriate
156
        # Now generate a custom id
2309.4.9 by John Arbash Meinel
WorkingTree.merged_modified() needs to switch back to utf8 file ids.
157
        file_id = osutils.safe_file_id(kind + '-'
158
                                       + path.raw_path.replace('/', '%'),
159
                                       warn=False)
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
160
        if self.should_print:
2309.4.9 by John Arbash Meinel
WorkingTree.merged_modified() needs to switch back to utf8 file ids.
161
            self._to_file.write('added %s with id %s\n'
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
162
                                % (path.raw_path, file_id))
163
        return file_id
164
165
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
166
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
167
    """Test smart adds with a specified branch."""
168
169
    def test_add_dot_from_root(self):
170
        """Test adding . from the root of the tree.""" 
171
        paths = ("original/", "original/file1", "original/file2")
172
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
173
        wt = self.make_branch_and_tree('.')
174
        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
175
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
176
            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
177
178
    def test_add_dot_from_subdir(self):
179
        """Test adding . from a subdir of the tree.""" 
180
        paths = ("original/", "original/file1", "original/file2")
181
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
182
        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
183
        os.chdir("original")
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
184
        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
185
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
186
            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
187
188
    def test_add_tree_from_above_tree(self):
189
        """Test adding a tree from above the tree.""" 
190
        paths = ("original/", "original/file1", "original/file2")
191
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
192
                        "branch/original/file2")
193
        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.
194
        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)
195
        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
196
        for path in paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
197
            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
198
199
    def test_add_above_tree_preserves_tree(self):
200
        """Test nested trees are not affect by an add above them."""
201
        paths = ("original/", "original/file1", "original/file2")
202
        child_paths = ("path")
203
        full_child_paths = ("original/child", "original/child/path")
204
        build_paths = ("original/", "original/file1", "original/file2", 
205
                       "original/child/", "original/child/path")
206
        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.
207
        tree = self.make_branch_and_tree('.')
208
        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)
209
        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
210
        for path in paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
211
            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
212
                                (path, None))
213
        for path in full_child_paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
214
            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
215
                             (path, None))
216
        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.
217
            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
218
219
    def test_add_paths(self):
220
        """Test smart-adding a list of paths."""
221
        paths = ("file1", "file2")
222
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
223
        wt = self.make_branch_and_tree('.')
224
        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
225
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
226
            self.assertNotEqual(wt.path2id(path), None)
227
1850.2.1 by John Arbash Meinel
Fix bug #52578, smart-add wasn't recursing all supplied directories.
228
    def test_add_multiple_dirs(self):
229
        """Test smart adding multiple directories at once."""
230
        added_paths = ['file1', 'file2',
231
                       'dir1/', 'dir1/file3',
232
                       'dir1/subdir2/', 'dir1/subdir2/file4',
233
                       'dir2/', 'dir2/file5',
234
                      ]
235
        not_added = ['file6', 'dir3/', 'dir3/file7', 'dir3/file8']
236
        self.build_tree(added_paths)
237
        self.build_tree(not_added)
238
239
        wt = self.make_branch_and_tree('.')
240
        smart_add_tree(wt, ['file1', 'file2', 'dir1', 'dir2'])
241
242
        for path in added_paths:
243
            self.assertNotEqual(None, wt.path2id(path.rstrip('/')),
244
                    'Failed to add path: %s' % (path,))
245
        for path in not_added:
246
            self.assertEqual(None, wt.path2id(path.rstrip('/')),
247
                    'Accidentally added path: %s' % (path,))
248
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
249
    def test_custom_ids(self):
250
        sio = StringIO()
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
251
        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.
252
        self.build_tree(['file1', 'dir1/', 'dir1/file2'])
253
254
        wt = self.make_branch_and_tree('.')
255
        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
256
        # The order of adds is not strictly fixed:
257
        sio.seek(0)
258
        lines = sorted(sio.readlines())
259
        self.assertEqualDiff(['added dir1 with id directory-dir1\n',
260
                              'added dir1/file2 with id file-dir1%file2\n',
261
                              'added file1 with id file-file1\n',
262
                             ], lines)
1911.3.1 by John Arbash Meinel
Updated smart_add so that the AddAction can return a custom id.
263
        self.assertEqual([('', wt.inventory.root.file_id),
264
                          ('dir1', 'directory-dir1'),
265
                          ('dir1/file2', 'file-dir1%file2'),
266
                          ('file1', 'file-file1'),
267
                         ], [(path, ie.file_id) for path, ie
268
                                in wt.inventory.iter_entries()])
269
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
270
1911.3.2 by John Arbash Meinel
Adding the AddFromBaseAction, which tries to reuse file ids from another tree
271
class TestAddFrom(TestCaseWithTransport):
272
    """Tests for AddFromBaseAction"""
273
274
    def make_base_tree(self):
275
        self.base_tree = self.make_branch_and_tree('base')
276
        self.build_tree(['base/a', 'base/b',
277
                         'base/dir/', 'base/dir/a',
278
                         'base/dir/subdir/',
279
                         'base/dir/subdir/b',
280
                        ])
281
        self.base_tree.add(['a', 'b', 'dir', 'dir/a',
282
                            'dir/subdir', 'dir/subdir/b'])
283
        self.base_tree.commit('creating initial tree.')
284
285
    def add_helper(self, base_tree, base_path, new_tree, file_list,
286
                   should_print=False):
287
        to_file = StringIO()
288
        base_tree.lock_read()
289
        try:
290
            new_tree.lock_write()
291
            try:
292
                action = AddFromBaseAction(base_tree, base_path,
293
                                           to_file=to_file,
294
                                           should_print=should_print)
295
                smart_add_tree(new_tree, file_list, action=action)
296
            finally:
297
                new_tree.unlock()
298
        finally:
299
            base_tree.unlock()
300
        return to_file.getvalue()
301
302
    def test_copy_all(self):
303
        self.make_base_tree()
304
        new_tree = self.make_branch_and_tree('new')
305
        files = ['a', 'b',
306
                 'dir/', 'dir/a',
307
                 'dir/subdir/',
308
                 'dir/subdir/b',
309
                ]
310
        self.build_tree(['new/' + fn for fn in files])
311
        self.add_helper(self.base_tree, '', new_tree, ['new'])
312
313
        for fn in files:
314
            base_file_id = self.base_tree.path2id(fn)
315
            new_file_id = new_tree.path2id(fn)
316
            self.assertEqual(base_file_id, new_file_id)
317
318
    def test_copy_from_dir(self):
319
        self.make_base_tree()
320
        new_tree = self.make_branch_and_tree('new')
321
322
        self.build_tree(['new/a', 'new/b', 'new/c',
323
                         'new/subdir/', 'new/subdir/b', 'new/subdir/d'])
1731.1.46 by Aaron Bentley
merge from bzr.dev
324
        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
325
        self.add_helper(self.base_tree, 'dir', new_tree, ['new'])
326
1731.1.46 by Aaron Bentley
merge from bzr.dev
327
        # We know 'a' and 'b' exist in the root, and they are being added
328
        # 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
329
        # use those ids
330
        self.assertEqual(self.base_tree.path2id('a'),
331
                         new_tree.path2id('a'))
332
        self.assertEqual(self.base_tree.path2id('b'),
333
                         new_tree.path2id('b'))
334
335
        # Because we specified 'dir/' as the base path, and we have
336
        # nothing named 'subdir' in the base tree, we should grab the
337
        # ids from there
338
        self.assertEqual(self.base_tree.path2id('dir/subdir'),
339
                         new_tree.path2id('subdir'))
340
        self.assertEqual(self.base_tree.path2id('dir/subdir/b'),
341
                         new_tree.path2id('subdir/b'))
342
343
        # These should get newly generated ids
344
        c_id = new_tree.path2id('c')
345
        self.assertNotEqual(None, c_id)
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)
369
        self.failIf(a_id in self.base_tree)
370
371
1830.3.6 by John Arbash Meinel
Test that smart_add_tree does the right thing in the presence of non-normalized filenames
372
class TestAddNonNormalized(TestCaseWithTransport):
373
374
    def make(self):
375
        try:
376
            self.build_tree([u'a\u030a'])
377
        except UnicodeError:
378
            raise TestSkipped('Filesystem cannot create unicode filenames')
379
380
        self.wt = self.make_branch_and_tree('.')
381
382
    def test_accessible_explicit(self):
383
        self.make()
384
        orig = osutils.normalized_filename
385
        osutils.normalized_filename = osutils._accessible_normalized_filename
386
        try:
387
            smart_add_tree(self.wt, [u'a\u030a'])
1907.1.3 by Aaron Bentley
Fixed unicode test cases
388
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
389
                    [(path, ie.kind) for path,ie in 
390
                        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
391
        finally:
392
            osutils.normalized_filename = orig
393
394
    def test_accessible_implicit(self):
395
        self.make()
396
        orig = osutils.normalized_filename
397
        osutils.normalized_filename = osutils._accessible_normalized_filename
398
        try:
399
            smart_add_tree(self.wt, [])
1907.1.3 by Aaron Bentley
Fixed unicode test cases
400
            self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
401
                    [(path, ie.kind) for path,ie in 
402
                        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
403
        finally:
404
            osutils.normalized_filename = orig
405
406
    def test_inaccessible_explicit(self):
407
        self.make()
408
        orig = osutils.normalized_filename
409
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
410
        try:
411
            self.assertRaises(errors.InvalidNormalization,
412
                    smart_add_tree, self.wt, [u'a\u030a'])
413
        finally:
414
            osutils.normalized_filename = orig
415
416
    def test_inaccessible_implicit(self):
417
        self.make()
418
        orig = osutils.normalized_filename
419
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
420
        try:
421
            # TODO: jam 20060701 In the future, this should probably
422
            #       just ignore files that don't fit the normalization
423
            #       rules, rather than exploding
424
            self.assertRaises(errors.InvalidNormalization,
425
                    smart_add_tree, self.wt, [])
426
        finally:
427
            osutils.normalized_filename = orig
428
429
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
430
class TestAddActions(TestCase):
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
431
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.
432
    def test_quiet(self):
433
        self.run_action("")
434
435
    def test__print(self):
436
        self.run_action("added path\n")
437
438
    def run_action(self, output):
1757.2.3 by Robert Collins
Get add tests passing.
439
        from bzrlib.add import AddAction, FastPath
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
440
        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
441
        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.
442
        action = AddAction(to_file=stdout, should_print=bool(output))
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
443
1757.2.3 by Robert Collins
Get add tests passing.
444
        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
445
        self.assertEqual(stdout.getvalue(), output)