/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/workingtree_implementations/test_remove.py

merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for interface conformance of 'WorkingTree.remove'"""
18
18
 
19
19
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
20
 
from bzrlib import errors, osutils
 
20
from bzrlib import errors, ignores, osutils
21
21
 
22
22
class TestRemove(TestCaseWithWorkingTree):
23
23
    """Tests WorkingTree.remove"""
24
24
 
25
25
    files = ['a', 'b/', 'b/c', 'd/']
26
26
    rfiles = ['b/c', 'b', 'a', 'd']
27
 
    a = ['a']
28
 
    b = ['b']
29
 
    b_c = ['b', 'b/c']
30
27
 
31
 
    def getTree(self):
 
28
    def get_tree(self, files):
32
29
        tree = self.make_branch_and_tree('.')
33
 
        self.build_tree(TestRemove.files)
34
 
        return tree
 
30
        self.build_tree(files)
 
31
        self.failUnlessExists(files)
 
32
        return tree
 
33
 
 
34
    def get_committed_tree(self, files, message="Committing"):
 
35
        tree = self.get_tree(files)
 
36
        tree.add(files)
 
37
        tree.commit(message)
 
38
        self.assertInWorkingTree(files)
 
39
        return tree
 
40
 
 
41
    def assertRemovedAndDeleted(self, files):
 
42
        self.assertNotInWorkingTree(files)
 
43
        self.failIfExists(files)
 
44
 
 
45
    def assertRemovedAndNotDeleted(self, files):
 
46
        self.assertNotInWorkingTree(files)
 
47
        self.failUnlessExists(files)
35
48
 
36
49
    def test_remove_keep(self):
37
 
        """Check that files are unversioned but not deleted."""
38
 
        tree = self.getTree()
 
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)
41
54
 
42
55
        tree.remove(TestRemove.files)
43
 
        self.assertNotInWorkingTree(TestRemove.files)
44
 
        self.failUnlessExists(TestRemove.files)
 
56
        self.assertRemovedAndNotDeleted(TestRemove.files)
 
57
 
 
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')
 
63
 
 
64
        tree.remove('subtree')
 
65
        self.assertRemovedAndNotDeleted('subtree')
45
66
 
46
67
    def test_remove_unchanged_files(self):
47
68
        """Check that unchanged files are removed and deleted."""
48
 
        tree = self.getTree()
49
 
        tree.add(TestRemove.files)
50
 
        tree.commit("files must not have changes")
51
 
        self.assertInWorkingTree(TestRemove.files)
52
 
 
 
69
        tree = self.get_committed_tree(TestRemove.files)
53
70
        tree.remove(TestRemove.files, keep_files=False)
54
 
 
55
 
        self.assertNotInWorkingTree(TestRemove.files)
56
 
        self.failIfExists(TestRemove.files)
 
71
        self.assertRemovedAndDeleted(TestRemove.files)
 
72
        tree._validate()
57
73
 
58
74
    def test_remove_added_files(self):
59
75
        """Removal of newly added files must fail."""
60
 
        tree = self.getTree()
 
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,
66
82
            '(?s)added:.*a.*b/.*b/c.*d/')
67
83
        self.assertInWorkingTree(TestRemove.files)
68
84
        self.failUnlessExists(TestRemove.files)
 
85
        tree._validate()
69
86
 
70
87
    def test_remove_changed_file(self):
71
88
        """Removal of a changed files must fail."""
72
 
        tree = self.getTree()
73
 
        tree.add(TestRemove.a)
74
 
        tree.commit("make sure a is versioned")
 
89
        tree = self.get_committed_tree(['a'])
75
90
        self.build_tree_contents([('a', "some other new content!")])
76
 
        self.assertInWorkingTree(TestRemove.a)
 
91
        self.assertInWorkingTree('a')
77
92
        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
78
 
            TestRemove.a, keep_files=False)
 
93
            'a', keep_files=False)
79
94
        self.assertContainsRe(err.changes_as_text, '(?s)modified:.*a')
80
 
        self.assertInWorkingTree(TestRemove.a)
81
 
        self.failUnlessExists(TestRemove.a)
 
95
        self.assertInWorkingTree('a')
 
96
        self.failUnlessExists('a')
 
97
        tree._validate()
82
98
 
83
99
    def test_remove_deleted_files(self):
84
100
        """Check that files are removed if they don't exist any more."""
85
 
        tree = self.getTree()
86
 
        tree.add(TestRemove.files)
87
 
        tree.commit("make sure files are versioned")
 
101
        tree = self.get_committed_tree(TestRemove.files)
88
102
        for f in TestRemove.rfiles:
89
103
            osutils.delete_any(f)
90
104
        self.assertInWorkingTree(TestRemove.files)
91
105
        self.failIfExists(TestRemove.files)
92
 
 
93
106
        tree.remove(TestRemove.files, keep_files=False)
94
 
 
95
 
        self.assertNotInWorkingTree(TestRemove.files)
96
 
        self.failIfExists(TestRemove.files)
 
107
        self.assertRemovedAndDeleted(TestRemove.files)
 
108
        tree._validate()
97
109
 
98
110
    def test_remove_renamed_files(self):
99
111
        """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")
 
112
        tree = self.get_committed_tree(TestRemove.files)
103
113
 
104
114
        for f in TestRemove.rfiles:
105
115
            tree.rename_one(f,f+'x')
108
118
        self.failUnlessExists(rfilesx)
109
119
 
110
120
        tree.remove(rfilesx, keep_files=False)
111
 
 
112
 
        self.assertNotInWorkingTree(rfilesx)
113
 
        self.failIfExists(rfilesx)
 
121
        self.assertRemovedAndDeleted(rfilesx)
 
122
        tree._validate()
114
123
 
115
124
    def test_remove_renamed_changed_files(self):
116
125
        """Check that files are not removed if they are renamed and changed."""
117
 
        tree = self.getTree()
118
 
        tree.add(TestRemove.files)
119
 
        tree.commit("make sure files are versioned")
 
126
        tree = self.get_committed_tree(TestRemove.files)
120
127
 
121
128
        for f in TestRemove.rfiles:
122
129
            tree.rename_one(f,f+'x')
132
139
            '(?s)modified:.*ax.*bx/cx')
133
140
        self.assertInWorkingTree(rfilesx)
134
141
        self.failUnlessExists(rfilesx)
 
142
        tree._validate()
135
143
 
136
144
    def test_force_remove_changed_files(self):
137
145
        """Check that changed files are removed and deleted when forced."""
138
 
        tree = self.getTree()
 
146
        tree = self.get_tree(TestRemove.files)
139
147
        tree.add(TestRemove.files)
140
148
        self.assertInWorkingTree(TestRemove.files)
141
149
 
142
150
        tree.remove(TestRemove.files, keep_files=False, force=True)
143
 
 
144
 
        self.assertNotInWorkingTree(TestRemove.files)
145
 
        self.failIfExists(TestRemove.files)
 
151
        self.assertRemovedAndDeleted(TestRemove.files)
 
152
        tree._validate()
146
153
 
147
154
    def test_remove_unknown_files(self):
148
155
        """Try to delete unknown files."""
149
 
        tree = self.getTree()
 
156
        tree = self.get_tree(TestRemove.files)
150
157
        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
151
158
            TestRemove.files, keep_files=False)
152
159
        self.assertContainsRe(err.changes_as_text,
153
160
            '(?s)unknown:.*d/.*b/c.*b/.*a.*')
 
161
        tree._validate()
154
162
 
155
163
    def test_remove_nonexisting_files(self):
156
164
        """Try to delete non-existing files."""
157
 
        tree = self.getTree()
 
165
        tree = self.get_tree(TestRemove.files)
158
166
        tree.remove([''], keep_files=False)
159
167
        tree.remove(['xyz', 'abc/def'], keep_files=False)
160
 
 
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)
171
 
 
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)
186
 
 
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)
 
168
        tree._validate()
 
169
 
 
170
    def test_remove_unchanged_directory(self):
 
171
        """Unchanged directories should be deleted."""
 
172
        files = ['b/', 'b/c', 'b/sub_directory/', 'b/sub_directory/with_file']
 
173
        tree = self.get_committed_tree(files)
 
174
        tree.remove('b', keep_files=False)
 
175
        self.assertRemovedAndDeleted('b')
 
176
        tree._validate()
 
177
 
 
178
    def test_remove_absent_directory(self):
 
179
        """Removing a absent directory succeeds without corruption (#150438)."""
 
180
        paths = ['a/', 'a/b']
 
181
        tree = self.get_committed_tree(paths)
 
182
        self.get_transport('.').delete_tree('a')
 
183
        tree.remove(['a'])
 
184
        self.assertRemovedAndDeleted('b')
 
185
        tree._validate()
 
186
 
 
187
    def test_remove_unknown_ignored_files(self):
 
188
        """Unknown ignored files should be deleted."""
 
189
        tree = self.get_committed_tree(['b/'])
 
190
        ignores.add_runtime_ignores(["*ignored*"])
 
191
 
 
192
        self.build_tree(['unknown_ignored_file'])
 
193
        self.assertNotEquals(None, tree.is_ignored('unknown_ignored_file'))
 
194
        tree.remove('unknown_ignored_file', keep_files=False)
 
195
        self.assertRemovedAndDeleted('unknown_ignored_file')
 
196
 
 
197
        self.build_tree(['b/unknown_ignored_file', 'b/unknown_ignored_dir/'])
 
198
        self.assertNotEquals(None, tree.is_ignored('b/unknown_ignored_file'))
 
199
        self.assertNotEquals(None, tree.is_ignored('b/unknown_ignored_dir'))
 
200
        tree.remove('b', keep_files=False)
 
201
        self.assertRemovedAndDeleted('b')
 
202
        tree._validate()
 
203
 
 
204
    def test_remove_changed_ignored_files(self):
 
205
        """Changed ignored files should not be deleted."""
 
206
        files = ['an_ignored_file']
 
207
        tree = self.get_tree(files)
 
208
        tree.add(files)
 
209
        ignores.add_runtime_ignores(["*ignored*"])
 
210
        self.assertInWorkingTree(files)
 
211
        self.assertNotEquals(None, tree.is_ignored(files[0]))
 
212
        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
 
213
            files, keep_files=False)
 
214
        self.assertContainsRe(err.changes_as_text,
 
215
            '(?s)added:.*' + files[0])
 
216
        self.assertInWorkingTree(files)
 
217
        tree._validate()
 
218
 
 
219
    def test_dont_remove_directory_with_unknowns(self):
 
220
        """Directories with unknowns should not be deleted."""
 
221
        directories = ['a/', 'b/', 'c/', 'c/c/']
 
222
        tree = self.get_committed_tree(directories)
 
223
 
 
224
        self.build_tree(['a/unknown_file'])
 
225
        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
 
226
            'a', keep_files=False)
 
227
        self.assertContainsRe(err.changes_as_text,
 
228
            '(?s)unknown:.*a/unknown_file')
 
229
 
 
230
        self.build_tree(['b/unknown_directory'])
 
231
        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
 
232
            'b', keep_files=False)
 
233
        self.assertContainsRe(err.changes_as_text,
 
234
            '(?s)unknown:.*b/unknown_directory')
 
235
 
 
236
        self.build_tree(['c/c/unknown_file'])
 
237
        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
 
238
            'c/c', keep_files=False)
 
239
        self.assertContainsRe(err.changes_as_text,
 
240
            '(?s)unknown:.*c/c/unknown_file')
 
241
 
 
242
        self.assertInWorkingTree(directories)
 
243
        self.failUnlessExists(directories)
 
244
        tree._validate()
 
245
 
 
246
    def test_force_remove_directory_with_unknowns(self):
 
247
        """Unchanged non-empty directories should be deleted when forced."""
 
248
        files = ['b/', 'b/c']
 
249
        tree = self.get_committed_tree(files)
 
250
 
 
251
        other_files = ['b/unknown_file', 'b/sub_directory/',
 
252
            'b/sub_directory/with_file', 'b/sub_directory/sub_directory/']
 
253
        self.build_tree(other_files)
 
254
 
 
255
        self.assertInWorkingTree(files)
 
256
        self.failUnlessExists(files)
 
257
 
 
258
        tree.remove('b', keep_files=False, force=True)
 
259
 
 
260
        self.assertRemovedAndDeleted(files)
 
261
        self.assertRemovedAndDeleted(other_files)
 
262
        tree._validate()
196
263
 
197
264
    def test_remove_directory_with_changed_file(self):
198
265
        """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")
 
266
        files = ['b/', 'b/c']
 
267
        tree = self.get_committed_tree(files)
202
268
        self.build_tree_contents([('b/c', "some other new content!")])
203
 
        self.assertInWorkingTree(TestRemove.b_c)
 
269
 
204
270
        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
205
 
            TestRemove.b, keep_files=False)
 
271
            'b', keep_files=False)
206
272
        self.assertContainsRe(err.changes_as_text, '(?s)modified:.*b/c')
207
 
        self.assertInWorkingTree(TestRemove.b_c)
208
 
        self.failUnlessExists(TestRemove.b_c)
209
 
 
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)
214
 
 
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'))
 
273
        self.assertInWorkingTree(files)
 
274
        self.failUnlessExists(files)
 
275
 
 
276
        # see if we can force it now..
 
277
        tree.remove('b', keep_files=False, force=True)
 
278
        self.assertRemovedAndDeleted(files)
 
279
        tree._validate()
 
280
 
 
281
    def test_remove_directory_with_renames(self):
 
282
        """Delete directory with renames in or out."""
 
283
 
 
284
        files = ['a/', 'a/file', 'a/directory/', 'b/']
 
285
        files_to_move = ['a/file', 'a/directory/']
 
286
 
 
287
        tree = self.get_committed_tree(files)
 
288
        # move stuff from a=>b
 
289
        tree.move(['a/file', 'a/directory'], to_dir='b')
 
290
 
 
291
        moved_files = ['b/file', 'b/directory/']
 
292
        self.assertRemovedAndDeleted(files_to_move)
 
293
        self.assertInWorkingTree(moved_files)
 
294
        self.failUnlessExists(moved_files)
 
295
 
 
296
        # check if it works with renames out
 
297
        tree.remove('a', keep_files=False)
 
298
        self.assertRemovedAndDeleted(['a/'])
 
299
 
 
300
        # check if it works with renames in
 
301
        tree.remove('b', keep_files=False)
 
302
        self.assertRemovedAndDeleted(['b/'])
 
303
        tree._validate()
221
304
 
222
305
    def test_non_cwd(self):
223
306
        tree = self.make_branch_and_tree('tree')
226
309
        tree.commit('add file')
227
310
        tree.remove('dir/', keep_files=False)
228
311
        self.failIfExists('tree/dir/file')
 
312
        self.assertNotInWorkingTree('tree/dir/file', 'tree')
 
313
        tree._validate()
 
314
 
 
315
    def test_remove_uncommitted_removed_file(self):
 
316
        # As per bug #152811
 
317
        tree = self.get_committed_tree(['a'])
 
318
        tree.remove('a', keep_files=False)
 
319
        tree.remove('a', keep_files=False)
 
320
        self.failIfExists('a')
 
321
        tree._validate()
 
322
 
 
323
    def test_remove_file_and_containing_dir(self):
 
324
        tree = self.get_committed_tree(['config/', 'config/file'])
 
325
        tree.remove('config/file', keep_files=False)
 
326
        tree.remove('config', keep_files=False)
 
327
        self.failIfExists('config/file')
 
328
        self.failIfExists('config')
 
329
        tree._validate()
 
330
 
 
331
    def test_remove_dir_before_bzr(self):
 
332
        # As per bug #272648. Note that a file must be present in the directory
 
333
        # or the bug doesn't manifest itself.
 
334
        tree = self.get_committed_tree(['.aaa/', '.aaa/file'])
 
335
        tree.remove('.aaa/', keep_files=False)
 
336
        self.failIfExists('.aaa/file')
 
337
        self.failIfExists('.aaa')
 
338
        tree._validate()