/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
1
# Copyright (C) 2006 Canonical Ltd
2
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.
7
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.
12
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
16
17
import os
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
18
19
from bzrlib.bzrdir import BzrDir
1534.7.32 by Aaron Bentley
Got conflict handling working when conflicts involve existing files
20
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
1534.7.162 by Aaron Bentley
Handle failures creating/deleting the Limbo directory
21
                           ReusingTransform, CantMoveRoot, NotVersionedError,
22
                           ExistingLimbo, ImmortalLimbo, LockError)
1534.7.176 by abentley
Fixed up tests for Windows
23
from bzrlib.osutils import file_kind, has_symlinks, pathjoin
1534.7.140 by Aaron Bentley
Moved the merge stuff into merge.py
24
from bzrlib.merge import Merge3Merger
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
25
from bzrlib.tests import TestCaseInTempDir, TestSkipped
26
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths, 
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
27
                              resolve_conflicts, cook_conflicts, 
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
28
                              conflicts_strings, find_interesting, build_tree)
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
29
30
class TestTreeTransform(TestCaseInTempDir):
1534.7.59 by Aaron Bentley
Simplified tests
31
    def setUp(self):
32
        super(TestTreeTransform, self).setUp()
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
33
        self.wt = BzrDir.create_standalone_workingtree('.')
1534.7.161 by Aaron Bentley
Used appropriate control_files
34
        os.chdir('..')
1534.7.59 by Aaron Bentley
Simplified tests
35
36
    def get_transform(self):
37
        transform = TreeTransform(self.wt)
1534.7.100 by Aaron Bentley
Fixed path-relative test cases
38
        #self.addCleanup(transform.finalize)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
39
        return transform, transform.trans_id_tree_file_id(self.wt.get_root_id())
1534.7.59 by Aaron Bentley
Simplified tests
40
1534.7.162 by Aaron Bentley
Handle failures creating/deleting the Limbo directory
41
    def test_existing_limbo(self):
42
        limbo_name = self.wt._control_files.controlfilename('limbo')
43
        transform, root = self.get_transform()
1534.7.176 by abentley
Fixed up tests for Windows
44
        os.mkdir(pathjoin(limbo_name, 'hehe'))
1534.7.162 by Aaron Bentley
Handle failures creating/deleting the Limbo directory
45
        self.assertRaises(ImmortalLimbo, transform.apply)
46
        self.assertRaises(LockError, self.wt.unlock)
47
        self.assertRaises(ExistingLimbo, self.get_transform)
48
        self.assertRaises(LockError, self.wt.unlock)
1534.7.176 by abentley
Fixed up tests for Windows
49
        os.rmdir(pathjoin(limbo_name, 'hehe'))
1534.7.162 by Aaron Bentley
Handle failures creating/deleting the Limbo directory
50
        os.rmdir(limbo_name)
51
        transform, root = self.get_transform()
52
        transform.apply()
1534.7.59 by Aaron Bentley
Simplified tests
53
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
54
    def test_build(self):
1534.7.59 by Aaron Bentley
Simplified tests
55
        transform, root = self.get_transform() 
56
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
57
        imaginary_id = transform.trans_id_tree_path('imaginary')
1534.7.59 by Aaron Bentley
Simplified tests
58
        self.assertEqual(transform.get_tree_parent(imaginary_id), root)
59
        self.assertEqual(transform.final_kind(root), 'directory')
60
        self.assertEqual(transform.final_file_id(root), self.wt.get_root_id())
61
        trans_id = transform.create_path('name', root)
62
        self.assertIs(transform.final_file_id(trans_id), None)
63
        self.assertRaises(NoSuchFile, transform.final_kind, trans_id)
64
        transform.create_file('contents', trans_id)
65
        transform.set_executability(True, trans_id)
66
        transform.version_file('my_pretties', trans_id)
67
        self.assertRaises(DuplicateKey, transform.version_file,
68
                          'my_pretties', trans_id)
69
        self.assertEqual(transform.final_file_id(trans_id), 'my_pretties')
70
        self.assertEqual(transform.final_parent(trans_id), root)
71
        self.assertIs(transform.final_parent(root), ROOT_PARENT)
72
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
73
        oz_id = transform.create_path('oz', root)
74
        transform.create_directory(oz_id)
75
        transform.version_file('ozzie', oz_id)
76
        trans_id2 = transform.create_path('name2', root)
77
        transform.create_file('contents', trans_id2)
78
        transform.set_executability(False, trans_id2)
79
        transform.version_file('my_pretties2', trans_id2)
1534.7.191 by Aaron Bentley
Got transform.apply to list modified paths
80
        modified_paths = transform.apply().modified_paths
1534.7.100 by Aaron Bentley
Fixed path-relative test cases
81
        self.assertEqual('contents', self.wt.get_file_byname('name').read())
1534.7.59 by Aaron Bentley
Simplified tests
82
        self.assertEqual(self.wt.path2id('name'), 'my_pretties')
83
        self.assertIs(self.wt.is_executable('my_pretties'), True)
84
        self.assertIs(self.wt.is_executable('my_pretties2'), False)
1534.7.100 by Aaron Bentley
Fixed path-relative test cases
85
        self.assertEqual('directory', file_kind(self.wt.abspath('oz')))
1534.7.191 by Aaron Bentley
Got transform.apply to list modified paths
86
        self.assertEqual(len(modified_paths), 3)
87
        tree_mod_paths = [self.wt.id2abspath(f) for f in 
88
                          ('ozzie', 'my_pretties', 'my_pretties2')]
89
        self.assertSubset(tree_mod_paths, modified_paths)
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
90
        # is it safe to finalize repeatedly?
91
        transform.finalize()
1534.7.59 by Aaron Bentley
Simplified tests
92
        transform.finalize()
1534.7.2 by Aaron Bentley
Added convenience function
93
94
    def test_convenience(self):
1534.7.59 by Aaron Bentley
Simplified tests
95
        transform, root = self.get_transform()
96
        trans_id = transform.new_file('name', root, 'contents', 
97
                                      'my_pretties', True)
98
        oz = transform.new_directory('oz', root, 'oz-id')
99
        dorothy = transform.new_directory('dorothy', oz, 'dorothy-id')
100
        toto = transform.new_file('toto', dorothy, 'toto-contents', 
101
                                  'toto-id', False)
102
103
        self.assertEqual(len(transform.find_conflicts()), 0)
104
        transform.apply()
105
        self.assertRaises(ReusingTransform, transform.find_conflicts)
1534.7.100 by Aaron Bentley
Fixed path-relative test cases
106
        self.assertEqual('contents', file(self.wt.abspath('name')).read())
1534.7.59 by Aaron Bentley
Simplified tests
107
        self.assertEqual(self.wt.path2id('name'), 'my_pretties')
108
        self.assertIs(self.wt.is_executable('my_pretties'), True)
109
        self.assertEqual(self.wt.path2id('oz'), 'oz-id')
110
        self.assertEqual(self.wt.path2id('oz/dorothy'), 'dorothy-id')
111
        self.assertEqual(self.wt.path2id('oz/dorothy/toto'), 'toto-id')
112
1534.7.100 by Aaron Bentley
Fixed path-relative test cases
113
        self.assertEqual('toto-contents', 
114
                         self.wt.get_file_byname('oz/dorothy/toto').read())
1534.7.59 by Aaron Bentley
Simplified tests
115
        self.assertIs(self.wt.is_executable('toto-id'), False)
1534.7.6 by Aaron Bentley
Added conflict handling
116
117
    def test_conflicts(self):
1534.7.59 by Aaron Bentley
Simplified tests
118
        transform, root = self.get_transform()
119
        trans_id = transform.new_file('name', root, 'contents', 
120
                                      'my_pretties')
121
        self.assertEqual(len(transform.find_conflicts()), 0)
122
        trans_id2 = transform.new_file('name', root, 'Crontents', 'toto')
123
        self.assertEqual(transform.find_conflicts(), 
124
                         [('duplicate', trans_id, trans_id2, 'name')])
125
        self.assertRaises(MalformedTransform, transform.apply)
126
        transform.adjust_path('name', trans_id, trans_id2)
127
        self.assertEqual(transform.find_conflicts(), 
128
                         [('non-directory parent', trans_id)])
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
129
        tinman_id = transform.trans_id_tree_path('tinman')
1534.7.59 by Aaron Bentley
Simplified tests
130
        transform.adjust_path('name', tinman_id, trans_id2)
131
        self.assertEqual(transform.find_conflicts(), 
132
                         [('unversioned parent', tinman_id), 
133
                          ('missing parent', tinman_id)])
134
        lion_id = transform.create_path('lion', root)
135
        self.assertEqual(transform.find_conflicts(), 
136
                         [('unversioned parent', tinman_id), 
137
                          ('missing parent', tinman_id)])
138
        transform.adjust_path('name', lion_id, trans_id2)
139
        self.assertEqual(transform.find_conflicts(), 
140
                         [('unversioned parent', lion_id),
141
                          ('missing parent', lion_id)])
142
        transform.version_file("Courage", lion_id)
143
        self.assertEqual(transform.find_conflicts(), 
144
                         [('missing parent', lion_id), 
145
                          ('versioning no contents', lion_id)])
146
        transform.adjust_path('name2', root, trans_id2)
147
        self.assertEqual(transform.find_conflicts(), 
148
                         [('versioning no contents', lion_id)])
149
        transform.create_file('Contents, okay?', lion_id)
150
        transform.adjust_path('name2', trans_id2, trans_id2)
151
        self.assertEqual(transform.find_conflicts(), 
152
                         [('parent loop', trans_id2), 
153
                          ('non-directory parent', trans_id2)])
154
        transform.adjust_path('name2', root, trans_id2)
155
        oz_id = transform.new_directory('oz', root)
156
        transform.set_executability(True, oz_id)
157
        self.assertEqual(transform.find_conflicts(), 
158
                         [('unversioned executability', oz_id)])
159
        transform.version_file('oz-id', oz_id)
160
        self.assertEqual(transform.find_conflicts(), 
161
                         [('non-file executability', oz_id)])
162
        transform.set_executability(None, oz_id)
1534.7.71 by abentley
All tests pass under Windows
163
        tip_id = transform.new_file('tip', oz_id, 'ozma', 'tip-id')
1534.7.59 by Aaron Bentley
Simplified tests
164
        transform.apply()
165
        self.assertEqual(self.wt.path2id('name'), 'my_pretties')
166
        self.assertEqual('contents', file(self.wt.abspath('name')).read())
167
        transform2, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
168
        oz_id = transform2.trans_id_tree_file_id('oz-id')
1534.7.59 by Aaron Bentley
Simplified tests
169
        newtip = transform2.new_file('tip', oz_id, 'other', 'tip-id')
170
        result = transform2.find_conflicts()
1534.7.135 by Aaron Bentley
Fixed deletion handling
171
        fp = FinalPaths(transform2)
1534.7.59 by Aaron Bentley
Simplified tests
172
        self.assert_('oz/tip' in transform2._tree_path_ids)
1534.7.176 by abentley
Fixed up tests for Windows
173
        self.assertEqual(fp.get_path(newtip), pathjoin('oz', 'tip'))
1534.7.59 by Aaron Bentley
Simplified tests
174
        self.assertEqual(len(result), 2)
175
        self.assertEqual((result[0][0], result[0][1]), 
176
                         ('duplicate', newtip))
177
        self.assertEqual((result[1][0], result[1][2]), 
178
                         ('duplicate id', newtip))
1534.7.73 by Aaron Bentley
Changed model again. Now iterator is used immediately.
179
        transform2.finalize()
1534.7.59 by Aaron Bentley
Simplified tests
180
        transform3 = TreeTransform(self.wt)
181
        self.addCleanup(transform3.finalize)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
182
        oz_id = transform3.trans_id_tree_file_id('oz-id')
1534.7.59 by Aaron Bentley
Simplified tests
183
        transform3.delete_contents(oz_id)
184
        self.assertEqual(transform3.find_conflicts(), 
185
                         [('missing parent', oz_id)])
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
186
        root_id = transform3.trans_id_tree_file_id('TREE_ROOT')
187
        tip_id = transform3.trans_id_tree_file_id('tip-id')
1534.7.59 by Aaron Bentley
Simplified tests
188
        transform3.adjust_path('tip', root_id, tip_id)
189
        transform3.apply()
1534.7.36 by Aaron Bentley
Added rename tests
190
1534.7.46 by Aaron Bentley
Ensured a conflict when parents of versioned files are unversioned
191
    def test_unversioning(self):
1534.7.59 by Aaron Bentley
Simplified tests
192
        create_tree, root = self.get_transform()
193
        parent_id = create_tree.new_directory('parent', root, 'parent-id')
194
        create_tree.new_file('child', parent_id, 'child', 'child-id')
195
        create_tree.apply()
196
        unversion = TreeTransform(self.wt)
197
        self.addCleanup(unversion.finalize)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
198
        parent = unversion.trans_id_tree_path('parent')
1534.7.59 by Aaron Bentley
Simplified tests
199
        unversion.unversion_file(parent)
200
        self.assertEqual(unversion.find_conflicts(), 
201
                         [('unversioned parent', parent_id)])
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
202
        file_id = unversion.trans_id_tree_file_id('child-id')
1534.7.59 by Aaron Bentley
Simplified tests
203
        unversion.unversion_file(file_id)
204
        unversion.apply()
1534.7.46 by Aaron Bentley
Ensured a conflict when parents of versioned files are unversioned
205
1534.7.36 by Aaron Bentley
Added rename tests
206
    def test_name_invariants(self):
1534.7.59 by Aaron Bentley
Simplified tests
207
        create_tree, root = self.get_transform()
208
        # prepare tree
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
209
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
1534.7.59 by Aaron Bentley
Simplified tests
210
        create_tree.new_file('name1', root, 'hello1', 'name1')
211
        create_tree.new_file('name2', root, 'hello2', 'name2')
212
        ddir = create_tree.new_directory('dying_directory', root, 'ddir')
213
        create_tree.new_file('dying_file', ddir, 'goodbye1', 'dfile')
214
        create_tree.new_file('moving_file', ddir, 'later1', 'mfile')
215
        create_tree.new_file('moving_file2', root, 'later2', 'mfile2')
216
        create_tree.apply()
217
218
        mangle_tree,root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
219
        root = mangle_tree.trans_id_tree_file_id('TREE_ROOT')
1534.7.59 by Aaron Bentley
Simplified tests
220
        #swap names
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
221
        name1 = mangle_tree.trans_id_tree_file_id('name1')
222
        name2 = mangle_tree.trans_id_tree_file_id('name2')
1534.7.59 by Aaron Bentley
Simplified tests
223
        mangle_tree.adjust_path('name2', root, name1)
224
        mangle_tree.adjust_path('name1', root, name2)
225
226
        #tests for deleting parent directories 
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
227
        ddir = mangle_tree.trans_id_tree_file_id('ddir')
1534.7.59 by Aaron Bentley
Simplified tests
228
        mangle_tree.delete_contents(ddir)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
229
        dfile = mangle_tree.trans_id_tree_file_id('dfile')
1534.7.59 by Aaron Bentley
Simplified tests
230
        mangle_tree.delete_versioned(dfile)
231
        mangle_tree.unversion_file(dfile)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
232
        mfile = mangle_tree.trans_id_tree_file_id('mfile')
1534.7.59 by Aaron Bentley
Simplified tests
233
        mangle_tree.adjust_path('mfile', root, mfile)
234
235
        #tests for adding parent directories
236
        newdir = mangle_tree.new_directory('new_directory', root, 'newdir')
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
237
        mfile2 = mangle_tree.trans_id_tree_file_id('mfile2')
1534.7.59 by Aaron Bentley
Simplified tests
238
        mangle_tree.adjust_path('mfile2', newdir, mfile2)
239
        mangle_tree.new_file('newfile', newdir, 'hello3', 'dfile')
240
        self.assertEqual(mangle_tree.final_file_id(mfile2), 'mfile2')
241
        self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
242
        self.assertEqual(mangle_tree.final_file_id(mfile2), 'mfile2')
243
        mangle_tree.apply()
244
        self.assertEqual(file(self.wt.abspath('name1')).read(), 'hello2')
245
        self.assertEqual(file(self.wt.abspath('name2')).read(), 'hello1')
1534.7.176 by abentley
Fixed up tests for Windows
246
        mfile2_path = self.wt.abspath(pathjoin('new_directory','mfile2'))
1534.7.41 by Aaron Bentley
Got inventory ID movement working
247
        self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
1534.7.38 by Aaron Bentley
Tested adding paths
248
        self.assertEqual(file(mfile2_path).read(), 'later2')
1534.7.59 by Aaron Bentley
Simplified tests
249
        self.assertEqual(self.wt.id2path('mfile2'), 'new_directory/mfile2')
250
        self.assertEqual(self.wt.path2id('new_directory/mfile2'), 'mfile2')
1534.7.176 by abentley
Fixed up tests for Windows
251
        newfile_path = self.wt.abspath(pathjoin('new_directory','newfile'))
1534.7.38 by Aaron Bentley
Tested adding paths
252
        self.assertEqual(file(newfile_path).read(), 'hello3')
1534.7.59 by Aaron Bentley
Simplified tests
253
        self.assertEqual(self.wt.path2id('dying_directory'), 'ddir')
254
        self.assertIs(self.wt.path2id('dying_directory/dying_file'), None)
1534.7.176 by abentley
Fixed up tests for Windows
255
        mfile2_path = self.wt.abspath(pathjoin('new_directory','mfile2'))
1534.7.43 by abentley
Fixed some Windows bugs, introduced a conflicts bug
256
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
257
    def test_both_rename(self):
258
        create_tree,root = self.get_transform()
259
        newdir = create_tree.new_directory('selftest', root, 'selftest-id')
260
        create_tree.new_file('blackbox.py', newdir, 'hello1', 'blackbox-id')
261
        create_tree.apply()        
262
        mangle_tree,root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
263
        selftest = mangle_tree.trans_id_tree_file_id('selftest-id')
264
        blackbox = mangle_tree.trans_id_tree_file_id('blackbox-id')
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
265
        mangle_tree.adjust_path('test', root, selftest)
266
        mangle_tree.adjust_path('test_too_much', root, selftest)
267
        mangle_tree.set_executability(True, blackbox)
268
        mangle_tree.apply()
269
270
    def test_both_rename2(self):
271
        create_tree,root = self.get_transform()
272
        bzrlib = create_tree.new_directory('bzrlib', root, 'bzrlib-id')
273
        tests = create_tree.new_directory('tests', bzrlib, 'tests-id')
274
        blackbox = create_tree.new_directory('blackbox', tests, 'blackbox-id')
275
        create_tree.new_file('test_too_much.py', blackbox, 'hello1', 
276
                             'test_too_much-id')
277
        create_tree.apply()        
278
        mangle_tree,root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
279
        bzrlib = mangle_tree.trans_id_tree_file_id('bzrlib-id')
280
        tests = mangle_tree.trans_id_tree_file_id('tests-id')
281
        test_too_much = mangle_tree.trans_id_tree_file_id('test_too_much-id')
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
282
        mangle_tree.adjust_path('selftest', bzrlib, tests)
283
        mangle_tree.adjust_path('blackbox.py', tests, test_too_much) 
284
        mangle_tree.set_executability(True, test_too_much)
285
        mangle_tree.apply()
286
287
    def test_both_rename3(self):
288
        create_tree,root = self.get_transform()
289
        tests = create_tree.new_directory('tests', root, 'tests-id')
290
        create_tree.new_file('test_too_much.py', tests, 'hello1', 
291
                             'test_too_much-id')
292
        create_tree.apply()        
293
        mangle_tree,root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
294
        tests = mangle_tree.trans_id_tree_file_id('tests-id')
295
        test_too_much = mangle_tree.trans_id_tree_file_id('test_too_much-id')
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
296
        mangle_tree.adjust_path('selftest', root, tests)
297
        mangle_tree.adjust_path('blackbox.py', tests, test_too_much) 
298
        mangle_tree.set_executability(True, test_too_much)
299
        mangle_tree.apply()
300
1534.7.48 by Aaron Bentley
Ensured we can move/rename dangling inventory entries
301
    def test_move_dangling_ie(self):
1534.7.59 by Aaron Bentley
Simplified tests
302
        create_tree, root = self.get_transform()
303
        # prepare tree
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
304
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
1534.7.59 by Aaron Bentley
Simplified tests
305
        create_tree.new_file('name1', root, 'hello1', 'name1')
306
        create_tree.apply()
307
        delete_contents, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
308
        file = delete_contents.trans_id_tree_file_id('name1')
1534.7.59 by Aaron Bentley
Simplified tests
309
        delete_contents.delete_contents(file)
310
        delete_contents.apply()
311
        move_id, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
312
        name1 = move_id.trans_id_tree_file_id('name1')
1534.7.59 by Aaron Bentley
Simplified tests
313
        newdir = move_id.new_directory('dir', root, 'newdir')
314
        move_id.adjust_path('name2', newdir, name1)
315
        move_id.apply()
1534.7.48 by Aaron Bentley
Ensured we can move/rename dangling inventory entries
316
        
1534.7.50 by Aaron Bentley
Detect duplicate inventory ids
317
    def test_replace_dangling_ie(self):
1534.7.59 by Aaron Bentley
Simplified tests
318
        create_tree, root = self.get_transform()
319
        # prepare tree
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
320
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
1534.7.59 by Aaron Bentley
Simplified tests
321
        create_tree.new_file('name1', root, 'hello1', 'name1')
322
        create_tree.apply()
323
        delete_contents = TreeTransform(self.wt)
324
        self.addCleanup(delete_contents.finalize)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
325
        file = delete_contents.trans_id_tree_file_id('name1')
1534.7.59 by Aaron Bentley
Simplified tests
326
        delete_contents.delete_contents(file)
327
        delete_contents.apply()
328
        delete_contents.finalize()
329
        replace = TreeTransform(self.wt)
330
        self.addCleanup(replace.finalize)
331
        name2 = replace.new_file('name2', root, 'hello2', 'name1')
332
        conflicts = replace.find_conflicts()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
333
        name1 = replace.trans_id_tree_file_id('name1')
1534.7.59 by Aaron Bentley
Simplified tests
334
        self.assertEqual(conflicts, [('duplicate id', name1, name2)])
335
        resolve_conflicts(replace)
336
        replace.apply()
1534.7.48 by Aaron Bentley
Ensured we can move/rename dangling inventory entries
337
1534.7.43 by abentley
Fixed some Windows bugs, introduced a conflicts bug
338
    def test_symlinks(self):
1534.7.45 by Aaron Bentley
Skipped symlink test more correctly
339
        if not has_symlinks():
340
            raise TestSkipped('Symlinks are not supported on this platform')
1534.7.59 by Aaron Bentley
Simplified tests
341
        transform,root = self.get_transform()
342
        oz_id = transform.new_directory('oz', root, 'oz-id')
343
        wizard = transform.new_symlink('wizard', oz_id, 'wizard-target', 
344
                                       'wizard-id')
345
        wiz_id = transform.create_path('wizard2', oz_id)
346
        transform.create_symlink('behind_curtain', wiz_id)
347
        transform.version_file('wiz-id2', wiz_id)            
1534.7.71 by abentley
All tests pass under Windows
348
        transform.set_executability(True, wiz_id)
349
        self.assertEqual(transform.find_conflicts(), 
350
                         [('non-file executability', wiz_id)])
351
        transform.set_executability(None, wiz_id)
1534.7.59 by Aaron Bentley
Simplified tests
352
        transform.apply()
353
        self.assertEqual(self.wt.path2id('oz/wizard'), 'wizard-id')
1534.7.100 by Aaron Bentley
Fixed path-relative test cases
354
        self.assertEqual(file_kind(self.wt.abspath('oz/wizard')), 'symlink')
355
        self.assertEqual(os.readlink(self.wt.abspath('oz/wizard2')), 
356
                         'behind_curtain')
357
        self.assertEqual(os.readlink(self.wt.abspath('oz/wizard')),
358
                         'wizard-target')
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
359
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
360
361
    def get_conflicted(self):
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
362
        create,root = self.get_transform()
363
        create.new_file('dorothy', root, 'dorothy', 'dorothy-id')
1534.7.61 by Aaron Bentley
Handled parent loops, missing parents, unversioned parents
364
        oz = create.new_directory('oz', root, 'oz-id')
365
        create.new_directory('emeraldcity', oz, 'emerald-id')
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
366
        create.apply()
367
        conflicts,root = self.get_transform()
1534.7.65 by Aaron Bentley
Text cleaup/docs
368
        # set up duplicate entry, duplicate id
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
369
        new_dorothy = conflicts.new_file('dorothy', root, 'dorothy', 
370
                                         'dorothy-id')
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
371
        old_dorothy = conflicts.trans_id_tree_file_id('dorothy-id')
372
        oz = conflicts.trans_id_tree_file_id('oz-id')
1534.7.65 by Aaron Bentley
Text cleaup/docs
373
        # set up missing, unversioned parent
374
        conflicts.delete_versioned(oz)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
375
        emerald = conflicts.trans_id_tree_file_id('emerald-id')
1534.7.65 by Aaron Bentley
Text cleaup/docs
376
        # set up parent loop
1534.7.61 by Aaron Bentley
Handled parent loops, missing parents, unversioned parents
377
        conflicts.adjust_path('emeraldcity', emerald, emerald)
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
378
        return conflicts, emerald, oz, old_dorothy, new_dorothy
379
380
    def test_conflict_resolution(self):
381
        conflicts, emerald, oz, old_dorothy, new_dorothy =\
382
            self.get_conflicted()
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
383
        resolve_conflicts(conflicts)
384
        self.assertEqual(conflicts.final_name(old_dorothy), 'dorothy.moved')
385
        self.assertIs(conflicts.final_file_id(old_dorothy), None)
386
        self.assertEqual(conflicts.final_name(new_dorothy), 'dorothy')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
387
        self.assertEqual(conflicts.final_file_id(new_dorothy), 'dorothy-id')
1534.7.64 by Aaron Bentley
Extra testing
388
        self.assertEqual(conflicts.final_parent(emerald), oz)
1534.7.63 by Aaron Bentley
Ensure transform can be applied after resolution
389
        conflicts.apply()
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
390
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
391
    def test_cook_conflicts(self):
392
        tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
393
        raw_conflicts = resolve_conflicts(tt)
394
        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
1534.7.171 by Aaron Bentley
Implemented stringifying filesystem conflicts
395
        duplicate = ('duplicate', 'Moved existing file to', 'dorothy.moved', 
396
                     None, 'dorothy', 'dorothy-id')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
397
        self.assertEqual(cooked_conflicts[0], duplicate)
398
        duplicate_id = ('duplicate id', 'Unversioned existing file', 
399
                        'dorothy.moved', None, 'dorothy', 'dorothy-id')
400
        self.assertEqual(cooked_conflicts[1], duplicate_id)
401
        missing_parent = ('missing parent', 'Not deleting', 'oz', 'oz-id')
402
        self.assertEqual(cooked_conflicts[2], missing_parent)
403
        unversioned_parent = ('unversioned parent', 
1534.7.171 by Aaron Bentley
Implemented stringifying filesystem conflicts
404
                              'Versioned directory', 'oz', 'oz-id')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
405
        self.assertEqual(cooked_conflicts[3], unversioned_parent)
406
        parent_loop = ('parent loop', 'Cancelled move', 'oz/emeraldcity', 
407
                       'emerald-id', 'oz/emeraldcity', 'emerald-id')
408
        self.assertEqual(cooked_conflicts[4], parent_loop)
409
        self.assertEqual(len(cooked_conflicts), 5)
410
        tt.finalize()
411
412
    def test_string_conflicts(self):
413
        tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
414
        raw_conflicts = resolve_conflicts(tt)
415
        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
416
        tt.finalize()
1534.7.171 by Aaron Bentley
Implemented stringifying filesystem conflicts
417
        conflicts_s = list(conflicts_strings(cooked_conflicts))
418
        self.assertEqual(len(cooked_conflicts), len(conflicts_s))
419
        self.assertEqual(conflicts_s[0], 'Conflict adding file dorothy.  '
420
                                         'Moved existing file to '
421
                                         'dorothy.moved.')
422
        self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy.  '
423
                                         'Unversioned existing file '
424
                                         'dorothy.moved.')
425
        self.assertEqual(conflicts_s[2], 'Conflict adding files to oz.  '
426
                                         'Not deleting.')
427
        self.assertEqual(conflicts_s[3], 'Conflict adding versioned files to '
428
                                         'oz.  Versioned directory.')
429
        self.assertEqual(conflicts_s[4], 'Conflict moving oz/emeraldcity into'
430
                                         ' oz/emeraldcity.  Cancelled move.')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
431
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
432
    def test_moving_versioned_directories(self):
433
        create, root = self.get_transform()
434
        kansas = create.new_directory('kansas', root, 'kansas-id')
435
        create.new_directory('house', kansas, 'house-id')
436
        create.new_directory('oz', root, 'oz-id')
437
        create.apply()
438
        cyclone, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
439
        oz = cyclone.trans_id_tree_file_id('oz-id')
440
        house = cyclone.trans_id_tree_file_id('house-id')
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
441
        cyclone.adjust_path('house', oz, house)
442
        cyclone.apply()
1534.7.66 by Aaron Bentley
Ensured we don't accidentally move the root directory
443
444
    def test_moving_root(self):
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
445
        create, root = self.get_transform()
446
        fun = create.new_directory('fun', root, 'fun-id')
447
        create.new_directory('sun', root, 'sun-id')
448
        create.new_directory('moon', root, 'moon')
449
        create.apply()
1534.7.66 by Aaron Bentley
Ensured we don't accidentally move the root directory
450
        transform, root = self.get_transform()
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
451
        transform.adjust_root_path('oldroot', fun)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
452
        new_root=transform.trans_id_tree_path('')
1534.7.69 by Aaron Bentley
Got real root moves working
453
        transform.version_file('new-root', new_root)
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
454
        transform.apply()
1534.7.93 by Aaron Bentley
Added text merge test
455
1534.7.114 by Aaron Bentley
Added file renaming test case
456
    def test_renames(self):
457
        create, root = self.get_transform()
458
        old = create.new_directory('old-parent', root, 'old-id')
459
        intermediate = create.new_directory('intermediate', old, 'im-id')
460
        myfile = create.new_file('myfile', intermediate, 'myfile-text',
461
                                 'myfile-id')
462
        create.apply()
463
        rename, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
464
        old = rename.trans_id_file_id('old-id')
1534.7.114 by Aaron Bentley
Added file renaming test case
465
        rename.adjust_path('new', root, old)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
466
        myfile = rename.trans_id_file_id('myfile-id')
1534.7.114 by Aaron Bentley
Added file renaming test case
467
        rename.set_executability(True, myfile)
468
        rename.apply()
469
1534.7.123 by Aaron Bentley
Fixed handling of unversioned files
470
    def test_find_interesting(self):
471
        create, root = self.get_transform()
472
        wt = create._tree
473
        create.new_file('vfile', root, 'myfile-text', 'myfile-id')
474
        create.new_file('uvfile', root, 'othertext')
475
        create.apply()
476
        self.assertEqual(find_interesting(wt, wt, ['vfile']),
477
                         set(['myfile-id']))
478
        self.assertRaises(NotVersionedError, find_interesting, wt, wt,
479
                          ['uvfile'])
480
1534.7.93 by Aaron Bentley
Added text merge test
481
482
class TransformGroup(object):
483
    def __init__(self, dirname):
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
484
        self.name = dirname
1534.7.93 by Aaron Bentley
Added text merge test
485
        os.mkdir(dirname)
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
486
        self.wt = BzrDir.create_standalone_workingtree(dirname)
487
        self.b = self.wt.branch
1534.7.93 by Aaron Bentley
Added text merge test
488
        self.tt = TreeTransform(self.wt)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
489
        self.root = self.tt.trans_id_tree_file_id(self.wt.get_root_id())
1534.7.93 by Aaron Bentley
Added text merge test
490
1534.7.95 by Aaron Bentley
Added more text merge tests
491
def conflict_text(tree, merge):
492
    template = '%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
493
    return template % ('<' * 7, tree, '=' * 7, merge, '>' * 7)
494
1534.7.93 by Aaron Bentley
Added text merge test
495
496
class TestTransformMerge(TestCaseInTempDir):
497
    def test_text_merge(self):
498
        base = TransformGroup("base")
499
        base.tt.new_file('a', base.root, 'a\nb\nc\nd\be\n', 'a')
1534.7.95 by Aaron Bentley
Added more text merge tests
500
        base.tt.new_file('b', base.root, 'b1', 'b')
501
        base.tt.new_file('c', base.root, 'c', 'c')
502
        base.tt.new_file('d', base.root, 'd', 'd')
503
        base.tt.new_file('e', base.root, 'e', 'e')
504
        base.tt.new_file('f', base.root, 'f', 'f')
1534.7.96 by Aaron Bentley
Tested with BASE as directory
505
        base.tt.new_directory('g', base.root, 'g')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
506
        base.tt.new_directory('h', base.root, 'h')
1534.7.93 by Aaron Bentley
Added text merge test
507
        base.tt.apply()
508
        other = TransformGroup("other")
509
        other.tt.new_file('a', other.root, 'y\nb\nc\nd\be\n', 'a')
1534.7.95 by Aaron Bentley
Added more text merge tests
510
        other.tt.new_file('b', other.root, 'b2', 'b')
511
        other.tt.new_file('c', other.root, 'c2', 'c')
512
        other.tt.new_file('d', other.root, 'd', 'd')
513
        other.tt.new_file('e', other.root, 'e2', 'e')
514
        other.tt.new_file('f', other.root, 'f', 'f')
1534.7.96 by Aaron Bentley
Tested with BASE as directory
515
        other.tt.new_file('g', other.root, 'g', 'g')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
516
        other.tt.new_file('h', other.root, 'h\ni\nj\nk\n', 'h')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
517
        other.tt.new_file('i', other.root, 'h\ni\nj\nk\n', 'i')
1534.7.93 by Aaron Bentley
Added text merge test
518
        other.tt.apply()
519
        this = TransformGroup("this")
520
        this.tt.new_file('a', this.root, 'a\nb\nc\nd\bz\n', 'a')
1534.7.95 by Aaron Bentley
Added more text merge tests
521
        this.tt.new_file('b', this.root, 'b', 'b')
522
        this.tt.new_file('c', this.root, 'c', 'c')
523
        this.tt.new_file('d', this.root, 'd2', 'd')
524
        this.tt.new_file('e', this.root, 'e2', 'e')
525
        this.tt.new_file('f', this.root, 'f', 'f')
1534.7.96 by Aaron Bentley
Tested with BASE as directory
526
        this.tt.new_file('g', this.root, 'g', 'g')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
527
        this.tt.new_file('h', this.root, '1\n2\n3\n4\n', 'h')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
528
        this.tt.new_file('i', this.root, '1\n2\n3\n4\n', 'i')
1534.7.93 by Aaron Bentley
Added text merge test
529
        this.tt.apply()
530
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.95 by Aaron Bentley
Added more text merge tests
531
        # textual merge
1534.7.93 by Aaron Bentley
Added text merge test
532
        self.assertEqual(this.wt.get_file('a').read(), 'y\nb\nc\nd\bz\n')
1534.7.95 by Aaron Bentley
Added more text merge tests
533
        # three-way text conflict
534
        self.assertEqual(this.wt.get_file('b').read(), 
535
                         conflict_text('b', 'b2'))
536
        # OTHER wins
537
        self.assertEqual(this.wt.get_file('c').read(), 'c2')
538
        # THIS wins
539
        self.assertEqual(this.wt.get_file('d').read(), 'd2')
540
        # Ambigious clean merge
541
        self.assertEqual(this.wt.get_file('e').read(), 'e2')
542
        # No change
543
        self.assertEqual(this.wt.get_file('f').read(), 'f')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
544
        # Correct correct results when THIS == OTHER 
1534.7.96 by Aaron Bentley
Tested with BASE as directory
545
        self.assertEqual(this.wt.get_file('g').read(), 'g')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
546
        # Text conflict when THIS & OTHER are text and BASE is dir
547
        self.assertEqual(this.wt.get_file('h').read(), 
548
                         conflict_text('1\n2\n3\n4\n', 'h\ni\nj\nk\n'))
549
        self.assertEqual(this.wt.get_file_byname('h.THIS').read(),
550
                         '1\n2\n3\n4\n')
551
        self.assertEqual(this.wt.get_file_byname('h.OTHER').read(),
552
                         'h\ni\nj\nk\n')
553
        self.assertEqual(file_kind(this.wt.abspath('h.BASE')), 'directory')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
554
        self.assertEqual(this.wt.get_file('i').read(), 
555
                         conflict_text('1\n2\n3\n4\n', 'h\ni\nj\nk\n'))
556
        self.assertEqual(this.wt.get_file_byname('i.THIS').read(),
557
                         '1\n2\n3\n4\n')
558
        self.assertEqual(this.wt.get_file_byname('i.OTHER').read(),
559
                         'h\ni\nj\nk\n')
560
        self.assertEqual(os.path.exists(this.wt.abspath('i.BASE')), False)
1534.7.192 by Aaron Bentley
Record hashes produced by merges
561
        modified = ['a', 'b', 'c', 'h', 'i']
562
        merge_modified = this.wt.merge_modified()
563
        self.assertSubset(merge_modified, modified)
564
        self.assertEqual(len(merge_modified), len(modified))
565
        file(this.wt.id2abspath('a'), 'wb').write('booga')
566
        modified.pop(0)
567
        merge_modified = this.wt.merge_modified()
568
        self.assertSubset(merge_modified, modified)
569
        self.assertEqual(len(merge_modified), len(modified))
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
570
571
    def test_file_merge(self):
1534.7.153 by Aaron Bentley
Handled test cases involving symlinks
572
        if not has_symlinks():
573
            raise TestSkipped('Symlinks are not supported on this platform')
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
574
        base = TransformGroup("BASE")
575
        this = TransformGroup("THIS")
576
        other = TransformGroup("OTHER")
577
        for tg in this, base, other:
578
            tg.tt.new_directory('a', tg.root, 'a')
579
            tg.tt.new_symlink('b', tg.root, 'b', 'b')
580
            tg.tt.new_file('c', tg.root, 'c', 'c')
581
            tg.tt.new_symlink('d', tg.root, tg.name, 'd')
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
582
        targets = ((base, 'base-e', 'base-f', None, None), 
583
                   (this, 'other-e', 'this-f', 'other-g', 'this-h'), 
584
                   (other, 'other-e', None, 'other-g', 'other-h'))
585
        for tg, e_target, f_target, g_target, h_target in targets:
586
            for link, target in (('e', e_target), ('f', f_target), 
587
                                 ('g', g_target), ('h', h_target)):
588
                if target is not None:
589
                    tg.tt.new_symlink(link, tg.root, target, link)
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
590
591
        for tg in this, base, other:
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
592
            tg.tt.apply()
593
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
594
        self.assertIs(os.path.isdir(this.wt.abspath('a')), True)
595
        self.assertIs(os.path.islink(this.wt.abspath('b')), True)
596
        self.assertIs(os.path.isfile(this.wt.abspath('c')), True)
597
        for suffix in ('THIS', 'BASE', 'OTHER'):
598
            self.assertEqual(os.readlink(this.wt.abspath('d.'+suffix)), suffix)
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
599
        self.assertIs(os.path.lexists(this.wt.abspath('d')), False)
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
600
        self.assertEqual(this.wt.id2path('d'), 'd.OTHER')
601
        self.assertEqual(this.wt.id2path('f'), 'f.THIS')
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
602
        self.assertEqual(os.readlink(this.wt.abspath('e')), 'other-e')
603
        self.assertIs(os.path.lexists(this.wt.abspath('e.THIS')), False)
604
        self.assertIs(os.path.lexists(this.wt.abspath('e.OTHER')), False)
605
        self.assertIs(os.path.lexists(this.wt.abspath('e.BASE')), False)
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
606
        self.assertIs(os.path.lexists(this.wt.abspath('g')), True)
607
        self.assertIs(os.path.lexists(this.wt.abspath('g.BASE')), False)
608
        self.assertIs(os.path.lexists(this.wt.abspath('h')), False)
609
        self.assertIs(os.path.lexists(this.wt.abspath('h.BASE')), False)
610
        self.assertIs(os.path.lexists(this.wt.abspath('h.THIS')), True)
611
        self.assertIs(os.path.lexists(this.wt.abspath('h.OTHER')), True)
1534.7.105 by Aaron Bentley
Got merge with rename working
612
613
    def test_filename_merge(self):
614
        base = TransformGroup("BASE")
615
        this = TransformGroup("THIS")
616
        other = TransformGroup("OTHER")
617
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a') 
618
                                   for t in [base, this, other]]
619
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b') 
620
                                   for t in [base, this, other]]
621
        base.tt.new_directory('c', base_a, 'c')
622
        this.tt.new_directory('c1', this_a, 'c')
623
        other.tt.new_directory('c', other_b, 'c')
624
625
        base.tt.new_directory('d', base_a, 'd')
626
        this.tt.new_directory('d1', this_b, 'd')
627
        other.tt.new_directory('d', other_a, 'd')
628
629
        base.tt.new_directory('e', base_a, 'e')
630
        this.tt.new_directory('e', this_a, 'e')
631
        other.tt.new_directory('e1', other_b, 'e')
632
633
        base.tt.new_directory('f', base_a, 'f')
634
        this.tt.new_directory('f1', this_b, 'f')
635
        other.tt.new_directory('f1', other_b, 'f')
636
637
        for tg in [this, base, other]:
638
            tg.tt.apply()
639
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.176 by abentley
Fixed up tests for Windows
640
        self.assertEqual(this.wt.id2path('c'), pathjoin('b/c1'))
641
        self.assertEqual(this.wt.id2path('d'), pathjoin('b/d1'))
642
        self.assertEqual(this.wt.id2path('e'), pathjoin('b/e1'))
643
        self.assertEqual(this.wt.id2path('f'), pathjoin('b/f1'))
1534.7.105 by Aaron Bentley
Got merge with rename working
644
645
    def test_filename_merge_conflicts(self):
646
        base = TransformGroup("BASE")
647
        this = TransformGroup("THIS")
648
        other = TransformGroup("OTHER")
649
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a') 
650
                                   for t in [base, this, other]]
651
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b') 
652
                                   for t in [base, this, other]]
653
654
        base.tt.new_file('g', base_a, 'g', 'g')
655
        other.tt.new_file('g1', other_b, 'g1', 'g')
656
657
        base.tt.new_file('h', base_a, 'h', 'h')
658
        this.tt.new_file('h1', this_b, 'h1', 'h')
659
660
        base.tt.new_file('i', base.root, 'i', 'i')
1534.7.153 by Aaron Bentley
Handled test cases involving symlinks
661
        other.tt.new_directory('i1', this_b, 'i')
1534.7.105 by Aaron Bentley
Got merge with rename working
662
663
        for tg in [this, base, other]:
664
            tg.tt.apply()
665
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
666
1534.7.176 by abentley
Fixed up tests for Windows
667
        self.assertEqual(this.wt.id2path('g'), pathjoin('b/g1.OTHER'))
1534.7.105 by Aaron Bentley
Got merge with rename working
668
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.BASE')), True)
669
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.THIS')), False)
1534.7.176 by abentley
Fixed up tests for Windows
670
        self.assertEqual(this.wt.id2path('h'), pathjoin('b/h1.THIS'))
1534.7.105 by Aaron Bentley
Got merge with rename working
671
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.BASE')), True)
672
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.OTHER')), False)
1534.7.176 by abentley
Fixed up tests for Windows
673
        self.assertEqual(this.wt.id2path('i'), pathjoin('b/i1.OTHER'))
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
674
675
class TestBuildTree(TestCaseInTempDir):
676
    def test_build_tree(self):
677
        if not has_symlinks():
678
            raise TestSkipped('Test requires symlink support')
679
        os.mkdir('a')
680
        a = BzrDir.create_standalone_workingtree('a')
681
        os.mkdir('a/foo')
682
        file('a/foo/bar', 'wb').write('contents')
683
        os.symlink('a/foo/bar', 'a/foo/baz')
684
        a.add(['foo', 'foo/bar', 'foo/baz'])
685
        a.commit('initial commit')
686
        b = BzrDir.create_standalone_workingtree('b')
687
        build_tree(a.basis_tree(), b)
688
        self.assertIs(os.path.isdir('b/foo'), True)
689
        self.assertEqual(file('b/foo/bar', 'rb').read(), "contents")
690
        self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')