15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
from cStringIO import StringIO
19
from bzrlib import osutils
21
from bzrlib import errors, ignores, osutils
20
22
from bzrlib.add import (
24
from bzrlib.tests import TestCase, TestCaseWithTransport
25
from bzrlib.inventory import Inventory
28
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
29
from bzrlib.errors import NoSuchFile
30
from bzrlib.inventory import InventoryFile, Inventory
31
from bzrlib.workingtree import WorkingTree
34
class TestSmartAdd(TestCaseWithTransport):
36
def test_add_dot_from_root(self):
37
"""Test adding . from the root of the tree."""
38
from bzrlib.add import smart_add
39
paths = ("original/", "original/file1", "original/file2")
40
self.build_tree(paths)
41
wt = self.make_branch_and_tree('.')
42
smart_add_tree(wt, (u".",))
44
self.assertNotEqual(wt.path2id(path), None)
46
def test_add_dot_from_subdir(self):
47
"""Test adding . from a subdir of the tree."""
48
from bzrlib.add import smart_add
49
paths = ("original/", "original/file1", "original/file2")
50
self.build_tree(paths)
51
wt = self.make_branch_and_tree('.')
53
smart_add_tree(wt, (u".",))
55
self.assertNotEqual(wt.path2id(path), None)
57
def test_add_tree_from_above_tree(self):
58
"""Test adding a tree from above the tree."""
59
from bzrlib.add import smart_add
60
paths = ("original/", "original/file1", "original/file2")
61
branch_paths = ("branch/", "branch/original/", "branch/original/file1",
62
"branch/original/file2")
63
self.build_tree(branch_paths)
64
wt = self.make_branch_and_tree('branch')
65
smart_add_tree(wt, ("branch",))
67
self.assertNotEqual(wt.path2id(path), None)
69
def test_add_above_tree_preserves_tree(self):
70
"""Test nested trees are not affect by an add above them."""
71
from bzrlib.add import smart_add
72
paths = ("original/", "original/file1", "original/file2")
73
child_paths = ("path",)
74
full_child_paths = ("original/child", "original/child/path")
75
build_paths = ("original/", "original/file1", "original/file2",
76
"original/child/", "original/child/path")
78
self.build_tree(build_paths)
79
wt = self.make_branch_and_tree('.')
80
child_tree = self.make_branch_and_tree('original/child')
81
smart_add_tree(wt, (".",))
83
self.assertNotEqual((path, wt.path2id(path)),
85
for path in full_child_paths:
86
self.assertEqual((path, wt.path2id(path)),
88
for path in child_paths:
89
self.assertEqual(child_tree.path2id(path), None)
91
def test_add_paths(self):
92
"""Test smart-adding a list of paths."""
93
from bzrlib.add import smart_add
94
paths = ("file1", "file2")
95
self.build_tree(paths)
96
wt = self.make_branch_and_tree('.')
97
smart_add_tree(wt, paths)
99
self.assertNotEqual(wt.path2id(path), None)
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)
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)
121
def test_add_dry_run(self):
122
"""Test a dry run add, make sure nothing is added."""
123
from bzrlib.commands import run_bzr
124
ignores._set_user_ignores(['./.bazaar'])
125
eq = self.assertEqual
126
wt = self.make_branch_and_tree('.')
127
self.build_tree(['inertiatic/', 'inertiatic/esp'])
128
eq(list(wt.unknowns()), ['inertiatic'])
129
self.capture('add --dry-run .')
130
eq(list(wt.unknowns()), ['inertiatic'])
132
def test_add_non_existant(self):
133
"""Test smart-adding a file that does not exist."""
134
from bzrlib.add import smart_add
135
wt = self.make_branch_and_tree('.')
136
self.assertRaises(NoSuchFile, smart_add_tree, wt, 'non-existant-file')
138
def test_returns_and_ignores(self):
139
"""Correctly returns added/ignored files"""
140
from bzrlib.commands import run_bzr
141
wt = self.make_branch_and_tree('.')
142
# The default ignore list includes '*.py[co]', but not CVS
143
ignores._set_user_ignores(['./.bazaar', '*.py[co]'])
144
self.build_tree(['inertiatic/', 'inertiatic/esp', 'inertiatic/CVS',
145
'inertiatic/foo.pyc'])
146
added, ignored = smart_add_tree(wt, u'.')
147
self.assertSubset(('inertiatic', 'inertiatic/esp', 'inertiatic/CVS'),
149
self.assertSubset(('*.py[co]',), ignored)
150
self.assertSubset(('inertiatic/foo.pyc',), ignored['*.py[co]'])
28
153
class AddCustomIDAction(AddAction):
30
155
def __call__(self, inv, parent_ie, path, kind):
31
156
# The first part just logs if appropriate
32
157
# Now generate a custom id
33
file_id = osutils.safe_file_id(kind + '-'
34
+ path.raw_path.replace('/', '%'),
158
file_id = kind + '-' + path.raw_path.replace('/', '%')
36
159
if self.should_print:
37
self._to_file.write('added %s with id %s\n'
160
self._to_file.write('added %s with id %s\n'
38
161
% (path.raw_path, file_id))
165
class TestSmartAddTree(TestCaseWithTransport):
166
"""Test smart adds with a specified branch."""
168
def test_add_dot_from_root(self):
169
"""Test adding . from the root of the tree."""
170
paths = ("original/", "original/file1", "original/file2")
171
self.build_tree(paths)
172
wt = self.make_branch_and_tree('.')
173
smart_add_tree(wt, (u".",))
175
self.assertNotEqual(wt.path2id(path), None)
177
def test_add_dot_from_subdir(self):
178
"""Test adding . from a subdir of the tree."""
179
paths = ("original/", "original/file1", "original/file2")
180
self.build_tree(paths)
181
wt = self.make_branch_and_tree('.')
183
smart_add_tree(wt, (u".",))
185
self.assertNotEqual(wt.path2id(path), None)
187
def test_add_tree_from_above_tree(self):
188
"""Test adding a tree from above the tree."""
189
paths = ("original/", "original/file1", "original/file2")
190
branch_paths = ("branch/", "branch/original/", "branch/original/file1",
191
"branch/original/file2")
192
self.build_tree(branch_paths)
193
tree = self.make_branch_and_tree('branch')
194
smart_add_tree(tree, ("branch",))
196
self.assertNotEqual(tree.path2id(path), None)
198
def test_add_above_tree_preserves_tree(self):
199
"""Test nested trees are not affect by an add above them."""
200
paths = ("original/", "original/file1", "original/file2")
201
child_paths = ("path")
202
full_child_paths = ("original/child", "original/child/path")
203
build_paths = ("original/", "original/file1", "original/file2",
204
"original/child/", "original/child/path")
205
self.build_tree(build_paths)
206
tree = self.make_branch_and_tree('.')
207
child_tree = self.make_branch_and_tree("original/child")
208
smart_add_tree(tree, (u".",))
210
self.assertNotEqual((path, tree.path2id(path)),
212
for path in full_child_paths:
213
self.assertEqual((path, tree.path2id(path)),
215
for path in child_paths:
216
self.assertEqual(child_tree.path2id(path), None)
218
def test_add_paths(self):
219
"""Test smart-adding a list of paths."""
220
paths = ("file1", "file2")
221
self.build_tree(paths)
222
wt = self.make_branch_and_tree('.')
223
smart_add_tree(wt, paths)
225
self.assertNotEqual(wt.path2id(path), None)
227
def test_add_multiple_dirs(self):
228
"""Test smart adding multiple directories at once."""
229
added_paths = ['file1', 'file2',
230
'dir1/', 'dir1/file3',
231
'dir1/subdir2/', 'dir1/subdir2/file4',
232
'dir2/', 'dir2/file5',
234
not_added = ['file6', 'dir3/', 'dir3/file7', 'dir3/file8']
235
self.build_tree(added_paths)
236
self.build_tree(not_added)
238
wt = self.make_branch_and_tree('.')
239
smart_add_tree(wt, ['file1', 'file2', 'dir1', 'dir2'])
241
for path in added_paths:
242
self.assertNotEqual(None, wt.path2id(path.rstrip('/')),
243
'Failed to add path: %s' % (path,))
244
for path in not_added:
245
self.assertEqual(None, wt.path2id(path.rstrip('/')),
246
'Accidentally added path: %s' % (path,))
248
def test_custom_ids(self):
250
action = AddCustomIDAction(to_file=sio, should_print=True)
251
self.build_tree(['file1', 'dir1/', 'dir1/file2'])
253
wt = self.make_branch_and_tree('.')
254
smart_add_tree(wt, ['.'], action=action)
255
# The order of adds is not strictly fixed:
257
lines = sorted(sio.readlines())
258
self.assertEqualDiff(['added dir1 with id directory-dir1\n',
259
'added dir1/file2 with id file-dir1%file2\n',
260
'added file1 with id file-file1\n',
262
self.assertEqual([('', wt.inventory.root.file_id),
263
('dir1', 'directory-dir1'),
264
('dir1/file2', 'file-dir1%file2'),
265
('file1', 'file-file1'),
266
], [(path, ie.file_id) for path, ie
267
in wt.inventory.iter_entries()])
42
270
class TestAddFrom(TestCaseWithTransport):
43
271
"""Tests for AddFromBaseAction"""
139
367
# matching path or child of 'subby'.
140
368
a_id = new_tree.path2id('subby/a')
141
369
self.assertNotEqual(None, a_id)
142
self.base_tree.lock_read()
143
self.addCleanup(self.base_tree.unlock)
144
370
self.failIf(a_id in self.base_tree)
373
class TestAddNonNormalized(TestCaseWithTransport):
377
self.build_tree([u'a\u030a'])
379
raise TestSkipped('Filesystem cannot create unicode filenames')
381
self.wt = self.make_branch_and_tree('.')
383
def test_accessible_explicit(self):
385
orig = osutils.normalized_filename
386
osutils.normalized_filename = osutils._accessible_normalized_filename
388
smart_add_tree(self.wt, [u'a\u030a'])
389
self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
390
[(path, ie.kind) for path,ie in
391
self.wt.inventory.iter_entries()])
393
osutils.normalized_filename = orig
395
def test_accessible_implicit(self):
397
orig = osutils.normalized_filename
398
osutils.normalized_filename = osutils._accessible_normalized_filename
400
smart_add_tree(self.wt, [])
401
self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
402
[(path, ie.kind) for path,ie in
403
self.wt.inventory.iter_entries()])
405
osutils.normalized_filename = orig
407
def test_inaccessible_explicit(self):
409
orig = osutils.normalized_filename
410
osutils.normalized_filename = osutils._inaccessible_normalized_filename
412
self.assertRaises(errors.InvalidNormalization,
413
smart_add_tree, self.wt, [u'a\u030a'])
415
osutils.normalized_filename = orig
417
def test_inaccessible_implicit(self):
419
orig = osutils.normalized_filename
420
osutils.normalized_filename = osutils._inaccessible_normalized_filename
422
# TODO: jam 20060701 In the future, this should probably
423
# just ignore files that don't fit the normalization
424
# rules, rather than exploding
425
self.assertRaises(errors.InvalidNormalization,
426
smart_add_tree, self.wt, [])
428
osutils.normalized_filename = orig
147
431
class TestAddActions(TestCase):
149
433
def test_quiet(self):