~bzr-pqm/bzr/bzr.dev

1092.1.26 by Robert Collins
start writing star-topology test, realise we need smart-add change
1
import os
2
import unittest
3
1836.1.22 by John Arbash Meinel
[merge] bzr.dev 1861
4
from bzrlib import errors, ignores, osutils
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
5
from bzrlib.add import smart_add, smart_add_tree
1830.3.6 by John Arbash Meinel
Test that smart_add_tree does the right thing in the presence of non-normalized filenames
6
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.
7
from bzrlib.errors import NoSuchFile
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
8
from bzrlib.inventory import InventoryFile, Inventory
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
9
from bzrlib.workingtree import WorkingTree
1092.1.26 by Robert Collins
start writing star-topology test, realise we need smart-add change
10
1830.3.4 by John Arbash Meinel
A couple no-op cleanups
11
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
12
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
13
14
    def test_add_dot_from_root(self):
15
        """Test adding . from the root of the tree.""" 
16
        from bzrlib.add import smart_add
17
        paths = ("original/", "original/file1", "original/file2")
18
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
19
        wt = self.make_branch_and_tree('.')
20
        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
21
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
22
            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
23
24
    def test_add_dot_from_subdir(self):
25
        """Test adding . from a subdir of the tree.""" 
26
        from bzrlib.add import smart_add
27
        paths = ("original/", "original/file1", "original/file2")
28
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
29
        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
30
        os.chdir("original")
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
31
        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
32
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
33
            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
34
35
    def test_add_tree_from_above_tree(self):
36
        """Test adding a tree from above the tree.""" 
37
        from bzrlib.add import smart_add
38
        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
39
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
40
                        "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
41
        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.
42
        wt = self.make_branch_and_tree('branch')
43
        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
44
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
45
            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
46
47
    def test_add_above_tree_preserves_tree(self):
48
        """Test nested trees are not affect by an add above them."""
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
49
        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
50
        paths = ("original/", "original/file1", "original/file2")
1143 by Martin Pool
- remove dead code and remove some small errors (pychecker)
51
        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
52
        full_child_paths = ("original/child", "original/child/path")
53
        build_paths = ("original/", "original/file1", "original/file2", 
54
                       "original/child/", "original/child/path")
1143 by Martin Pool
- remove dead code and remove some small errors (pychecker)
55
        
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
        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.
57
        wt = self.make_branch_and_tree('.')
58
        child_tree = self.make_branch_and_tree('original/child')
1757.2.9 by Robert Collins
Remove spurious u cast from test_smart_add.py
59
        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
60
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
61
            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
62
                                (path, None))
63
        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.
64
            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
65
                             (path, None))
66
        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.
67
            self.assertEqual(child_tree.path2id(path), None)
1092.1.28 by Robert Collins
test adding lists of paths
68
69
    def test_add_paths(self):
70
        """Test smart-adding a list of paths."""
71
        from bzrlib.add import smart_add
72
        paths = ("file1", "file2")
73
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
74
        wt = self.make_branch_and_tree('.')
75
        smart_add_tree(wt, paths)
1092.1.28 by Robert Collins
test adding lists of paths
76
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
77
            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.
78
    
79
    def test_add_ignored_nested_paths(self):
80
        """Test smart-adding a list of paths which includes ignored ones."""
81
        wt = self.make_branch_and_tree('.')
82
        tree_shape = ("adir/", "adir/CVS/", "adir/CVS/afile", "adir/CVS/afile2")
83
        add_paths = ("adir/CVS", "adir/CVS/afile", "adir")
84
        expected_paths = ("adir", "adir/CVS", "adir/CVS/afile", "adir/CVS/afile2")
85
        self.build_tree(tree_shape)
86
        smart_add_tree(wt, add_paths)
87
        for path in expected_paths:
88
            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
89
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.
90
    def test_save_false(self):
91
        """Test smart-adding a path with save set to false."""
92
        wt = self.make_branch_and_tree('.')
93
        self.build_tree(['file'])
94
        smart_add_tree(wt, ['file'], save=False)
95
        self.assertNotEqual(wt.path2id('file'), None, "No id added for 'file'")
96
        wt.read_working_inventory()
97
        self.assertEqual(wt.path2id('file'), None)
98
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
99
    def test_add_dry_run(self):
100
        """Test a dry run add, make sure nothing is added."""
101
        from bzrlib.commands import run_bzr
1836.1.16 by John Arbash Meinel
Cleanup some tests which don't expect .bazaar/ to show up. Some still fail.
102
        ignores.set_user_ignores(['./.bazaar'])
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
103
        eq = self.assertEqual
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
104
        wt = self.make_branch_and_tree('.')
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
105
        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.
106
        eq(list(wt.unknowns()), ['inertiatic'])
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
107
        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.
108
        eq(list(wt.unknowns()), ['inertiatic'])
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
109
1185.56.2 by Michael Ellerman
Raise NoSuchFile when someone tries to add a non-existant file.
110
    def test_add_non_existant(self):
111
        """Test smart-adding a file that does not exist."""
112
        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.
113
        wt = self.make_branch_and_tree('.')
114
        self.assertRaises(NoSuchFile, smart_add_tree, wt, 'non-existant-file')
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
115
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
116
    def test_returns_and_ignores(self):
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
117
        """Correctly returns added/ignored files"""
118
        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.
119
        wt = self.make_branch_and_tree('.')
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
120
        # The default ignore list includes '*.py[co]', but not CVS
1836.1.16 by John Arbash Meinel
Cleanup some tests which don't expect .bazaar/ to show up. Some still fail.
121
        ignores.set_user_ignores(['./.bazaar', '*.py[co]'])
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
122
        self.build_tree(['inertiatic/', 'inertiatic/esp', 'inertiatic/CVS',
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
123
                        'inertiatic/foo.pyc'])
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
124
        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.
125
        self.assertSubset(('inertiatic', 'inertiatic/esp', 'inertiatic/CVS'),
126
                          added)
1836.1.15 by John Arbash Meinel
Updated WorkingTree to use the new user-level ignores.
127
        self.assertSubset(('*.py[co]',), ignored)
128
        self.assertSubset(('inertiatic/foo.pyc',), ignored['*.py[co]'])
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
129
130
1765.1.1 by Robert Collins
Remove the default ignores list from bzr, lowering the minimum overhead in bzr add.
131
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
132
    """Test smart adds with a specified branch."""
133
134
    def test_add_dot_from_root(self):
135
        """Test adding . from the root of the tree.""" 
136
        paths = ("original/", "original/file1", "original/file2")
137
        self.build_tree(paths)
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('.')
139
        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
140
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
141
            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
142
143
    def test_add_dot_from_subdir(self):
144
        """Test adding . from a subdir of the tree.""" 
145
        paths = ("original/", "original/file1", "original/file2")
146
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
147
        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
148
        os.chdir("original")
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
149
        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
150
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
151
            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
152
153
    def test_add_tree_from_above_tree(self):
154
        """Test adding a tree from above the tree.""" 
155
        paths = ("original/", "original/file1", "original/file2")
156
        branch_paths = ("branch/", "branch/original/", "branch/original/file1",
157
                        "branch/original/file2")
158
        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.
159
        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)
160
        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
161
        for path in paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
162
            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
163
164
    def test_add_above_tree_preserves_tree(self):
165
        """Test nested trees are not affect by an add above them."""
166
        paths = ("original/", "original/file1", "original/file2")
167
        child_paths = ("path")
168
        full_child_paths = ("original/child", "original/child/path")
169
        build_paths = ("original/", "original/file1", "original/file2", 
170
                       "original/child/", "original/child/path")
171
        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.
172
        tree = self.make_branch_and_tree('.')
173
        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)
174
        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
175
        for path in paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
176
            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
177
                                (path, None))
178
        for path in full_child_paths:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
179
            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
180
                             (path, None))
181
        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.
182
            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
183
184
    def test_add_paths(self):
185
        """Test smart-adding a list of paths."""
186
        paths = ("file1", "file2")
187
        self.build_tree(paths)
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
188
        wt = self.make_branch_and_tree('.')
189
        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
190
        for path in paths:
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
191
            self.assertNotEqual(wt.path2id(path), None)
192
1850.2.1 by John Arbash Meinel
Fix bug #52578, smart-add wasn't recursing all supplied directories.
193
    def test_add_multiple_dirs(self):
194
        """Test smart adding multiple directories at once."""
195
        added_paths = ['file1', 'file2',
196
                       'dir1/', 'dir1/file3',
197
                       'dir1/subdir2/', 'dir1/subdir2/file4',
198
                       'dir2/', 'dir2/file5',
199
                      ]
200
        not_added = ['file6', 'dir3/', 'dir3/file7', 'dir3/file8']
201
        self.build_tree(added_paths)
202
        self.build_tree(not_added)
203
204
        wt = self.make_branch_and_tree('.')
205
        smart_add_tree(wt, ['file1', 'file2', 'dir1', 'dir2'])
206
207
        for path in added_paths:
208
            self.assertNotEqual(None, wt.path2id(path.rstrip('/')),
209
                    'Failed to add path: %s' % (path,))
210
        for path in not_added:
211
            self.assertEqual(None, wt.path2id(path.rstrip('/')),
212
                    'Accidentally added path: %s' % (path,))
213
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
214
1830.3.6 by John Arbash Meinel
Test that smart_add_tree does the right thing in the presence of non-normalized filenames
215
class TestAddNonNormalized(TestCaseWithTransport):
216
217
    def make(self):
218
        try:
219
            self.build_tree([u'a\u030a'])
220
        except UnicodeError:
221
            raise TestSkipped('Filesystem cannot create unicode filenames')
222
223
        self.wt = self.make_branch_and_tree('.')
224
225
    def test_accessible_explicit(self):
226
        self.make()
227
        orig = osutils.normalized_filename
228
        osutils.normalized_filename = osutils._accessible_normalized_filename
229
        try:
230
            smart_add_tree(self.wt, [u'a\u030a'])
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
231
            self.assertEqual([(u'\xe5', 'file')],
232
                    [(path, ie.kind) for path,ie in 
233
                        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
234
        finally:
235
            osutils.normalized_filename = orig
236
237
    def test_accessible_implicit(self):
238
        self.make()
239
        orig = osutils.normalized_filename
240
        osutils.normalized_filename = osutils._accessible_normalized_filename
241
        try:
242
            smart_add_tree(self.wt, [])
1830.3.17 by John Arbash Meinel
list_files() with wrong normalized_filename code raises exceptions. Fix this
243
            self.assertEqual([(u'\xe5', 'file')],
244
                    [(path, ie.kind) for path,ie in 
245
                        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
246
        finally:
247
            osutils.normalized_filename = orig
248
249
    def test_inaccessible_explicit(self):
250
        self.make()
251
        orig = osutils.normalized_filename
252
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
253
        try:
254
            self.assertRaises(errors.InvalidNormalization,
255
                    smart_add_tree, self.wt, [u'a\u030a'])
256
        finally:
257
            osutils.normalized_filename = orig
258
259
    def test_inaccessible_implicit(self):
260
        self.make()
261
        orig = osutils.normalized_filename
262
        osutils.normalized_filename = osutils._inaccessible_normalized_filename
263
        try:
264
            # TODO: jam 20060701 In the future, this should probably
265
            #       just ignore files that don't fit the normalization
266
            #       rules, rather than exploding
267
            self.assertRaises(errors.InvalidNormalization,
268
                    smart_add_tree, self.wt, [])
269
        finally:
270
            osutils.normalized_filename = orig
271
272
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
273
class TestAddActions(TestCase):
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
274
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.
275
    def test_quiet(self):
276
        self.run_action("")
277
278
    def test__print(self):
279
        self.run_action("added path\n")
280
281
    def run_action(self, output):
1757.2.3 by Robert Collins
Get add tests passing.
282
        from bzrlib.add import AddAction, FastPath
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
283
        from cStringIO import StringIO
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
284
        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
285
        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.
286
        action = AddAction(to_file=stdout, should_print=bool(output))
1185.53.2 by Michael Ellerman
Add tests for bzr add --dry-run
287
1757.2.3 by Robert Collins
Get add tests passing.
288
        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
289
        self.assertEqual(stdout.getvalue(), output)