17
17
"""Tests for interface conformance of 'WorkingTree.remove'"""
19
19
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
20
from bzrlib import errors, osutils
20
from bzrlib import errors, ignores, osutils
22
22
class TestRemove(TestCaseWithWorkingTree):
23
23
"""Tests WorkingTree.remove"""
25
25
files = ['a', 'b/', 'b/c', 'd/']
26
26
rfiles = ['b/c', 'b', 'a', 'd']
28
def get_tree(self, files):
32
29
tree = self.make_branch_and_tree('.')
33
self.build_tree(TestRemove.files)
30
self.build_tree(files)
31
self.failUnlessExists(files)
34
def get_committed_tree(self, files, message="Committing"):
35
tree = self.get_tree(files)
38
self.assertInWorkingTree(files)
41
def assertRemovedAndDeleted(self, files):
42
self.assertNotInWorkingTree(files)
43
self.failIfExists(files)
45
def assertRemovedAndNotDeleted(self, files):
46
self.assertNotInWorkingTree(files)
47
self.failUnlessExists(files)
36
49
def test_remove_keep(self):
37
"""Check that files are unversioned but not deleted."""
50
"""Check that files and directories are unversioned but not deleted."""
51
tree = self.get_tree(TestRemove.files)
39
52
tree.add(TestRemove.files)
40
53
self.assertInWorkingTree(TestRemove.files)
42
55
tree.remove(TestRemove.files)
43
self.assertNotInWorkingTree(TestRemove.files)
44
self.failUnlessExists(TestRemove.files)
56
self.assertRemovedAndNotDeleted(TestRemove.files)
58
def test_remove_keep_subtree(self):
59
"""Check that a directory is unversioned but not deleted."""
60
tree = self.make_branch_and_tree('.')
61
subtree = self.make_branch_and_tree('subtree')
62
tree.add('subtree', 'subtree-id')
64
tree.remove('subtree')
65
self.assertRemovedAndNotDeleted('subtree')
46
67
def test_remove_unchanged_files(self):
47
68
"""Check that unchanged files are removed and deleted."""
49
tree.add(TestRemove.files)
50
tree.commit("files must not have changes")
51
self.assertInWorkingTree(TestRemove.files)
69
tree = self.get_committed_tree(TestRemove.files)
53
71
tree.remove(TestRemove.files, keep_files=False)
55
self.assertNotInWorkingTree(TestRemove.files)
56
self.failIfExists(TestRemove.files)
72
self.assertRemovedAndDeleted(TestRemove.files)
58
74
def test_remove_added_files(self):
59
75
"""Removal of newly added files must fail."""
76
tree = self.get_tree(TestRemove.files)
61
77
tree.add(TestRemove.files)
62
78
self.assertInWorkingTree(TestRemove.files)
63
79
err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
70
86
def test_remove_changed_file(self):
71
87
"""Removal of a changed files must fail."""
73
tree.add(TestRemove.a)
74
tree.commit("make sure a is versioned")
88
tree = self.get_committed_tree('a')
75
89
self.build_tree_contents([('a', "some other new content!")])
76
self.assertInWorkingTree(TestRemove.a)
90
self.assertInWorkingTree('a')
77
91
err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
78
TestRemove.a, keep_files=False)
92
'a', keep_files=False)
79
93
self.assertContainsRe(err.changes_as_text, '(?s)modified:.*a')
80
self.assertInWorkingTree(TestRemove.a)
81
self.failUnlessExists(TestRemove.a)
94
self.assertInWorkingTree('a')
95
self.failUnlessExists('a')
83
97
def test_remove_deleted_files(self):
84
98
"""Check that files are removed if they don't exist any more."""
86
tree.add(TestRemove.files)
87
tree.commit("make sure files are versioned")
99
tree = self.get_committed_tree(TestRemove.files)
88
100
for f in TestRemove.rfiles:
89
101
osutils.delete_any(f)
90
102
self.assertInWorkingTree(TestRemove.files)
91
103
self.failIfExists(TestRemove.files)
93
105
tree.remove(TestRemove.files, keep_files=False)
95
self.assertNotInWorkingTree(TestRemove.files)
96
self.failIfExists(TestRemove.files)
106
self.assertRemovedAndDeleted(TestRemove.files)
98
108
def test_remove_renamed_files(self):
99
109
"""Check that files are removed even if they are renamed."""
100
tree = self.getTree()
101
tree.add(TestRemove.files)
102
tree.commit("make sure files are versioned")
110
tree = self.get_committed_tree(TestRemove.files)
104
112
for f in TestRemove.rfiles:
105
113
tree.rename_one(f,f+'x')
155
157
def test_remove_nonexisting_files(self):
156
158
"""Try to delete non-existing files."""
157
tree = self.getTree()
159
tree = self.get_tree(TestRemove.files)
158
160
tree.remove([''], keep_files=False)
159
161
tree.remove(['xyz', 'abc/def'], keep_files=False)
161
def test_remove_nonempty_directory(self):
162
"""Unchanged non-empty directories should be deleted."""
163
tree = self.getTree()
164
tree.add(TestRemove.files)
165
tree.commit("make sure b is versioned")
166
self.assertInWorkingTree(TestRemove.files)
167
self.failUnlessExists(TestRemove.files)
168
tree.remove(TestRemove.b, keep_files=False)
169
self.assertNotInWorkingTree(TestRemove.b)
170
self.failIfExists(TestRemove.b)
172
def test_remove_nonempty_directory_with_unknowns(self):
173
"""Unchanged non-empty directories should be deleted."""
174
tree = self.getTree()
175
tree.add(TestRemove.files)
176
tree.commit("make sure b is versioned")
177
self.assertInWorkingTree(TestRemove.files)
178
self.failUnlessExists(TestRemove.files)
179
self.build_tree(['b/my_unknown_file'])
180
err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
181
TestRemove.b, keep_files=False)
182
self.assertContainsRe(err.changes_as_text,
183
'(?s)unknown:.*b/my_unknown_file')
184
self.assertInWorkingTree(TestRemove.b)
185
self.failUnlessExists(TestRemove.b)
187
def test_force_remove_nonempty_directory(self):
188
tree = self.getTree()
189
tree.add(TestRemove.files)
190
tree.commit("make sure b is versioned")
191
self.assertInWorkingTree(TestRemove.files)
192
self.failUnlessExists(TestRemove.files)
193
tree.remove(TestRemove.b, keep_files=False, force=True)
194
self.assertNotInWorkingTree(TestRemove.b_c)
195
self.failIfExists(TestRemove.b_c)
163
def test_remove_unchanged_directory(self):
164
"""Unchanged directories should be deleted."""
165
files = ['b/', 'b/c', 'b/sub_directory/', 'b/sub_directory/with_file']
166
tree = self.get_committed_tree(files)
167
tree.remove('b', keep_files=False)
168
self.assertRemovedAndDeleted('b')
170
def test_remove_unknown_ignored_files(self):
171
"""Unknown ignored files should be deleted."""
172
tree = self.get_committed_tree(['b/'])
173
ignores.add_runtime_ignores(["*ignored*"])
175
self.build_tree(['unknown_ignored_file'])
176
self.assertNotEquals(None, tree.is_ignored('unknown_ignored_file'))
177
tree.remove('unknown_ignored_file', keep_files=False)
178
self.assertRemovedAndDeleted('unknown_ignored_file')
180
self.build_tree(['b/unknown_ignored_file', 'b/unknown_ignored_dir/'])
181
self.assertNotEquals(None, tree.is_ignored('b/unknown_ignored_file'))
182
self.assertNotEquals(None, tree.is_ignored('b/unknown_ignored_dir'))
183
tree.remove('b', keep_files=False)
184
self.assertRemovedAndDeleted('b')
186
def test_dont_remove_directory_with_unknowns(self):
187
"""Directories with unknowns should not be deleted."""
188
directories = ['a/', 'b/', 'c/', 'c/c/']
189
tree = self.get_committed_tree(directories)
191
self.build_tree(['a/unknown_file'])
192
err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
193
'a', keep_files=False)
194
self.assertContainsRe(err.changes_as_text,
195
'(?s)unknown:.*a/unknown_file')
197
self.build_tree(['b/unknown_directory'])
198
err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
199
'b', keep_files=False)
200
self.assertContainsRe(err.changes_as_text,
201
'(?s)unknown:.*b/unknown_directory')
203
self.build_tree(['c/c/unknown_file'])
204
err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
205
'c/c', keep_files=False)
206
self.assertContainsRe(err.changes_as_text,
207
'(?s)unknown:.*c/c/unknown_file')
209
self.assertInWorkingTree(directories)
210
self.failUnlessExists(directories)
212
def test_force_remove_directory_with_unknowns(self):
213
"""Unchanged non-empty directories should be deleted when forced."""
214
files = ['b/', 'b/c']
215
tree = self.get_committed_tree(files)
217
other_files = ['b/unknown_file', 'b/sub_directory/',
218
'b/sub_directory/with_file', 'b/sub_directory/sub_directory/']
219
self.build_tree(other_files)
221
self.assertInWorkingTree(files)
222
self.failUnlessExists(files)
224
tree.remove('b', keep_files=False, force=True)
226
self.assertRemovedAndDeleted(files)
227
self.assertRemovedAndDeleted(other_files)
197
229
def test_remove_directory_with_changed_file(self):
198
230
"""Refuse to delete directories with changed files."""
199
tree = self.getTree()
200
tree.add(TestRemove.b_c)
201
tree.commit("make sure b and c are versioned")
231
files = ['b/', 'b/c']
232
tree = self.get_committed_tree(files)
202
233
self.build_tree_contents([('b/c', "some other new content!")])
203
self.assertInWorkingTree(TestRemove.b_c)
204
235
err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
205
TestRemove.b, keep_files=False)
236
'b', keep_files=False)
206
237
self.assertContainsRe(err.changes_as_text, '(?s)modified:.*b/c')
207
self.assertInWorkingTree(TestRemove.b_c)
208
self.failUnlessExists(TestRemove.b_c)
210
#see if we can force it now..
211
tree.remove(TestRemove.b, keep_files=False, force=True)
212
self.assertNotInWorkingTree(TestRemove.b_c)
213
self.failIfExists(TestRemove.b_c)
215
def test_remove_subtree(self):
216
tree = self.make_branch_and_tree('.')
217
subtree = self.make_branch_and_tree('subtree')
218
tree.add('subtree', 'subtree-id')
219
tree.remove('subtree')
220
self.assertIs(None, tree.path2id('subtree'))
238
self.assertInWorkingTree(files)
239
self.failUnlessExists(files)
241
# see if we can force it now..
242
tree.remove('b', keep_files=False, force=True)
243
self.assertRemovedAndDeleted(files)
245
def test_remove_directory_with_renames(self):
246
"""Delete directory with renames in or out."""
248
files = ['a/', 'a/file', 'a/directory/', 'b/']
249
files_to_move = ['a/file', 'a/directory/']
251
tree = self.get_committed_tree(files)
252
# move stuff from a=>b
253
tree.move(['a/file', 'a/directory'], to_dir='b')
255
moved_files = ['b/file', 'b/directory/']
256
self.assertRemovedAndDeleted(files_to_move)
257
self.assertInWorkingTree(moved_files)
258
self.failUnlessExists(moved_files)
260
# check if it works with renames out
261
tree.remove('a', keep_files=False)
262
self.assertRemovedAndDeleted(['a/'])
264
# check if it works with renames in
265
tree.remove('b', keep_files=False)
266
self.assertRemovedAndDeleted(['b/'])
222
268
def test_non_cwd(self):
223
269
tree = self.make_branch_and_tree('tree')