/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
1558.7.11 by Aaron Bentley
Avoid spurious conflict on add/delete
191
    def test_add_del(self):
192
        start, root = self.get_transform()
193
        start.new_directory('a', root, 'a')
194
        start.apply()
195
        transform, root = self.get_transform()
196
        transform.delete_versioned(transform.trans_id_tree_file_id('a'))
197
        transform.new_directory('a', root, 'a')
198
        transform.apply()
199
1534.7.46 by Aaron Bentley
Ensured a conflict when parents of versioned files are unversioned
200
    def test_unversioning(self):
1534.7.59 by Aaron Bentley
Simplified tests
201
        create_tree, root = self.get_transform()
202
        parent_id = create_tree.new_directory('parent', root, 'parent-id')
203
        create_tree.new_file('child', parent_id, 'child', 'child-id')
204
        create_tree.apply()
205
        unversion = TreeTransform(self.wt)
206
        self.addCleanup(unversion.finalize)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
207
        parent = unversion.trans_id_tree_path('parent')
1534.7.59 by Aaron Bentley
Simplified tests
208
        unversion.unversion_file(parent)
209
        self.assertEqual(unversion.find_conflicts(), 
210
                         [('unversioned parent', parent_id)])
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
211
        file_id = unversion.trans_id_tree_file_id('child-id')
1534.7.59 by Aaron Bentley
Simplified tests
212
        unversion.unversion_file(file_id)
213
        unversion.apply()
1534.7.46 by Aaron Bentley
Ensured a conflict when parents of versioned files are unversioned
214
1534.7.36 by Aaron Bentley
Added rename tests
215
    def test_name_invariants(self):
1534.7.59 by Aaron Bentley
Simplified tests
216
        create_tree, root = self.get_transform()
217
        # prepare tree
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
218
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
1534.7.59 by Aaron Bentley
Simplified tests
219
        create_tree.new_file('name1', root, 'hello1', 'name1')
220
        create_tree.new_file('name2', root, 'hello2', 'name2')
221
        ddir = create_tree.new_directory('dying_directory', root, 'ddir')
222
        create_tree.new_file('dying_file', ddir, 'goodbye1', 'dfile')
223
        create_tree.new_file('moving_file', ddir, 'later1', 'mfile')
224
        create_tree.new_file('moving_file2', root, 'later2', 'mfile2')
225
        create_tree.apply()
226
227
        mangle_tree,root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
228
        root = mangle_tree.trans_id_tree_file_id('TREE_ROOT')
1534.7.59 by Aaron Bentley
Simplified tests
229
        #swap names
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
230
        name1 = mangle_tree.trans_id_tree_file_id('name1')
231
        name2 = mangle_tree.trans_id_tree_file_id('name2')
1534.7.59 by Aaron Bentley
Simplified tests
232
        mangle_tree.adjust_path('name2', root, name1)
233
        mangle_tree.adjust_path('name1', root, name2)
234
235
        #tests for deleting parent directories 
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
236
        ddir = mangle_tree.trans_id_tree_file_id('ddir')
1534.7.59 by Aaron Bentley
Simplified tests
237
        mangle_tree.delete_contents(ddir)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
238
        dfile = mangle_tree.trans_id_tree_file_id('dfile')
1534.7.59 by Aaron Bentley
Simplified tests
239
        mangle_tree.delete_versioned(dfile)
240
        mangle_tree.unversion_file(dfile)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
241
        mfile = mangle_tree.trans_id_tree_file_id('mfile')
1534.7.59 by Aaron Bentley
Simplified tests
242
        mangle_tree.adjust_path('mfile', root, mfile)
243
244
        #tests for adding parent directories
245
        newdir = mangle_tree.new_directory('new_directory', root, 'newdir')
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
246
        mfile2 = mangle_tree.trans_id_tree_file_id('mfile2')
1534.7.59 by Aaron Bentley
Simplified tests
247
        mangle_tree.adjust_path('mfile2', newdir, mfile2)
248
        mangle_tree.new_file('newfile', newdir, 'hello3', 'dfile')
249
        self.assertEqual(mangle_tree.final_file_id(mfile2), 'mfile2')
250
        self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
251
        self.assertEqual(mangle_tree.final_file_id(mfile2), 'mfile2')
252
        mangle_tree.apply()
253
        self.assertEqual(file(self.wt.abspath('name1')).read(), 'hello2')
254
        self.assertEqual(file(self.wt.abspath('name2')).read(), 'hello1')
1534.7.176 by abentley
Fixed up tests for Windows
255
        mfile2_path = self.wt.abspath(pathjoin('new_directory','mfile2'))
1534.7.41 by Aaron Bentley
Got inventory ID movement working
256
        self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
1534.7.38 by Aaron Bentley
Tested adding paths
257
        self.assertEqual(file(mfile2_path).read(), 'later2')
1534.7.59 by Aaron Bentley
Simplified tests
258
        self.assertEqual(self.wt.id2path('mfile2'), 'new_directory/mfile2')
259
        self.assertEqual(self.wt.path2id('new_directory/mfile2'), 'mfile2')
1534.7.176 by abentley
Fixed up tests for Windows
260
        newfile_path = self.wt.abspath(pathjoin('new_directory','newfile'))
1534.7.38 by Aaron Bentley
Tested adding paths
261
        self.assertEqual(file(newfile_path).read(), 'hello3')
1534.7.59 by Aaron Bentley
Simplified tests
262
        self.assertEqual(self.wt.path2id('dying_directory'), 'ddir')
263
        self.assertIs(self.wt.path2id('dying_directory/dying_file'), None)
1534.7.176 by abentley
Fixed up tests for Windows
264
        mfile2_path = self.wt.abspath(pathjoin('new_directory','mfile2'))
1534.7.43 by abentley
Fixed some Windows bugs, introduced a conflicts bug
265
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
266
    def test_both_rename(self):
267
        create_tree,root = self.get_transform()
268
        newdir = create_tree.new_directory('selftest', root, 'selftest-id')
269
        create_tree.new_file('blackbox.py', newdir, 'hello1', 'blackbox-id')
270
        create_tree.apply()        
271
        mangle_tree,root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
272
        selftest = mangle_tree.trans_id_tree_file_id('selftest-id')
273
        blackbox = mangle_tree.trans_id_tree_file_id('blackbox-id')
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
274
        mangle_tree.adjust_path('test', root, selftest)
275
        mangle_tree.adjust_path('test_too_much', root, selftest)
276
        mangle_tree.set_executability(True, blackbox)
277
        mangle_tree.apply()
278
279
    def test_both_rename2(self):
280
        create_tree,root = self.get_transform()
281
        bzrlib = create_tree.new_directory('bzrlib', root, 'bzrlib-id')
282
        tests = create_tree.new_directory('tests', bzrlib, 'tests-id')
283
        blackbox = create_tree.new_directory('blackbox', tests, 'blackbox-id')
284
        create_tree.new_file('test_too_much.py', blackbox, 'hello1', 
285
                             'test_too_much-id')
286
        create_tree.apply()        
287
        mangle_tree,root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
288
        bzrlib = mangle_tree.trans_id_tree_file_id('bzrlib-id')
289
        tests = mangle_tree.trans_id_tree_file_id('tests-id')
290
        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
291
        mangle_tree.adjust_path('selftest', bzrlib, tests)
292
        mangle_tree.adjust_path('blackbox.py', tests, test_too_much) 
293
        mangle_tree.set_executability(True, test_too_much)
294
        mangle_tree.apply()
295
296
    def test_both_rename3(self):
297
        create_tree,root = self.get_transform()
298
        tests = create_tree.new_directory('tests', root, 'tests-id')
299
        create_tree.new_file('test_too_much.py', tests, 'hello1', 
300
                             'test_too_much-id')
301
        create_tree.apply()        
302
        mangle_tree,root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
303
        tests = mangle_tree.trans_id_tree_file_id('tests-id')
304
        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
305
        mangle_tree.adjust_path('selftest', root, tests)
306
        mangle_tree.adjust_path('blackbox.py', tests, test_too_much) 
307
        mangle_tree.set_executability(True, test_too_much)
308
        mangle_tree.apply()
309
1534.7.48 by Aaron Bentley
Ensured we can move/rename dangling inventory entries
310
    def test_move_dangling_ie(self):
1534.7.59 by Aaron Bentley
Simplified tests
311
        create_tree, root = self.get_transform()
312
        # prepare tree
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
313
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
1534.7.59 by Aaron Bentley
Simplified tests
314
        create_tree.new_file('name1', root, 'hello1', 'name1')
315
        create_tree.apply()
316
        delete_contents, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
317
        file = delete_contents.trans_id_tree_file_id('name1')
1534.7.59 by Aaron Bentley
Simplified tests
318
        delete_contents.delete_contents(file)
319
        delete_contents.apply()
320
        move_id, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
321
        name1 = move_id.trans_id_tree_file_id('name1')
1534.7.59 by Aaron Bentley
Simplified tests
322
        newdir = move_id.new_directory('dir', root, 'newdir')
323
        move_id.adjust_path('name2', newdir, name1)
324
        move_id.apply()
1534.7.48 by Aaron Bentley
Ensured we can move/rename dangling inventory entries
325
        
1534.7.50 by Aaron Bentley
Detect duplicate inventory ids
326
    def test_replace_dangling_ie(self):
1534.7.59 by Aaron Bentley
Simplified tests
327
        create_tree, root = self.get_transform()
328
        # prepare tree
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
329
        root = create_tree.trans_id_tree_file_id('TREE_ROOT')
1534.7.59 by Aaron Bentley
Simplified tests
330
        create_tree.new_file('name1', root, 'hello1', 'name1')
331
        create_tree.apply()
332
        delete_contents = TreeTransform(self.wt)
333
        self.addCleanup(delete_contents.finalize)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
334
        file = delete_contents.trans_id_tree_file_id('name1')
1534.7.59 by Aaron Bentley
Simplified tests
335
        delete_contents.delete_contents(file)
336
        delete_contents.apply()
337
        delete_contents.finalize()
338
        replace = TreeTransform(self.wt)
339
        self.addCleanup(replace.finalize)
340
        name2 = replace.new_file('name2', root, 'hello2', 'name1')
341
        conflicts = replace.find_conflicts()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
342
        name1 = replace.trans_id_tree_file_id('name1')
1534.7.59 by Aaron Bentley
Simplified tests
343
        self.assertEqual(conflicts, [('duplicate id', name1, name2)])
344
        resolve_conflicts(replace)
345
        replace.apply()
1534.7.48 by Aaron Bentley
Ensured we can move/rename dangling inventory entries
346
1534.7.43 by abentley
Fixed some Windows bugs, introduced a conflicts bug
347
    def test_symlinks(self):
1534.7.45 by Aaron Bentley
Skipped symlink test more correctly
348
        if not has_symlinks():
349
            raise TestSkipped('Symlinks are not supported on this platform')
1534.7.59 by Aaron Bentley
Simplified tests
350
        transform,root = self.get_transform()
351
        oz_id = transform.new_directory('oz', root, 'oz-id')
352
        wizard = transform.new_symlink('wizard', oz_id, 'wizard-target', 
353
                                       'wizard-id')
354
        wiz_id = transform.create_path('wizard2', oz_id)
355
        transform.create_symlink('behind_curtain', wiz_id)
356
        transform.version_file('wiz-id2', wiz_id)            
1534.7.71 by abentley
All tests pass under Windows
357
        transform.set_executability(True, wiz_id)
358
        self.assertEqual(transform.find_conflicts(), 
359
                         [('non-file executability', wiz_id)])
360
        transform.set_executability(None, wiz_id)
1534.7.59 by Aaron Bentley
Simplified tests
361
        transform.apply()
362
        self.assertEqual(self.wt.path2id('oz/wizard'), 'wizard-id')
1534.7.100 by Aaron Bentley
Fixed path-relative test cases
363
        self.assertEqual(file_kind(self.wt.abspath('oz/wizard')), 'symlink')
364
        self.assertEqual(os.readlink(self.wt.abspath('oz/wizard2')), 
365
                         'behind_curtain')
366
        self.assertEqual(os.readlink(self.wt.abspath('oz/wizard')),
367
                         'wizard-target')
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
368
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
369
370
    def get_conflicted(self):
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
371
        create,root = self.get_transform()
372
        create.new_file('dorothy', root, 'dorothy', 'dorothy-id')
1534.7.61 by Aaron Bentley
Handled parent loops, missing parents, unversioned parents
373
        oz = create.new_directory('oz', root, 'oz-id')
374
        create.new_directory('emeraldcity', oz, 'emerald-id')
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
375
        create.apply()
376
        conflicts,root = self.get_transform()
1534.7.65 by Aaron Bentley
Text cleaup/docs
377
        # set up duplicate entry, duplicate id
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
378
        new_dorothy = conflicts.new_file('dorothy', root, 'dorothy', 
379
                                         'dorothy-id')
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
380
        old_dorothy = conflicts.trans_id_tree_file_id('dorothy-id')
381
        oz = conflicts.trans_id_tree_file_id('oz-id')
1534.7.65 by Aaron Bentley
Text cleaup/docs
382
        # set up missing, unversioned parent
383
        conflicts.delete_versioned(oz)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
384
        emerald = conflicts.trans_id_tree_file_id('emerald-id')
1534.7.65 by Aaron Bentley
Text cleaup/docs
385
        # set up parent loop
1534.7.61 by Aaron Bentley
Handled parent loops, missing parents, unversioned parents
386
        conflicts.adjust_path('emeraldcity', emerald, emerald)
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
387
        return conflicts, emerald, oz, old_dorothy, new_dorothy
388
389
    def test_conflict_resolution(self):
390
        conflicts, emerald, oz, old_dorothy, new_dorothy =\
391
            self.get_conflicted()
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
392
        resolve_conflicts(conflicts)
393
        self.assertEqual(conflicts.final_name(old_dorothy), 'dorothy.moved')
394
        self.assertIs(conflicts.final_file_id(old_dorothy), None)
395
        self.assertEqual(conflicts.final_name(new_dorothy), 'dorothy')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
396
        self.assertEqual(conflicts.final_file_id(new_dorothy), 'dorothy-id')
1534.7.64 by Aaron Bentley
Extra testing
397
        self.assertEqual(conflicts.final_parent(emerald), oz)
1534.7.63 by Aaron Bentley
Ensure transform can be applied after resolution
398
        conflicts.apply()
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
399
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
400
    def test_cook_conflicts(self):
401
        tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
402
        raw_conflicts = resolve_conflicts(tt)
403
        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
1534.7.171 by Aaron Bentley
Implemented stringifying filesystem conflicts
404
        duplicate = ('duplicate', 'Moved existing file to', 'dorothy.moved', 
405
                     None, 'dorothy', 'dorothy-id')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
406
        self.assertEqual(cooked_conflicts[0], duplicate)
407
        duplicate_id = ('duplicate id', 'Unversioned existing file', 
408
                        'dorothy.moved', None, 'dorothy', 'dorothy-id')
409
        self.assertEqual(cooked_conflicts[1], duplicate_id)
410
        missing_parent = ('missing parent', 'Not deleting', 'oz', 'oz-id')
411
        self.assertEqual(cooked_conflicts[2], missing_parent)
412
        unversioned_parent = ('unversioned parent', 
1534.7.171 by Aaron Bentley
Implemented stringifying filesystem conflicts
413
                              'Versioned directory', 'oz', 'oz-id')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
414
        self.assertEqual(cooked_conflicts[3], unversioned_parent)
415
        parent_loop = ('parent loop', 'Cancelled move', 'oz/emeraldcity', 
416
                       'emerald-id', 'oz/emeraldcity', 'emerald-id')
417
        self.assertEqual(cooked_conflicts[4], parent_loop)
418
        self.assertEqual(len(cooked_conflicts), 5)
419
        tt.finalize()
420
421
    def test_string_conflicts(self):
422
        tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
423
        raw_conflicts = resolve_conflicts(tt)
424
        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
425
        tt.finalize()
1534.7.171 by Aaron Bentley
Implemented stringifying filesystem conflicts
426
        conflicts_s = list(conflicts_strings(cooked_conflicts))
427
        self.assertEqual(len(cooked_conflicts), len(conflicts_s))
428
        self.assertEqual(conflicts_s[0], 'Conflict adding file dorothy.  '
429
                                         'Moved existing file to '
430
                                         'dorothy.moved.')
431
        self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy.  '
432
                                         'Unversioned existing file '
433
                                         'dorothy.moved.')
434
        self.assertEqual(conflicts_s[2], 'Conflict adding files to oz.  '
435
                                         'Not deleting.')
436
        self.assertEqual(conflicts_s[3], 'Conflict adding versioned files to '
437
                                         'oz.  Versioned directory.')
438
        self.assertEqual(conflicts_s[4], 'Conflict moving oz/emeraldcity into'
439
                                         ' oz/emeraldcity.  Cancelled move.')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
440
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
441
    def test_moving_versioned_directories(self):
442
        create, root = self.get_transform()
443
        kansas = create.new_directory('kansas', root, 'kansas-id')
444
        create.new_directory('house', kansas, 'house-id')
445
        create.new_directory('oz', root, 'oz-id')
446
        create.apply()
447
        cyclone, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
448
        oz = cyclone.trans_id_tree_file_id('oz-id')
449
        house = cyclone.trans_id_tree_file_id('house-id')
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
450
        cyclone.adjust_path('house', oz, house)
451
        cyclone.apply()
1534.7.66 by Aaron Bentley
Ensured we don't accidentally move the root directory
452
453
    def test_moving_root(self):
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
454
        create, root = self.get_transform()
455
        fun = create.new_directory('fun', root, 'fun-id')
456
        create.new_directory('sun', root, 'sun-id')
457
        create.new_directory('moon', root, 'moon')
458
        create.apply()
1534.7.66 by Aaron Bentley
Ensured we don't accidentally move the root directory
459
        transform, root = self.get_transform()
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
460
        transform.adjust_root_path('oldroot', fun)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
461
        new_root=transform.trans_id_tree_path('')
1534.7.69 by Aaron Bentley
Got real root moves working
462
        transform.version_file('new-root', new_root)
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
463
        transform.apply()
1534.7.93 by Aaron Bentley
Added text merge test
464
1534.7.114 by Aaron Bentley
Added file renaming test case
465
    def test_renames(self):
466
        create, root = self.get_transform()
467
        old = create.new_directory('old-parent', root, 'old-id')
468
        intermediate = create.new_directory('intermediate', old, 'im-id')
469
        myfile = create.new_file('myfile', intermediate, 'myfile-text',
470
                                 'myfile-id')
471
        create.apply()
472
        rename, root = self.get_transform()
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
473
        old = rename.trans_id_file_id('old-id')
1534.7.114 by Aaron Bentley
Added file renaming test case
474
        rename.adjust_path('new', root, old)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
475
        myfile = rename.trans_id_file_id('myfile-id')
1534.7.114 by Aaron Bentley
Added file renaming test case
476
        rename.set_executability(True, myfile)
477
        rename.apply()
478
1534.7.123 by Aaron Bentley
Fixed handling of unversioned files
479
    def test_find_interesting(self):
480
        create, root = self.get_transform()
481
        wt = create._tree
482
        create.new_file('vfile', root, 'myfile-text', 'myfile-id')
483
        create.new_file('uvfile', root, 'othertext')
484
        create.apply()
485
        self.assertEqual(find_interesting(wt, wt, ['vfile']),
486
                         set(['myfile-id']))
487
        self.assertRaises(NotVersionedError, find_interesting, wt, wt,
488
                          ['uvfile'])
489
1534.7.93 by Aaron Bentley
Added text merge test
490
491
class TransformGroup(object):
492
    def __init__(self, dirname):
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
493
        self.name = dirname
1534.7.93 by Aaron Bentley
Added text merge test
494
        os.mkdir(dirname)
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
495
        self.wt = BzrDir.create_standalone_workingtree(dirname)
496
        self.b = self.wt.branch
1534.7.93 by Aaron Bentley
Added text merge test
497
        self.tt = TreeTransform(self.wt)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
498
        self.root = self.tt.trans_id_tree_file_id(self.wt.get_root_id())
1534.7.93 by Aaron Bentley
Added text merge test
499
1534.7.95 by Aaron Bentley
Added more text merge tests
500
def conflict_text(tree, merge):
501
    template = '%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
502
    return template % ('<' * 7, tree, '=' * 7, merge, '>' * 7)
503
1534.7.93 by Aaron Bentley
Added text merge test
504
505
class TestTransformMerge(TestCaseInTempDir):
506
    def test_text_merge(self):
507
        base = TransformGroup("base")
508
        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
509
        base.tt.new_file('b', base.root, 'b1', 'b')
510
        base.tt.new_file('c', base.root, 'c', 'c')
511
        base.tt.new_file('d', base.root, 'd', 'd')
512
        base.tt.new_file('e', base.root, 'e', 'e')
513
        base.tt.new_file('f', base.root, 'f', 'f')
1534.7.96 by Aaron Bentley
Tested with BASE as directory
514
        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
515
        base.tt.new_directory('h', base.root, 'h')
1534.7.93 by Aaron Bentley
Added text merge test
516
        base.tt.apply()
517
        other = TransformGroup("other")
518
        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
519
        other.tt.new_file('b', other.root, 'b2', 'b')
520
        other.tt.new_file('c', other.root, 'c2', 'c')
521
        other.tt.new_file('d', other.root, 'd', 'd')
522
        other.tt.new_file('e', other.root, 'e2', 'e')
523
        other.tt.new_file('f', other.root, 'f', 'f')
1534.7.96 by Aaron Bentley
Tested with BASE as directory
524
        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
525
        other.tt.new_file('h', other.root, 'h\ni\nj\nk\n', 'h')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
526
        other.tt.new_file('i', other.root, 'h\ni\nj\nk\n', 'i')
1534.7.93 by Aaron Bentley
Added text merge test
527
        other.tt.apply()
528
        this = TransformGroup("this")
529
        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
530
        this.tt.new_file('b', this.root, 'b', 'b')
531
        this.tt.new_file('c', this.root, 'c', 'c')
532
        this.tt.new_file('d', this.root, 'd2', 'd')
533
        this.tt.new_file('e', this.root, 'e2', 'e')
534
        this.tt.new_file('f', this.root, 'f', 'f')
1534.7.96 by Aaron Bentley
Tested with BASE as directory
535
        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
536
        this.tt.new_file('h', this.root, '1\n2\n3\n4\n', 'h')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
537
        this.tt.new_file('i', this.root, '1\n2\n3\n4\n', 'i')
1534.7.93 by Aaron Bentley
Added text merge test
538
        this.tt.apply()
539
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.95 by Aaron Bentley
Added more text merge tests
540
        # textual merge
1534.7.93 by Aaron Bentley
Added text merge test
541
        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
542
        # three-way text conflict
543
        self.assertEqual(this.wt.get_file('b').read(), 
544
                         conflict_text('b', 'b2'))
545
        # OTHER wins
546
        self.assertEqual(this.wt.get_file('c').read(), 'c2')
547
        # THIS wins
548
        self.assertEqual(this.wt.get_file('d').read(), 'd2')
549
        # Ambigious clean merge
550
        self.assertEqual(this.wt.get_file('e').read(), 'e2')
551
        # No change
552
        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
553
        # Correct correct results when THIS == OTHER 
1534.7.96 by Aaron Bentley
Tested with BASE as directory
554
        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
555
        # Text conflict when THIS & OTHER are text and BASE is dir
556
        self.assertEqual(this.wt.get_file('h').read(), 
557
                         conflict_text('1\n2\n3\n4\n', 'h\ni\nj\nk\n'))
558
        self.assertEqual(this.wt.get_file_byname('h.THIS').read(),
559
                         '1\n2\n3\n4\n')
560
        self.assertEqual(this.wt.get_file_byname('h.OTHER').read(),
561
                         'h\ni\nj\nk\n')
562
        self.assertEqual(file_kind(this.wt.abspath('h.BASE')), 'directory')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
563
        self.assertEqual(this.wt.get_file('i').read(), 
564
                         conflict_text('1\n2\n3\n4\n', 'h\ni\nj\nk\n'))
565
        self.assertEqual(this.wt.get_file_byname('i.THIS').read(),
566
                         '1\n2\n3\n4\n')
567
        self.assertEqual(this.wt.get_file_byname('i.OTHER').read(),
568
                         'h\ni\nj\nk\n')
569
        self.assertEqual(os.path.exists(this.wt.abspath('i.BASE')), False)
1534.7.192 by Aaron Bentley
Record hashes produced by merges
570
        modified = ['a', 'b', 'c', 'h', 'i']
571
        merge_modified = this.wt.merge_modified()
572
        self.assertSubset(merge_modified, modified)
573
        self.assertEqual(len(merge_modified), len(modified))
574
        file(this.wt.id2abspath('a'), 'wb').write('booga')
575
        modified.pop(0)
576
        merge_modified = this.wt.merge_modified()
577
        self.assertSubset(merge_modified, modified)
578
        self.assertEqual(len(merge_modified), len(modified))
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
579
580
    def test_file_merge(self):
1534.7.153 by Aaron Bentley
Handled test cases involving symlinks
581
        if not has_symlinks():
582
            raise TestSkipped('Symlinks are not supported on this platform')
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
583
        base = TransformGroup("BASE")
584
        this = TransformGroup("THIS")
585
        other = TransformGroup("OTHER")
586
        for tg in this, base, other:
587
            tg.tt.new_directory('a', tg.root, 'a')
588
            tg.tt.new_symlink('b', tg.root, 'b', 'b')
589
            tg.tt.new_file('c', tg.root, 'c', 'c')
590
            tg.tt.new_symlink('d', tg.root, tg.name, 'd')
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
591
        targets = ((base, 'base-e', 'base-f', None, None), 
592
                   (this, 'other-e', 'this-f', 'other-g', 'this-h'), 
593
                   (other, 'other-e', None, 'other-g', 'other-h'))
594
        for tg, e_target, f_target, g_target, h_target in targets:
595
            for link, target in (('e', e_target), ('f', f_target), 
596
                                 ('g', g_target), ('h', h_target)):
597
                if target is not None:
598
                    tg.tt.new_symlink(link, tg.root, target, link)
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
599
600
        for tg in this, base, other:
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
601
            tg.tt.apply()
602
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
603
        self.assertIs(os.path.isdir(this.wt.abspath('a')), True)
604
        self.assertIs(os.path.islink(this.wt.abspath('b')), True)
605
        self.assertIs(os.path.isfile(this.wt.abspath('c')), True)
606
        for suffix in ('THIS', 'BASE', 'OTHER'):
607
            self.assertEqual(os.readlink(this.wt.abspath('d.'+suffix)), suffix)
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
608
        self.assertIs(os.path.lexists(this.wt.abspath('d')), False)
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
609
        self.assertEqual(this.wt.id2path('d'), 'd.OTHER')
610
        self.assertEqual(this.wt.id2path('f'), 'f.THIS')
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
611
        self.assertEqual(os.readlink(this.wt.abspath('e')), 'other-e')
612
        self.assertIs(os.path.lexists(this.wt.abspath('e.THIS')), False)
613
        self.assertIs(os.path.lexists(this.wt.abspath('e.OTHER')), False)
614
        self.assertIs(os.path.lexists(this.wt.abspath('e.BASE')), False)
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
615
        self.assertIs(os.path.lexists(this.wt.abspath('g')), True)
616
        self.assertIs(os.path.lexists(this.wt.abspath('g.BASE')), False)
617
        self.assertIs(os.path.lexists(this.wt.abspath('h')), False)
618
        self.assertIs(os.path.lexists(this.wt.abspath('h.BASE')), False)
619
        self.assertIs(os.path.lexists(this.wt.abspath('h.THIS')), True)
620
        self.assertIs(os.path.lexists(this.wt.abspath('h.OTHER')), True)
1534.7.105 by Aaron Bentley
Got merge with rename working
621
622
    def test_filename_merge(self):
623
        base = TransformGroup("BASE")
624
        this = TransformGroup("THIS")
625
        other = TransformGroup("OTHER")
626
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a') 
627
                                   for t in [base, this, other]]
628
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b') 
629
                                   for t in [base, this, other]]
630
        base.tt.new_directory('c', base_a, 'c')
631
        this.tt.new_directory('c1', this_a, 'c')
632
        other.tt.new_directory('c', other_b, 'c')
633
634
        base.tt.new_directory('d', base_a, 'd')
635
        this.tt.new_directory('d1', this_b, 'd')
636
        other.tt.new_directory('d', other_a, 'd')
637
638
        base.tt.new_directory('e', base_a, 'e')
639
        this.tt.new_directory('e', this_a, 'e')
640
        other.tt.new_directory('e1', other_b, 'e')
641
642
        base.tt.new_directory('f', base_a, 'f')
643
        this.tt.new_directory('f1', this_b, 'f')
644
        other.tt.new_directory('f1', other_b, 'f')
645
646
        for tg in [this, base, other]:
647
            tg.tt.apply()
648
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.176 by abentley
Fixed up tests for Windows
649
        self.assertEqual(this.wt.id2path('c'), pathjoin('b/c1'))
650
        self.assertEqual(this.wt.id2path('d'), pathjoin('b/d1'))
651
        self.assertEqual(this.wt.id2path('e'), pathjoin('b/e1'))
652
        self.assertEqual(this.wt.id2path('f'), pathjoin('b/f1'))
1534.7.105 by Aaron Bentley
Got merge with rename working
653
654
    def test_filename_merge_conflicts(self):
655
        base = TransformGroup("BASE")
656
        this = TransformGroup("THIS")
657
        other = TransformGroup("OTHER")
658
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a') 
659
                                   for t in [base, this, other]]
660
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b') 
661
                                   for t in [base, this, other]]
662
663
        base.tt.new_file('g', base_a, 'g', 'g')
664
        other.tt.new_file('g1', other_b, 'g1', 'g')
665
666
        base.tt.new_file('h', base_a, 'h', 'h')
667
        this.tt.new_file('h1', this_b, 'h1', 'h')
668
669
        base.tt.new_file('i', base.root, 'i', 'i')
1534.7.153 by Aaron Bentley
Handled test cases involving symlinks
670
        other.tt.new_directory('i1', this_b, 'i')
1534.7.105 by Aaron Bentley
Got merge with rename working
671
672
        for tg in [this, base, other]:
673
            tg.tt.apply()
674
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
675
1534.7.176 by abentley
Fixed up tests for Windows
676
        self.assertEqual(this.wt.id2path('g'), pathjoin('b/g1.OTHER'))
1534.7.105 by Aaron Bentley
Got merge with rename working
677
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.BASE')), True)
678
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.THIS')), False)
1534.7.176 by abentley
Fixed up tests for Windows
679
        self.assertEqual(this.wt.id2path('h'), pathjoin('b/h1.THIS'))
1534.7.105 by Aaron Bentley
Got merge with rename working
680
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.BASE')), True)
681
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.OTHER')), False)
1534.7.176 by abentley
Fixed up tests for Windows
682
        self.assertEqual(this.wt.id2path('i'), pathjoin('b/i1.OTHER'))
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
683
684
class TestBuildTree(TestCaseInTempDir):
685
    def test_build_tree(self):
686
        if not has_symlinks():
687
            raise TestSkipped('Test requires symlink support')
688
        os.mkdir('a')
689
        a = BzrDir.create_standalone_workingtree('a')
690
        os.mkdir('a/foo')
691
        file('a/foo/bar', 'wb').write('contents')
692
        os.symlink('a/foo/bar', 'a/foo/baz')
693
        a.add(['foo', 'foo/bar', 'foo/baz'])
694
        a.commit('initial commit')
695
        b = BzrDir.create_standalone_workingtree('b')
696
        build_tree(a.basis_tree(), b)
697
        self.assertIs(os.path.isdir('b/foo'), True)
698
        self.assertEqual(file('b/foo/bar', 'rb').read(), "contents")
699
        self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')