1
# Copyright (C) 2007 Canonical Ltd
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.
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.
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
17
"""Tests for interface conformance of 'WorkingTree.rename_one'"""
26
from bzrlib.workingtree_4 import WorkingTreeFormat4
27
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
30
class TestRenameOne(TestCaseWithWorkingTree):
32
def get_tree_layout(self, tree):
33
"""Get the (path, file_id) pairs for the current tree."""
36
return [(path, ie.file_id) for path, ie
37
in tree.iter_entries_by_dir()]
41
def assertTreeLayout(self, expected, tree):
42
"""Check that the tree has the correct layout."""
43
actual = self.get_tree_layout(tree)
44
self.assertEqual(expected, actual)
46
def test_rename_one_target_not_dir(self):
47
tree = self.make_branch_and_tree('.')
48
self.build_tree(['a'])
50
tree.commit('initial', rev_id='rev-1')
52
self.assertRaises(errors.BzrMoveFailedError,
53
tree.rename_one, 'a', 'not-a-dir/b')
55
def test_rename_one_non_existent(self):
56
tree = self.make_branch_and_tree('.')
57
self.build_tree(['a/'])
59
tree.commit('initial', rev_id='rev-1')
60
self.assertRaises(errors.BzrMoveFailedError,
61
tree.rename_one, 'not-a-file', 'a/failure')
62
self.assertRaises(errors.BzrMoveFailedError,
63
tree.rename_one, 'not-a-file', 'also_not')
65
def test_rename_one_target_not_versioned(self):
66
tree = self.make_branch_and_tree('.')
67
self.build_tree(['a/', 'b'])
69
tree.commit('initial', rev_id='rev-1')
70
self.assertRaises(errors.BzrMoveFailedError,
71
tree.rename_one, 'b', 'a/b')
73
def test_rename_one_unversioned(self):
74
tree = self.make_branch_and_tree('.')
75
self.build_tree(['a/', 'b'])
77
tree.commit('initial', rev_id='rev-1')
78
self.assertRaises(errors.BzrMoveFailedError,
79
tree.rename_one, 'b', 'a/b')
81
def test_rename_one_samedir(self):
82
tree = self.make_branch_and_tree('.')
83
self.build_tree(['a', 'b/'])
84
tree.add(['a', 'b'], ['a-id', 'b-id'])
85
tree.commit('initial', rev_id='rev-1')
86
root_id = tree.get_root_id()
88
a_contents = tree.get_file_text('a-id')
89
tree.rename_one('a', 'foo')
90
self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('foo', 'a-id')],
92
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
94
self.failIfExists('a')
95
self.assertFileEqual(a_contents, 'foo')
97
def test_rename_one_not_localdir(self):
98
tree = self.make_branch_and_tree('tree')
99
self.build_tree(['tree/a', 'tree/b/'])
100
tree.add(['a', 'b'], ['a-id', 'b-id'])
101
tree.commit('initial', rev_id='rev-1')
102
root_id = tree.get_root_id()
104
a_contents = tree.get_file_text('a-id')
105
tree.rename_one('a', 'b/foo')
106
self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/foo', 'a-id')],
108
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
110
self.failIfExists('tree/a')
111
self.assertFileEqual(a_contents, 'tree/b/foo')
113
def test_rename_one_subdir(self):
114
tree = self.make_branch_and_tree('.')
115
self.build_tree(['a', 'b/', 'b/c'])
116
tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
117
tree.commit('initial', rev_id='rev-1')
118
root_id = tree.get_root_id()
119
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
120
('b/c', 'c-id')], tree)
121
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
122
('b/c', 'c-id')], tree.basis_tree())
123
a_contents = tree.get_file_text('a-id')
124
tree.rename_one('a', 'b/d')
125
self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/c', 'c-id'),
126
('b/d', 'a-id')], tree)
127
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
128
('b/c', 'c-id')], tree.basis_tree())
129
self.failIfExists('a')
130
self.assertFileEqual(a_contents, 'b/d')
132
def test_rename_one_parent_dir(self):
133
tree = self.make_branch_and_tree('.')
134
self.build_tree(['a', 'b/', 'b/c'])
135
tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
136
tree.commit('initial', rev_id='rev-1')
137
root_id = tree.get_root_id()
138
c_contents = tree.get_file_text('c-id')
139
tree.rename_one('b/c', 'd')
140
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
141
('d', 'c-id')], tree)
142
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
143
('b/c', 'c-id')], tree.basis_tree())
144
self.failIfExists('b/c')
145
self.assertFileEqual(c_contents, 'd')
147
def test_rename_one_fail_consistent(self):
148
tree = self.make_branch_and_tree('.')
149
self.build_tree(['a', 'b/', 'b/a', 'c'])
150
tree.add(['a', 'b', 'c'], ['a-id', 'b-id', 'c-id'])
151
tree.commit('initial', rev_id='rev-1')
152
root_id = tree.get_root_id()
153
# Target already exists
154
self.assertRaises(errors.RenameFailedFilesExist,
155
tree.rename_one, 'a', 'b/a')
156
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
157
('c', 'c-id')], tree)
158
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
159
('c', 'c-id')], tree.basis_tree())
161
def test_rename_one_onto_existing(self):
162
tree = self.make_branch_and_tree('.')
163
self.build_tree(['a', 'b'])
164
tree.add(['a', 'b'], ['a-id', 'b-id'])
165
tree.commit('initial', rev_id='rev-1')
167
self.assertRaises(errors.BzrMoveFailedError,
168
tree.rename_one, 'a', 'b')
170
def test_rename_one_onto_self(self):
171
tree = self.make_branch_and_tree('.')
172
self.build_tree(['b/', 'b/a'])
173
tree.add(['b', 'b/a'], ['b-id', 'a-id'])
174
tree.commit('initial', rev_id='rev-1')
176
self.assertRaises(errors.BzrMoveFailedError,
177
tree.rename_one, 'b/a', 'b/a')
179
def test_rename_one_onto_self_root(self):
180
tree = self.make_branch_and_tree('.')
181
self.build_tree(['a'])
182
tree.add(['a'], ['a-id'])
183
tree.commit('initial', rev_id='rev-1')
185
self.assertRaises(errors.BzrMoveFailedError,
186
tree.rename_one, 'a', 'a')
188
def test_rename_one_after(self):
189
tree = self.make_branch_and_tree('.')
190
self.build_tree(['a', 'b/'])
191
tree.add(['a', 'b'], ['a-id', 'b-id'])
192
tree.commit('initial', rev_id='rev-1')
193
root_id = tree.get_root_id()
194
os.rename('a', 'b/foo')
196
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
198
# We don't need after=True as long as source is missing and target
200
tree.rename_one('a', 'b/foo')
201
self.assertTreeLayout([('', root_id), ('b', 'b-id'),
202
('b/foo', 'a-id')], tree)
203
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
206
def test_rename_one_after_with_after(self):
207
tree = self.make_branch_and_tree('.')
208
self.build_tree(['a', 'b/'])
209
tree.add(['a', 'b'], ['a-id', 'b-id'])
210
tree.commit('initial', rev_id='rev-1')
211
root_id = tree.get_root_id()
212
os.rename('a', 'b/foo')
214
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
216
# Passing after=True should work as well
217
tree.rename_one('a', 'b/foo', after=True)
218
self.assertTreeLayout([('', root_id), ('b', 'b-id'),
219
('b/foo', 'a-id')], tree)
220
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
223
def test_rename_one_after_no_target(self):
224
tree = self.make_branch_and_tree('.')
225
self.build_tree(['a', 'b/'])
226
tree.add(['a', 'b'], ['a-id', 'b-id'])
227
tree.commit('initial', rev_id='rev-1')
228
root_id = tree.get_root_id()
230
# Passing after when the file hasn't been rename_one raises an exception
231
self.assertRaises(errors.BzrMoveFailedError,
232
tree.rename_one, 'a', 'b/foo', after=True)
233
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
235
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
238
def test_rename_one_after_source_and_dest(self):
239
tree = self.make_branch_and_tree('.')
240
self.build_tree(['a', 'b/', 'b/foo'])
241
tree.add(['a', 'b'], ['a-id', 'b-id'])
242
tree.commit('initial', rev_id='rev-1')
243
root_id = tree.get_root_id()
245
# TODO: jam 20070225 I would usually use 'rb', but assertFileEqual
247
a_file = open('a', 'r')
249
a_text = a_file.read()
252
foo_file = open('b/foo', 'r')
254
foo_text = foo_file.read()
258
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
260
self.assertRaises(errors.RenameFailedFilesExist,
261
tree.rename_one, 'a', 'b/foo', after=False)
262
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
264
self.assertFileEqual(a_text, 'a')
265
self.assertFileEqual(foo_text, 'b/foo')
266
# But you can pass after=True
267
tree.rename_one('a', 'b/foo', after=True)
268
self.assertTreeLayout([('', root_id), ('b', 'b-id'),
269
('b/foo', 'a-id')], tree)
270
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
272
# But it shouldn't actually move anything
273
self.assertFileEqual(a_text, 'a')
274
self.assertFileEqual(foo_text, 'b/foo')
276
def test_rename_one_directory(self):
277
tree = self.make_branch_and_tree('.')
278
self.build_tree(['a/', 'a/b', 'a/c/', 'a/c/d', 'e/'])
279
tree.add(['a', 'a/b', 'a/c', 'a/c/d', 'e'],
280
['a-id', 'b-id', 'c-id', 'd-id', 'e-id'])
281
tree.commit('initial', rev_id='rev-1')
282
root_id = tree.get_root_id()
284
tree.rename_one('a', 'e/f')
285
self.assertTreeLayout([('', root_id), ('e', 'e-id'), ('e/f', 'a-id'),
286
('e/f/b', 'b-id'), ('e/f/c', 'c-id'),
287
('e/f/c/d', 'd-id')], tree)
288
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('e', 'e-id'),
289
('a/b', 'b-id'), ('a/c', 'c-id'),
290
('a/c/d', 'd-id')], tree.basis_tree())
292
def test_rename_one_moved(self):
293
"""Moving a moved entry works as expected."""
294
tree = self.make_branch_and_tree('.')
295
self.build_tree(['a/', 'a/b', 'c/'])
296
tree.add(['a', 'a/b', 'c'], ['a-id', 'b-id', 'c-id'])
297
tree.commit('initial', rev_id='rev-1')
298
root_id = tree.get_root_id()
300
tree.rename_one('a/b', 'c/foo')
301
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
302
('c/foo', 'b-id')], tree)
303
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
304
('a/b', 'b-id')], tree.basis_tree())
306
tree.rename_one('c/foo', 'bar')
307
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('bar', 'b-id'),
308
('c', 'c-id')], tree)
309
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
310
('a/b', 'b-id')], tree.basis_tree())
312
def test_rename_to_denormalised_fails(self):
313
tree = self.make_branch_and_tree('.')
314
self.build_tree(['a'])
316
self.assertRaises((errors.InvalidNormalization, UnicodeEncodeError),
317
tree.rename_one, 'a', u'ba\u030arry')