/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.1 by Vincent Ladeuil
Fix assert_ being deprecated by using assertTrue.
1
# Copyright (C) 2006-2012, 2016 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
16
5582.8.1 by Martin
Make bt.test_transform.TestTreeTransform.test_rename_fails not care about the exact stringification of the exception instance
17
import errno
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
18
import os
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
19
import sys
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
20
import time
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
21
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
22
from .. import (
2694.5.4 by Jelmer Vernooij
Move bzrlib.util.bencode to bzrlib._bencode_py.
23
    bencode,
2090.2.1 by Martin Pool
Fix some code which relies on assertions and breaks under python -O
24
    errors,
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
25
    filters,
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
26
    generate_ids,
3199.1.4 by Vincent Ladeuil
Fix 16 leaked tmp dirs. Probably indicates a lock handling problem with TransformPreview
27
    osutils,
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
28
    revision as _mod_revision,
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
29
    rules,
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
30
    tests,
5409.1.17 by Vincent Ladeuil
Ensures we fallback to the default policy if a bogus one is specified.
31
    trace,
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
32
    transform,
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
33
    urlutils,
34
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
35
from ..conflicts import (
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
36
    DeletingParent,
37
    DuplicateEntry,
38
    DuplicateID,
39
    MissingParent,
40
    NonDirectoryParent,
41
    ParentLoop,
42
    UnversionedParent,
43
)
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
44
from ..controldir import ControlDir
45
from ..diff import show_diff_trees
46
from ..errors import (
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
47
    DuplicateKey,
48
    ExistingLimbo,
49
    ExistingPendingDeletion,
50
    ImmortalLimbo,
51
    ImmortalPendingDeletion,
52
    LockError,
53
    MalformedTransform,
54
    ReusingTransform,
55
)
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
56
from ..osutils import (
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
57
    file_kind,
58
    pathjoin,
59
)
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
60
from ..merge import Merge3Merger, Merger
61
from ..mutabletree import MutableTree
62
from ..sixish import (
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
63
    BytesIO,
6973.6.2 by Jelmer Vernooij
Fix more tests.
64
    text_type,
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
65
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
66
from . import (
5050.44.1 by Vincent Ladeuil
One more fixed test related to bug #646133
67
    features,
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
68
    TestCaseInTempDir,
69
    TestSkipped,
70
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
71
from .features import (
3136.1.1 by Aaron Bentley
Add support for hardlinks to TreeTransform
72
    HardlinkFeature,
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
73
    SymlinkFeature,
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
74
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
75
from ..transform import (
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
76
    build_tree,
77
    create_from_tree,
78
    cook_conflicts,
79
    _FileMover,
80
    FinalPaths,
81
    resolve_conflicts,
82
    resolve_checkout,
83
    ROOT_PARENT,
84
    TransformPreview,
85
    TreeTransform,
86
)
0.13.13 by Aaron Bentley
Add direct test of serialization records
87
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
88
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
89
class TestTreeTransform(tests.TestCaseWithTransport):
1740.2.4 by Aaron Bentley
Update transform tests and docs
90
1534.7.59 by Aaron Bentley
Simplified tests
91
    def setUp(self):
92
        super(TestTreeTransform, self).setUp()
6437.14.2 by Jelmer Vernooij
Run subtree tests with development-subtree rather than deprecated dirstate-with-subtree.
93
        self.wt = self.make_branch_and_tree('.', format='development-subtree')
1534.7.161 by Aaron Bentley
Used appropriate control_files
94
        os.chdir('..')
1534.7.59 by Aaron Bentley
Simplified tests
95
96
    def get_transform(self):
97
        transform = TreeTransform(self.wt)
3453.2.7 by Aaron Bentley
Remove test kipple
98
        self.addCleanup(transform.finalize)
1731.1.33 by Aaron Bentley
Revert no-special-root changes
99
        return transform, transform.root
1534.7.59 by Aaron Bentley
Simplified tests
100
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
101
    def get_transform_for_sha1_test(self):
102
        trans, root = self.get_transform()
103
        self.wt.lock_tree_write()
104
        self.addCleanup(self.wt.unlock)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
105
        contents = [b'just some content\n']
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
106
        sha1 = osutils.sha_strings(contents)
107
        # Roll back the clock
108
        trans._creation_mtime = time.time() - 20.0
109
        return trans, root, contents, sha1
110
1534.7.162 by Aaron Bentley
Handle failures creating/deleting the Limbo directory
111
    def test_existing_limbo(self):
112
        transform, root = self.get_transform()
2733.2.6 by Aaron Bentley
Make TreeTransform commits rollbackable
113
        limbo_name = transform._limbodir
114
        deletion_path = transform._deletiondir
1534.7.176 by abentley
Fixed up tests for Windows
115
        os.mkdir(pathjoin(limbo_name, 'hehe'))
1534.7.162 by Aaron Bentley
Handle failures creating/deleting the Limbo directory
116
        self.assertRaises(ImmortalLimbo, transform.apply)
117
        self.assertRaises(LockError, self.wt.unlock)
118
        self.assertRaises(ExistingLimbo, self.get_transform)
119
        self.assertRaises(LockError, self.wt.unlock)
1534.7.176 by abentley
Fixed up tests for Windows
120
        os.rmdir(pathjoin(limbo_name, 'hehe'))
1534.7.162 by Aaron Bentley
Handle failures creating/deleting the Limbo directory
121
        os.rmdir(limbo_name)
2733.2.6 by Aaron Bentley
Make TreeTransform commits rollbackable
122
        os.rmdir(deletion_path)
1534.7.162 by Aaron Bentley
Handle failures creating/deleting the Limbo directory
123
        transform, root = self.get_transform()
124
        transform.apply()
1534.7.59 by Aaron Bentley
Simplified tests
125
2733.2.11 by Aaron Bentley
Detect irregularities with the pending-deletion directory
126
    def test_existing_pending_deletion(self):
127
        transform, root = self.get_transform()
128
        deletion_path = self._limbodir = urlutils.local_path_from_url(
3407.2.8 by Martin Pool
Deprecate LockableFiles.controlfilename
129
            transform._tree._transport.abspath('pending-deletion'))
2733.2.11 by Aaron Bentley
Detect irregularities with the pending-deletion directory
130
        os.mkdir(pathjoin(deletion_path, 'blocking-directory'))
131
        self.assertRaises(ImmortalPendingDeletion, transform.apply)
132
        self.assertRaises(LockError, self.wt.unlock)
133
        self.assertRaises(ExistingPendingDeletion, self.get_transform)
134
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
135
    def test_build(self):
3034.2.1 by Aaron Bentley
Fix is_executable tests for win32
136
        transform, root = self.get_transform()
137
        self.wt.lock_tree_write()
138
        self.addCleanup(self.wt.unlock)
1534.7.59 by Aaron Bentley
Simplified tests
139
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
140
        imaginary_id = transform.trans_id_tree_path('imaginary')
1534.10.32 by Aaron Bentley
Test and fix case where name has trailing slash
141
        imaginary_id2 = transform.trans_id_tree_path('imaginary/')
142
        self.assertEqual(imaginary_id, imaginary_id2)
4597.9.7 by Vincent Ladeuil
transform.final_kind() now returns None instead of raising NoSuchFile.
143
        self.assertEqual(root, transform.get_tree_parent(imaginary_id))
144
        self.assertEqual('directory', transform.final_kind(root))
145
        self.assertEqual(self.wt.get_root_id(), transform.final_file_id(root))
1534.7.59 by Aaron Bentley
Simplified tests
146
        trans_id = transform.create_path('name', root)
147
        self.assertIs(transform.final_file_id(trans_id), None)
4597.9.7 by Vincent Ladeuil
transform.final_kind() now returns None instead of raising NoSuchFile.
148
        self.assertIs(None, transform.final_kind(trans_id))
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
149
        transform.create_file([b'contents'], trans_id)
1534.7.59 by Aaron Bentley
Simplified tests
150
        transform.set_executability(True, trans_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
151
        transform.version_file(b'my_pretties', trans_id)
1534.7.59 by Aaron Bentley
Simplified tests
152
        self.assertRaises(DuplicateKey, transform.version_file,
6973.10.1 by Jelmer Vernooij
Fix some tests.
153
                          b'my_pretties', trans_id)
154
        self.assertEqual(transform.final_file_id(trans_id), b'my_pretties')
1534.7.59 by Aaron Bentley
Simplified tests
155
        self.assertEqual(transform.final_parent(trans_id), root)
156
        self.assertIs(transform.final_parent(root), ROOT_PARENT)
157
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
158
        oz_id = transform.create_path('oz', root)
159
        transform.create_directory(oz_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
160
        transform.version_file(b'ozzie', oz_id)
1534.7.59 by Aaron Bentley
Simplified tests
161
        trans_id2 = transform.create_path('name2', root)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
162
        transform.create_file([b'contents'], trans_id2)
1534.7.59 by Aaron Bentley
Simplified tests
163
        transform.set_executability(False, trans_id2)
6973.10.1 by Jelmer Vernooij
Fix some tests.
164
        transform.version_file(b'my_pretties2', trans_id2)
1534.7.191 by Aaron Bentley
Got transform.apply to list modified paths
165
        modified_paths = transform.apply().modified_paths
6973.10.1 by Jelmer Vernooij
Fix some tests.
166
        with self.wt.get_file('name') as f:
167
            self.assertEqual(b'contents', f.read())
168
        self.assertEqual(self.wt.path2id('name'), b'my_pretties')
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
169
        self.assertIs(self.wt.is_executable('name'), True)
170
        self.assertIs(self.wt.is_executable('name2'), False)
1534.7.100 by Aaron Bentley
Fixed path-relative test cases
171
        self.assertEqual('directory', file_kind(self.wt.abspath('oz')))
1534.7.191 by Aaron Bentley
Got transform.apply to list modified paths
172
        self.assertEqual(len(modified_paths), 3)
6883.7.6 by Jelmer Vernooij
Remove uses of id2path.
173
        tree_mod_paths = [self.wt.abspath(self.wt.id2path(f)) for f in
6973.10.1 by Jelmer Vernooij
Fix some tests.
174
                          (b'ozzie', b'my_pretties', b'my_pretties2')]
1534.7.191 by Aaron Bentley
Got transform.apply to list modified paths
175
        self.assertSubset(tree_mod_paths, modified_paths)
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
176
        # is it safe to finalize repeatedly?
177
        transform.finalize()
1534.7.59 by Aaron Bentley
Simplified tests
178
        transform.finalize()
1534.7.2 by Aaron Bentley
Added convenience function
179
5752.3.6 by John Arbash Meinel
More direct tests of TreeTransform behavior wrt _observed_sha1s
180
    def test_apply_informs_tree_of_observed_sha1(self):
181
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
6973.10.1 by Jelmer Vernooij
Fix some tests.
182
        trans_id = trans.new_file('file1', root, contents, file_id=b'file1-id',
5752.3.6 by John Arbash Meinel
More direct tests of TreeTransform behavior wrt _observed_sha1s
183
                                  sha1=sha1)
184
        calls = []
185
        orig = self.wt._observed_sha1
186
        def _observed_sha1(*args):
187
            calls.append(args)
188
            orig(*args)
189
        self.wt._observed_sha1 = _observed_sha1
190
        trans.apply()
191
        self.assertEqual([(None, 'file1', trans._observed_sha1s[trans_id])],
192
                         calls)
193
5752.3.1 by John Arbash Meinel
Merge up from 2.4-windows-lfstat
194
    def test_create_file_caches_sha1(self):
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
195
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
5752.3.1 by John Arbash Meinel
Merge up from 2.4-windows-lfstat
196
        trans_id = trans.create_path('file1', root)
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
197
        trans.create_file(contents, trans_id, sha1=sha1)
5752.3.1 by John Arbash Meinel
Merge up from 2.4-windows-lfstat
198
        st_val = osutils.lstat(trans._limbo_name(trans_id))
199
        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
200
        self.assertEqual(o_sha1, sha1)
201
        self.assertEqualStat(o_st_val, st_val)
202
203
    def test__apply_insertions_updates_sha1(self):
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
204
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
5752.3.1 by John Arbash Meinel
Merge up from 2.4-windows-lfstat
205
        trans_id = trans.create_path('file1', root)
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
206
        trans.create_file(contents, trans_id, sha1=sha1)
5752.3.1 by John Arbash Meinel
Merge up from 2.4-windows-lfstat
207
        st_val = osutils.lstat(trans._limbo_name(trans_id))
208
        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
209
        self.assertEqual(o_sha1, sha1)
210
        self.assertEqualStat(o_st_val, st_val)
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
211
        creation_mtime = trans._creation_mtime + 10.0
5752.3.1 by John Arbash Meinel
Merge up from 2.4-windows-lfstat
212
        # We fake a time difference from when the file was created until now it
213
        # is being renamed by using os.utime. Note that the change we actually
214
        # want to see is the real ctime change from 'os.rename()', but as long
215
        # as we observe a new stat value, we should be fine.
216
        os.utime(trans._limbo_name(trans_id), (creation_mtime, creation_mtime))
217
        trans.apply()
218
        new_st_val = osutils.lstat(self.wt.abspath('file1'))
219
        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
220
        self.assertEqual(o_sha1, sha1)
221
        self.assertEqualStat(o_st_val, new_st_val)
222
        self.assertNotEqual(st_val.st_mtime, new_st_val.st_mtime)
223
5752.3.4 by John Arbash Meinel
Add new_file(sha1=XXX) and pass that down to create_file.
224
    def test_new_file_caches_sha1(self):
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
225
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
6973.10.1 by Jelmer Vernooij
Fix some tests.
226
        trans_id = trans.new_file('file1', root, contents, file_id=b'file1-id',
5752.3.4 by John Arbash Meinel
Add new_file(sha1=XXX) and pass that down to create_file.
227
                                  sha1=sha1)
228
        st_val = osutils.lstat(trans._limbo_name(trans_id))
229
        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
230
        self.assertEqual(o_sha1, sha1)
231
        self.assertEqualStat(o_st_val, st_val)
232
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
233
    def test_cancel_creation_removes_observed_sha1(self):
234
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
6973.10.1 by Jelmer Vernooij
Fix some tests.
235
        trans_id = trans.new_file('file1', root, contents, file_id=b'file1-id',
5752.3.5 by John Arbash Meinel
Refactor tests into a common helper.
236
                                  sha1=sha1)
237
        self.assertTrue(trans_id in trans._observed_sha1s)
238
        trans.cancel_creation(trans_id)
239
        self.assertFalse(trans_id in trans._observed_sha1s)
240
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
241
    def test_create_files_same_timestamp(self):
242
        transform, root = self.get_transform()
243
        self.wt.lock_tree_write()
244
        self.addCleanup(self.wt.unlock)
245
        # Roll back the clock, so that we know everything is being set to the
246
        # exact time
4934.1.10 by John Arbash Meinel
Rework the tests a bit.
247
        transform._creation_mtime = creation_mtime = time.time() - 20.0
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
248
        transform.create_file([b'content-one'],
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
249
                              transform.create_path('one', root))
250
        time.sleep(1) # *ugly*
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
251
        transform.create_file([b'content-two'],
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
252
                              transform.create_path('two', root))
253
        transform.apply()
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
254
        fo, st1 = self.wt.get_file_with_stat('one', filtered=False)
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
255
        fo.close()
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
256
        fo, st2 = self.wt.get_file_with_stat('two', filtered=False)
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
257
        fo.close()
4934.2.2 by Martin
Rearrange osutils.fset_mtime tests a little and make them robust on FAT filesystems
258
        # We only guarantee 2s resolution
4934.1.11 by John Arbash Meinel
2 => 2.0 because it looks better.
259
        self.assertTrue(abs(creation_mtime - st1.st_mtime) < 2.0,
4934.1.10 by John Arbash Meinel
Rework the tests a bit.
260
            "%s != %s within 2 seconds" % (creation_mtime, st1.st_mtime))
4934.1.6 by John Arbash Meinel
It turns out that with os/python/C buffering, we need to flush
261
        # But if we have more than that, all files should get the same result
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
262
        self.assertEqual(st1.st_mtime, st2.st_mtime)
263
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
264
    def test_change_root_id(self):
265
        transform, root = self.get_transform()
6855.4.1 by Jelmer Vernooij
Yet more bees.
266
        self.assertNotEqual(b'new-root-id', self.wt.get_root_id())
267
        transform.new_directory('', ROOT_PARENT, b'new-root-id')
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
268
        transform.delete_contents(root)
269
        transform.unversion_file(root)
270
        transform.fixup_new_roots()
271
        transform.apply()
6855.4.1 by Jelmer Vernooij
Yet more bees.
272
        self.assertEqual(b'new-root-id', self.wt.get_root_id())
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
273
274
    def test_change_root_id_add_files(self):
275
        transform, root = self.get_transform()
6855.4.1 by Jelmer Vernooij
Yet more bees.
276
        self.assertNotEqual(b'new-root-id', self.wt.get_root_id())
277
        new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
6973.10.1 by Jelmer Vernooij
Fix some tests.
278
        transform.new_file('file', new_trans_id, [b'new-contents\n'],
279
                           b'new-file-id')
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
280
        transform.delete_contents(root)
281
        transform.unversion_file(root)
282
        transform.fixup_new_roots()
283
        transform.apply()
6855.4.1 by Jelmer Vernooij
Yet more bees.
284
        self.assertEqual(b'new-root-id', self.wt.get_root_id())
285
        self.assertEqual(b'new-file-id', self.wt.path2id('file'))
6973.10.1 by Jelmer Vernooij
Fix some tests.
286
        self.assertFileEqual(b'new-contents\n', self.wt.abspath('file'))
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
287
288
    def test_add_two_roots(self):
289
        transform, root = self.get_transform()
6855.4.1 by Jelmer Vernooij
Yet more bees.
290
        new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
291
        new_trans_id = transform.new_directory('', ROOT_PARENT, b'alt-root-id')
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
292
        self.assertRaises(ValueError, transform.fixup_new_roots)
293
6011.1.1 by Aaron Bentley
Merging an unrelated tree retains root.
294
    def test_retain_existing_root(self):
295
        tt, root = self.get_transform()
296
        with tt:
6855.4.1 by Jelmer Vernooij
Yet more bees.
297
            tt.new_directory('', ROOT_PARENT, b'new-root-id')
6011.1.1 by Aaron Bentley
Merging an unrelated tree retains root.
298
            tt.fixup_new_roots()
6855.4.1 by Jelmer Vernooij
Yet more bees.
299
            self.assertNotEqual(b'new-root-id', tt.final_file_id(tt.root))
6011.1.1 by Aaron Bentley
Merging an unrelated tree retains root.
300
301
    def test_retain_existing_root_added_file(self):
302
        tt, root = self.get_transform()
6855.4.1 by Jelmer Vernooij
Yet more bees.
303
        new_trans_id = tt.new_directory('', ROOT_PARENT, b'new-root-id')
304
        child = tt.new_directory('child', new_trans_id, b'child-id')
6011.1.1 by Aaron Bentley
Merging an unrelated tree retains root.
305
        tt.fixup_new_roots()
306
        self.assertEqual(tt.root, tt.final_parent(child))
307
5954.4.7 by Aaron Bentley
Add test for unversioned roots.
308
    def test_add_unversioned_root(self):
309
        transform, root = self.get_transform()
310
        new_trans_id = transform.new_directory('', ROOT_PARENT, None)
6011.1.1 by Aaron Bentley
Merging an unrelated tree retains root.
311
        transform.delete_contents(transform.root)
5954.4.7 by Aaron Bentley
Add test for unversioned roots.
312
        transform.fixup_new_roots()
5954.4.11 by Aaron Bentley
Eschew testtools.testcase.ExpectedException from too-new testtools.
313
        self.assertNotIn(transform.root, transform._new_id)
5954.4.7 by Aaron Bentley
Add test for unversioned roots.
314
5993.2.3 by Jelmer Vernooij
Update NEWS, consistently use require_tree_root as argument everywhere.
315
    def test_remove_root_fixup(self):
316
        transform, root = self.get_transform()
317
        old_root_id = self.wt.get_root_id()
6855.4.1 by Jelmer Vernooij
Yet more bees.
318
        self.assertNotEqual(b'new-root-id', old_root_id)
5993.2.3 by Jelmer Vernooij
Update NEWS, consistently use require_tree_root as argument everywhere.
319
        transform.delete_contents(root)
320
        transform.unversion_file(root)
5993.2.4 by Jelmer Vernooij
Remove feature flag.
321
        transform.fixup_new_roots()
5993.2.3 by Jelmer Vernooij
Update NEWS, consistently use require_tree_root as argument everywhere.
322
        transform.apply()
323
        self.assertEqual(old_root_id, self.wt.get_root_id())
324
325
        transform, root = self.get_transform()
6855.4.1 by Jelmer Vernooij
Yet more bees.
326
        new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
327
        new_trans_id = transform.new_directory('', ROOT_PARENT, b'alt-root-id')
5993.2.3 by Jelmer Vernooij
Update NEWS, consistently use require_tree_root as argument everywhere.
328
        self.assertRaises(ValueError, transform.fixup_new_roots)
329
6024.1.1 by Aaron Bentley
Move empty-tree prevention into TreeTransform.apply.
330
    def test_fixup_new_roots_permits_empty_tree(self):
331
        transform, root = self.get_transform()
332
        transform.delete_contents(root)
333
        transform.unversion_file(root)
334
        transform.fixup_new_roots()
335
        self.assertIs(None, transform.final_kind(root))
336
        self.assertIs(None, transform.final_file_id(root))
337
5954.4.1 by Aaron Bentley
Never attempt to delete the tree root.
338
    def test_apply_retains_root_directory(self):
339
        # Do not attempt to delete the physical root directory, because that
340
        # is impossible.
341
        transform, root = self.get_transform()
342
        with transform:
343
            transform.delete_contents(root)
5954.4.12 by Aaron Bentley
Eschew more ExpectedException.
344
            e = self.assertRaises(AssertionError, self.assertRaises,
345
                                  errors.TransformRenameFailed,
346
                                  transform.apply)
347
        self.assertContainsRe('TransformRenameFailed not raised', str(e))
5954.4.1 by Aaron Bentley
Never attempt to delete the tree root.
348
6024.1.1 by Aaron Bentley
Move empty-tree prevention into TreeTransform.apply.
349
    def test_apply_retains_file_id(self):
350
        transform, root = self.get_transform()
351
        old_root_id = transform.tree_file_id(root)
352
        transform.unversion_file(root)
353
        transform.apply()
354
        self.assertEqual(old_root_id, self.wt.get_root_id())
355
3136.1.1 by Aaron Bentley
Add support for hardlinks to TreeTransform
356
    def test_hardlink(self):
357
        self.requireFeature(HardlinkFeature)
358
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
359
        transform.new_file('file1', root, [b'contents'])
3136.1.1 by Aaron Bentley
Add support for hardlinks to TreeTransform
360
        transform.apply()
361
        target = self.make_branch_and_tree('target')
362
        target_transform = TreeTransform(target)
363
        trans_id = target_transform.create_path('file1', target_transform.root)
364
        target_transform.create_hardlink(self.wt.abspath('file1'), trans_id)
365
        target_transform.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
366
        self.assertPathExists('target/file1')
3136.1.1 by Aaron Bentley
Add support for hardlinks to TreeTransform
367
        source_stat = os.stat(self.wt.abspath('file1'))
368
        target_stat = os.stat('target/file1')
369
        self.assertEqual(source_stat, target_stat)
370
1534.7.2 by Aaron Bentley
Added convenience function
371
    def test_convenience(self):
1534.7.59 by Aaron Bentley
Simplified tests
372
        transform, root = self.get_transform()
3034.2.1 by Aaron Bentley
Fix is_executable tests for win32
373
        self.wt.lock_tree_write()
374
        self.addCleanup(self.wt.unlock)
6973.10.1 by Jelmer Vernooij
Fix some tests.
375
        trans_id = transform.new_file('name', root, [b'contents'],
376
                                      b'my_pretties', True)
6973.13.2 by Jelmer Vernooij
Fix some more tests.
377
        oz = transform.new_directory('oz', root, b'oz-id')
6973.10.1 by Jelmer Vernooij
Fix some tests.
378
        dorothy = transform.new_directory('dorothy', oz, b'dorothy-id')
379
        toto = transform.new_file('toto', dorothy, [b'toto-contents'],
380
                                  b'toto-id', False)
1534.7.59 by Aaron Bentley
Simplified tests
381
382
        self.assertEqual(len(transform.find_conflicts()), 0)
383
        transform.apply()
384
        self.assertRaises(ReusingTransform, transform.find_conflicts)
6973.7.5 by Jelmer Vernooij
s/file/open.
385
        with open(self.wt.abspath('name'), 'r') as f:
386
            self.assertEqual('contents', f.read())
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
387
        self.assertEqual(self.wt.path2id('name'), b'my_pretties')
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
388
        self.assertIs(self.wt.is_executable('name'), True)
6973.10.1 by Jelmer Vernooij
Fix some tests.
389
        self.assertEqual(self.wt.path2id('oz'), b'oz-id')
390
        self.assertEqual(self.wt.path2id('oz/dorothy'), b'dorothy-id')
391
        self.assertEqual(self.wt.path2id('oz/dorothy/toto'), b'toto-id')
1534.7.59 by Aaron Bentley
Simplified tests
392
6973.10.1 by Jelmer Vernooij
Fix some tests.
393
        self.assertEqual(b'toto-contents',
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
394
                         self.wt.get_file('oz/dorothy/toto').read())
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
395
        self.assertIs(self.wt.is_executable('oz/dorothy/toto'), False)
1534.7.6 by Aaron Bentley
Added conflict handling
396
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
397
    def test_tree_reference(self):
398
        transform, root = self.get_transform()
399
        tree = transform._tree
6973.13.2 by Jelmer Vernooij
Fix some more tests.
400
        trans_id = transform.new_directory('reference', root, b'subtree-id')
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
401
        transform.set_tree_reference(b'subtree-revision', trans_id)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
402
        transform.apply()
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
403
        tree.lock_read()
404
        self.addCleanup(tree.unlock)
6973.13.2 by Jelmer Vernooij
Fix some more tests.
405
        self.assertEqual(b'subtree-revision',
406
                         tree.root_inventory.get_entry(b'subtree-id').reference_revision)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
407
1534.7.6 by Aaron Bentley
Added conflict handling
408
    def test_conflicts(self):
1534.7.59 by Aaron Bentley
Simplified tests
409
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
410
        trans_id = transform.new_file('name', root, [b'contents'],
411
                                      b'my_pretties')
1534.7.59 by Aaron Bentley
Simplified tests
412
        self.assertEqual(len(transform.find_conflicts()), 0)
6973.10.1 by Jelmer Vernooij
Fix some tests.
413
        trans_id2 = transform.new_file('name', root, [b'Crontents'], b'toto')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
414
        self.assertEqual(transform.find_conflicts(),
1534.7.59 by Aaron Bentley
Simplified tests
415
                         [('duplicate', trans_id, trans_id2, 'name')])
416
        self.assertRaises(MalformedTransform, transform.apply)
417
        transform.adjust_path('name', trans_id, trans_id2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
418
        self.assertEqual(transform.find_conflicts(),
1534.7.59 by Aaron Bentley
Simplified tests
419
                         [('non-directory parent', trans_id)])
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
420
        tinman_id = transform.trans_id_tree_path('tinman')
1534.7.59 by Aaron Bentley
Simplified tests
421
        transform.adjust_path('name', tinman_id, trans_id2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
422
        self.assertEqual(transform.find_conflicts(),
423
                         [('unversioned parent', tinman_id),
1534.7.59 by Aaron Bentley
Simplified tests
424
                          ('missing parent', tinman_id)])
425
        lion_id = transform.create_path('lion', root)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
426
        self.assertEqual(transform.find_conflicts(),
427
                         [('unversioned parent', tinman_id),
1534.7.59 by Aaron Bentley
Simplified tests
428
                          ('missing parent', tinman_id)])
429
        transform.adjust_path('name', lion_id, trans_id2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
430
        self.assertEqual(transform.find_conflicts(),
1534.7.59 by Aaron Bentley
Simplified tests
431
                         [('unversioned parent', lion_id),
432
                          ('missing parent', lion_id)])
433
        transform.version_file("Courage", lion_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
434
        self.assertEqual(transform.find_conflicts(),
435
                         [('missing parent', lion_id),
1534.7.59 by Aaron Bentley
Simplified tests
436
                          ('versioning no contents', lion_id)])
437
        transform.adjust_path('name2', root, trans_id2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
438
        self.assertEqual(transform.find_conflicts(),
1534.7.59 by Aaron Bentley
Simplified tests
439
                         [('versioning no contents', lion_id)])
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
440
        transform.create_file([b'Contents, okay?'], lion_id)
1534.7.59 by Aaron Bentley
Simplified tests
441
        transform.adjust_path('name2', trans_id2, trans_id2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
442
        self.assertEqual(transform.find_conflicts(),
443
                         [('parent loop', trans_id2),
1534.7.59 by Aaron Bentley
Simplified tests
444
                          ('non-directory parent', trans_id2)])
445
        transform.adjust_path('name2', root, trans_id2)
446
        oz_id = transform.new_directory('oz', root)
447
        transform.set_executability(True, oz_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
448
        self.assertEqual(transform.find_conflicts(),
1534.7.59 by Aaron Bentley
Simplified tests
449
                         [('unversioned executability', oz_id)])
6973.10.1 by Jelmer Vernooij
Fix some tests.
450
        transform.version_file(b'oz-id', oz_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
451
        self.assertEqual(transform.find_conflicts(),
1534.7.59 by Aaron Bentley
Simplified tests
452
                         [('non-file executability', oz_id)])
453
        transform.set_executability(None, oz_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
454
        tip_id = transform.new_file('tip', oz_id, [b'ozma'], b'tip-id')
1534.7.59 by Aaron Bentley
Simplified tests
455
        transform.apply()
6973.10.1 by Jelmer Vernooij
Fix some tests.
456
        self.assertEqual(self.wt.path2id('name'), b'my_pretties')
6973.7.5 by Jelmer Vernooij
s/file/open.
457
        with open(self.wt.abspath('name'), 'r') as f:
6973.10.1 by Jelmer Vernooij
Fix some tests.
458
            self.assertEqual(b'contents', f.read())
1534.7.59 by Aaron Bentley
Simplified tests
459
        transform2, root = self.get_transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
460
        oz_id = transform2.trans_id_tree_path('oz')
6973.10.1 by Jelmer Vernooij
Fix some tests.
461
        newtip = transform2.new_file('tip', oz_id, [b'other'], b'tip-id')
1534.7.59 by Aaron Bentley
Simplified tests
462
        result = transform2.find_conflicts()
1534.7.135 by Aaron Bentley
Fixed deletion handling
463
        fp = FinalPaths(transform2)
6614.1.1 by Vincent Ladeuil
Fix assert_ being deprecated by using assertTrue.
464
        self.assertTrue('oz/tip' in transform2._tree_path_ids)
1534.7.176 by abentley
Fixed up tests for Windows
465
        self.assertEqual(fp.get_path(newtip), pathjoin('oz', 'tip'))
1534.7.59 by Aaron Bentley
Simplified tests
466
        self.assertEqual(len(result), 2)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
467
        self.assertEqual((result[0][0], result[0][1]),
1534.7.59 by Aaron Bentley
Simplified tests
468
                         ('duplicate', newtip))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
469
        self.assertEqual((result[1][0], result[1][2]),
1534.7.59 by Aaron Bentley
Simplified tests
470
                         ('duplicate id', newtip))
1534.7.73 by Aaron Bentley
Changed model again. Now iterator is used immediately.
471
        transform2.finalize()
1534.7.59 by Aaron Bentley
Simplified tests
472
        transform3 = TreeTransform(self.wt)
473
        self.addCleanup(transform3.finalize)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
474
        oz_id = transform3.trans_id_tree_path('oz')
1534.7.59 by Aaron Bentley
Simplified tests
475
        transform3.delete_contents(oz_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
476
        self.assertEqual(transform3.find_conflicts(),
1534.7.59 by Aaron Bentley
Simplified tests
477
                         [('missing parent', oz_id)])
1731.1.33 by Aaron Bentley
Revert no-special-root changes
478
        root_id = transform3.root
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
479
        tip_id = transform3.trans_id_tree_path('oz/tip')
1534.7.59 by Aaron Bentley
Simplified tests
480
        transform3.adjust_path('tip', root_id, tip_id)
481
        transform3.apply()
1534.7.36 by Aaron Bentley
Added rename tests
482
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
483
    def test_conflict_on_case_insensitive(self):
484
        tree = self.make_branch_and_tree('tree')
485
        # Don't try this at home, kids!
486
        # Force the tree to report that it is case sensitive, for conflict
487
        # resolution tests
488
        tree.case_sensitive = True
489
        transform = TreeTransform(tree)
490
        self.addCleanup(transform.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
491
        transform.new_file('file', transform.root, [b'content'])
492
        transform.new_file('FiLe', transform.root, [b'content'])
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
493
        result = transform.find_conflicts()
494
        self.assertEqual([], result)
3008.1.15 by Aaron Bentley
Make case_sensitive an aspect of the transform, not the source tree
495
        transform.finalize()
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
496
        # Force the tree to report that it is case insensitive, for conflict
497
        # generation tests
498
        tree.case_sensitive = False
3008.1.15 by Aaron Bentley
Make case_sensitive an aspect of the transform, not the source tree
499
        transform = TreeTransform(tree)
500
        self.addCleanup(transform.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
501
        transform.new_file('file', transform.root, [b'content'])
502
        transform.new_file('FiLe', transform.root, [b'content'])
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
503
        result = transform.find_conflicts()
504
        self.assertEqual([('duplicate', 'new-1', 'new-2', 'file')], result)
505
3034.4.7 by Aaron Bentley
Add test for filename conflicts with existing files
506
    def test_conflict_on_case_insensitive_existing(self):
507
        tree = self.make_branch_and_tree('tree')
508
        self.build_tree(['tree/FiLe'])
509
        # Don't try this at home, kids!
510
        # Force the tree to report that it is case sensitive, for conflict
511
        # resolution tests
512
        tree.case_sensitive = True
513
        transform = TreeTransform(tree)
514
        self.addCleanup(transform.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
515
        transform.new_file('file', transform.root, [b'content'])
3034.4.7 by Aaron Bentley
Add test for filename conflicts with existing files
516
        result = transform.find_conflicts()
517
        self.assertEqual([], result)
3008.1.15 by Aaron Bentley
Make case_sensitive an aspect of the transform, not the source tree
518
        transform.finalize()
3034.4.7 by Aaron Bentley
Add test for filename conflicts with existing files
519
        # Force the tree to report that it is case insensitive, for conflict
520
        # generation tests
521
        tree.case_sensitive = False
3008.1.15 by Aaron Bentley
Make case_sensitive an aspect of the transform, not the source tree
522
        transform = TreeTransform(tree)
523
        self.addCleanup(transform.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
524
        transform.new_file('file', transform.root, [b'content'])
3034.4.7 by Aaron Bentley
Add test for filename conflicts with existing files
525
        result = transform.find_conflicts()
526
        self.assertEqual([('duplicate', 'new-1', 'new-2', 'file')], result)
527
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
528
    def test_resolve_case_insensitive_conflict(self):
529
        tree = self.make_branch_and_tree('tree')
530
        # Don't try this at home, kids!
531
        # Force the tree to report that it is case insensitive, for conflict
532
        # resolution tests
533
        tree.case_sensitive = False
534
        transform = TreeTransform(tree)
535
        self.addCleanup(transform.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
536
        transform.new_file('file', transform.root, [b'content'])
537
        transform.new_file('FiLe', transform.root, [b'content'])
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
538
        resolve_conflicts(transform)
539
        transform.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
540
        self.assertPathExists('tree/file')
541
        self.assertPathExists('tree/FiLe.moved')
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
542
3034.4.2 by Aaron Bentley
Get conflict handling and case-insensitive tree creation under test
543
    def test_resolve_checkout_case_conflict(self):
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
544
        tree = self.make_branch_and_tree('tree')
545
        # Don't try this at home, kids!
546
        # Force the tree to report that it is case insensitive, for conflict
547
        # resolution tests
548
        tree.case_sensitive = False
549
        transform = TreeTransform(tree)
550
        self.addCleanup(transform.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
551
        transform.new_file('file', transform.root, [b'content'])
552
        transform.new_file('FiLe', transform.root, [b'content'])
3034.4.2 by Aaron Bentley
Get conflict handling and case-insensitive tree creation under test
553
        resolve_conflicts(transform,
554
                          pass_func=lambda t, c: resolve_checkout(t, c, []))
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
555
        transform.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
556
        self.assertPathExists('tree/file')
557
        self.assertPathExists('tree/FiLe.moved')
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
558
3034.4.2 by Aaron Bentley
Get conflict handling and case-insensitive tree creation under test
559
    def test_apply_case_conflict(self):
3034.4.6 by Aaron Bentley
Update apply_case_conflict tests
560
        """Ensure that a transform with case conflicts can always be applied"""
3034.4.2 by Aaron Bentley
Get conflict handling and case-insensitive tree creation under test
561
        tree = self.make_branch_and_tree('tree')
562
        transform = TreeTransform(tree)
563
        self.addCleanup(transform.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
564
        transform.new_file('file', transform.root, [b'content'])
565
        transform.new_file('FiLe', transform.root, [b'content'])
3034.4.6 by Aaron Bentley
Update apply_case_conflict tests
566
        dir = transform.new_directory('dir', transform.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
567
        transform.new_file('dirfile', dir, [b'content'])
568
        transform.new_file('dirFiLe', dir, [b'content'])
3034.4.6 by Aaron Bentley
Update apply_case_conflict tests
569
        resolve_conflicts(transform)
3034.4.2 by Aaron Bentley
Get conflict handling and case-insensitive tree creation under test
570
        transform.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
571
        self.assertPathExists('tree/file')
3034.4.3 by Aaron Bentley
Add case-sensitivity handling to WorkingTree
572
        if not os.path.exists('tree/FiLe.moved'):
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
573
            self.assertPathExists('tree/FiLe')
574
        self.assertPathExists('tree/dir/dirfile')
3034.4.6 by Aaron Bentley
Update apply_case_conflict tests
575
        if not os.path.exists('tree/dir/dirFiLe.moved'):
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
576
            self.assertPathExists('tree/dir/dirFiLe')
3034.4.2 by Aaron Bentley
Get conflict handling and case-insensitive tree creation under test
577
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
578
    def test_case_insensitive_limbo(self):
579
        tree = self.make_branch_and_tree('tree')
580
        # Don't try this at home, kids!
581
        # Force the tree to report that it is case insensitive
582
        tree.case_sensitive = False
583
        transform = TreeTransform(tree)
584
        self.addCleanup(transform.finalize)
585
        dir = transform.new_directory('dir', transform.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
586
        first = transform.new_file('file', dir, [b'content'])
587
        second = transform.new_file('FiLe', dir, [b'content'])
3034.4.1 by Aaron Bentley
Start handling case-insensitivity
588
        self.assertContainsRe(transform._limbo_name(first), 'new-1/file')
589
        self.assertNotContainsRe(transform._limbo_name(second), 'new-1/FiLe')
590
4634.78.1 by Aaron Bentley
adjust_path updatest limbo paths.
591
    def test_adjust_path_updates_child_limbo_names(self):
592
        tree = self.make_branch_and_tree('tree')
593
        transform = TreeTransform(tree)
594
        self.addCleanup(transform.finalize)
595
        foo_id = transform.new_directory('foo', transform.root)
596
        bar_id = transform.new_directory('bar', foo_id)
597
        baz_id = transform.new_directory('baz', bar_id)
598
        qux_id = transform.new_directory('qux', baz_id)
599
        transform.adjust_path('quxx', foo_id, bar_id)
600
        self.assertStartsWith(transform._limbo_name(qux_id),
601
                              transform._limbo_name(bar_id))
602
1558.7.11 by Aaron Bentley
Avoid spurious conflict on add/delete
603
    def test_add_del(self):
604
        start, root = self.get_transform()
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
605
        start.new_directory('a', root, b'a')
1558.7.11 by Aaron Bentley
Avoid spurious conflict on add/delete
606
        start.apply()
607
        transform, root = self.get_transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
608
        transform.delete_versioned(transform.trans_id_tree_path('a'))
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
609
        transform.new_directory('a', root, b'a')
1558.7.11 by Aaron Bentley
Avoid spurious conflict on add/delete
610
        transform.apply()
611
1534.7.46 by Aaron Bentley
Ensured a conflict when parents of versioned files are unversioned
612
    def test_unversioning(self):
1534.7.59 by Aaron Bentley
Simplified tests
613
        create_tree, root = self.get_transform()
6855.4.1 by Jelmer Vernooij
Yet more bees.
614
        parent_id = create_tree.new_directory('parent', root, b'parent-id')
6973.10.1 by Jelmer Vernooij
Fix some tests.
615
        create_tree.new_file('child', parent_id, [b'child'], b'child-id')
1534.7.59 by Aaron Bentley
Simplified tests
616
        create_tree.apply()
617
        unversion = TreeTransform(self.wt)
618
        self.addCleanup(unversion.finalize)
1534.7.181 by Aaron Bentley
Renamed a bunch of functions
619
        parent = unversion.trans_id_tree_path('parent')
1534.7.59 by Aaron Bentley
Simplified tests
620
        unversion.unversion_file(parent)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
621
        self.assertEqual(unversion.find_conflicts(),
1534.7.59 by Aaron Bentley
Simplified tests
622
                         [('unversioned parent', parent_id)])
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
623
        file_id = unversion.trans_id_tree_path('parent/child')
1534.7.59 by Aaron Bentley
Simplified tests
624
        unversion.unversion_file(file_id)
625
        unversion.apply()
1534.7.46 by Aaron Bentley
Ensured a conflict when parents of versioned files are unversioned
626
1534.7.36 by Aaron Bentley
Added rename tests
627
    def test_name_invariants(self):
1534.7.59 by Aaron Bentley
Simplified tests
628
        create_tree, root = self.get_transform()
629
        # prepare tree
1731.1.33 by Aaron Bentley
Revert no-special-root changes
630
        root = create_tree.root
6973.10.1 by Jelmer Vernooij
Fix some tests.
631
        create_tree.new_file('name1', root, [b'hello1'], b'name1')
632
        create_tree.new_file('name2', root, [b'hello2'], b'name2')
633
        ddir = create_tree.new_directory('dying_directory', root, b'ddir')
634
        create_tree.new_file('dying_file', ddir, [b'goodbye1'], b'dfile')
635
        create_tree.new_file('moving_file', ddir, [b'later1'], b'mfile')
636
        create_tree.new_file('moving_file2', root, [b'later2'], b'mfile2')
1534.7.59 by Aaron Bentley
Simplified tests
637
        create_tree.apply()
638
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
639
        mangle_tree, root = self.get_transform()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
640
        root = mangle_tree.root
1534.7.59 by Aaron Bentley
Simplified tests
641
        #swap names
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
642
        name1 = mangle_tree.trans_id_tree_path('name1')
643
        name2 = mangle_tree.trans_id_tree_path('name2')
1534.7.59 by Aaron Bentley
Simplified tests
644
        mangle_tree.adjust_path('name2', root, name1)
645
        mangle_tree.adjust_path('name1', root, name2)
646
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
647
        #tests for deleting parent directories
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
648
        ddir = mangle_tree.trans_id_tree_path('dying_directory')
1534.7.59 by Aaron Bentley
Simplified tests
649
        mangle_tree.delete_contents(ddir)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
650
        dfile = mangle_tree.trans_id_tree_path('dying_directory/dying_file')
1534.7.59 by Aaron Bentley
Simplified tests
651
        mangle_tree.delete_versioned(dfile)
652
        mangle_tree.unversion_file(dfile)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
653
        mfile = mangle_tree.trans_id_tree_path('dying_directory/moving_file')
1534.7.59 by Aaron Bentley
Simplified tests
654
        mangle_tree.adjust_path('mfile', root, mfile)
655
656
        #tests for adding parent directories
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
657
        newdir = mangle_tree.new_directory('new_directory', root, b'newdir')
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
658
        mfile2 = mangle_tree.trans_id_tree_path('moving_file2')
1534.7.59 by Aaron Bentley
Simplified tests
659
        mangle_tree.adjust_path('mfile2', newdir, mfile2)
6973.10.1 by Jelmer Vernooij
Fix some tests.
660
        mangle_tree.new_file('newfile', newdir, [b'hello3'], b'dfile')
661
        self.assertEqual(mangle_tree.final_file_id(mfile2), b'mfile2')
1534.7.59 by Aaron Bentley
Simplified tests
662
        self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
6973.10.1 by Jelmer Vernooij
Fix some tests.
663
        self.assertEqual(mangle_tree.final_file_id(mfile2), b'mfile2')
1534.7.59 by Aaron Bentley
Simplified tests
664
        mangle_tree.apply()
6973.7.5 by Jelmer Vernooij
s/file/open.
665
        with open(self.wt.abspath('name1'), 'r') as f:
666
            self.assertEqual(f.read(), 'hello2')
667
        with open(self.wt.abspath('name2'), 'r') as f:
668
            self.assertEqual(f.read(), 'hello1')
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
669
        mfile2_path = self.wt.abspath(pathjoin('new_directory', 'mfile2'))
1534.7.41 by Aaron Bentley
Got inventory ID movement working
670
        self.assertEqual(mangle_tree.final_parent(mfile2), newdir)
6973.7.5 by Jelmer Vernooij
s/file/open.
671
        with open(mfile2_path, 'r') as f:
672
            self.assertEqual(f.read(), 'later2')
6855.4.1 by Jelmer Vernooij
Yet more bees.
673
        self.assertEqual(self.wt.id2path(b'mfile2'), 'new_directory/mfile2')
674
        self.assertEqual(self.wt.path2id('new_directory/mfile2'), b'mfile2')
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
675
        newfile_path = self.wt.abspath(pathjoin('new_directory', 'newfile'))
6973.7.5 by Jelmer Vernooij
s/file/open.
676
        with open(newfile_path, 'r') as f:
677
            self.assertEqual(f.read(), 'hello3')
6855.4.1 by Jelmer Vernooij
Yet more bees.
678
        self.assertEqual(self.wt.path2id('dying_directory'), b'ddir')
1534.7.59 by Aaron Bentley
Simplified tests
679
        self.assertIs(self.wt.path2id('dying_directory/dying_file'), None)
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
680
        mfile2_path = self.wt.abspath(pathjoin('new_directory', 'mfile2'))
1534.7.43 by abentley
Fixed some Windows bugs, introduced a conflicts bug
681
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
682
    def test_both_rename(self):
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
683
        create_tree, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
684
        newdir = create_tree.new_directory('selftest', root, b'selftest-id')
685
        create_tree.new_file('blackbox.py', newdir, [b'hello1'], b'blackbox-id')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
686
        create_tree.apply()
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
687
        mangle_tree, root = self.get_transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
688
        selftest = mangle_tree.trans_id_tree_path('selftest')
689
        blackbox = mangle_tree.trans_id_tree_path('selftest/blackbox.py')
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
690
        mangle_tree.adjust_path('test', root, selftest)
691
        mangle_tree.adjust_path('test_too_much', root, selftest)
692
        mangle_tree.set_executability(True, blackbox)
693
        mangle_tree.apply()
694
695
    def test_both_rename2(self):
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
696
        create_tree, root = self.get_transform()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
697
        breezy = create_tree.new_directory('breezy', root, b'breezy-id')
698
        tests = create_tree.new_directory('tests', breezy, b'tests-id')
699
        blackbox = create_tree.new_directory('blackbox', tests, b'blackbox-id')
6973.10.1 by Jelmer Vernooij
Fix some tests.
700
        create_tree.new_file('test_too_much.py', blackbox, [b'hello1'],
701
                             b'test_too_much-id')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
702
        create_tree.apply()
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
703
        mangle_tree, root = self.get_transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
704
        breezy = mangle_tree.trans_id_tree_path('breezy')
705
        tests = mangle_tree.trans_id_tree_path('breezy/tests')
706
        test_too_much = mangle_tree.trans_id_tree_path('breezy/tests/blackbox/test_too_much.py')
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
707
        mangle_tree.adjust_path('selftest', breezy, tests)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
708
        mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
709
        mangle_tree.set_executability(True, test_too_much)
710
        mangle_tree.apply()
711
712
    def test_both_rename3(self):
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
713
        create_tree, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
714
        tests = create_tree.new_directory('tests', root, b'tests-id')
715
        create_tree.new_file('test_too_much.py', tests, [b'hello1'],
716
                             b'test_too_much-id')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
717
        create_tree.apply()
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
718
        mangle_tree, root = self.get_transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
719
        tests = mangle_tree.trans_id_tree_path('tests')
720
        test_too_much = mangle_tree.trans_id_tree_path('tests/test_too_much.py')
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
721
        mangle_tree.adjust_path('selftest', root, tests)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
722
        mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
1534.7.150 by Aaron Bentley
Handled simultaneous renames of parent and child better
723
        mangle_tree.set_executability(True, test_too_much)
724
        mangle_tree.apply()
725
1534.7.48 by Aaron Bentley
Ensured we can move/rename dangling inventory entries
726
    def test_move_dangling_ie(self):
1534.7.59 by Aaron Bentley
Simplified tests
727
        create_tree, root = self.get_transform()
728
        # prepare tree
1731.1.33 by Aaron Bentley
Revert no-special-root changes
729
        root = create_tree.root
6973.10.1 by Jelmer Vernooij
Fix some tests.
730
        create_tree.new_file('name1', root, [b'hello1'], b'name1')
1534.7.59 by Aaron Bentley
Simplified tests
731
        create_tree.apply()
732
        delete_contents, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
733
        file = delete_contents.trans_id_tree_path(b'name1')
1534.7.59 by Aaron Bentley
Simplified tests
734
        delete_contents.delete_contents(file)
735
        delete_contents.apply()
736
        move_id, root = self.get_transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
737
        name1 = move_id.trans_id_tree_path('name1')
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
738
        newdir = move_id.new_directory('dir', root, b'newdir')
1534.7.59 by Aaron Bentley
Simplified tests
739
        move_id.adjust_path('name2', newdir, name1)
740
        move_id.apply()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
741
1534.7.50 by Aaron Bentley
Detect duplicate inventory ids
742
    def test_replace_dangling_ie(self):
1534.7.59 by Aaron Bentley
Simplified tests
743
        create_tree, root = self.get_transform()
744
        # prepare tree
1731.1.33 by Aaron Bentley
Revert no-special-root changes
745
        root = create_tree.root
6973.10.1 by Jelmer Vernooij
Fix some tests.
746
        create_tree.new_file('name1', root, [b'hello1'], 'name1')
1534.7.59 by Aaron Bentley
Simplified tests
747
        create_tree.apply()
748
        delete_contents = TreeTransform(self.wt)
749
        self.addCleanup(delete_contents.finalize)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
750
        file = delete_contents.trans_id_tree_path('name1')
1534.7.59 by Aaron Bentley
Simplified tests
751
        delete_contents.delete_contents(file)
752
        delete_contents.apply()
753
        delete_contents.finalize()
754
        replace = TreeTransform(self.wt)
755
        self.addCleanup(replace.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
756
        name2 = replace.new_file('name2', root, [b'hello2'], 'name1')
1534.7.59 by Aaron Bentley
Simplified tests
757
        conflicts = replace.find_conflicts()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
758
        name1 = replace.trans_id_tree_path('name1')
1534.7.59 by Aaron Bentley
Simplified tests
759
        self.assertEqual(conflicts, [('duplicate id', name1, name2)])
760
        resolve_conflicts(replace)
761
        replace.apply()
1534.7.48 by Aaron Bentley
Ensured we can move/rename dangling inventory entries
762
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
763
    def _test_symlinks(self, link_name1, link_target1,
4241.14.17 by Vincent Ladeuil
Add more tests for unicode symlinks to test_transform.
764
                       link_name2, link_target2):
765
766
        def ozpath(p): return 'oz/' + p
767
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
768
        self.requireFeature(SymlinkFeature)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
769
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
770
        oz_id = transform.new_directory('oz', root, b'oz-id')
4241.14.17 by Vincent Ladeuil
Add more tests for unicode symlinks to test_transform.
771
        wizard = transform.new_symlink(link_name1, oz_id, link_target1,
6973.10.1 by Jelmer Vernooij
Fix some tests.
772
                                       b'wizard-id')
4241.14.17 by Vincent Ladeuil
Add more tests for unicode symlinks to test_transform.
773
        wiz_id = transform.create_path(link_name2, oz_id)
774
        transform.create_symlink(link_target2, wiz_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
775
        transform.version_file(b'wiz-id2', wiz_id)
1534.7.71 by abentley
All tests pass under Windows
776
        transform.set_executability(True, wiz_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
777
        self.assertEqual(transform.find_conflicts(),
1534.7.71 by abentley
All tests pass under Windows
778
                         [('non-file executability', wiz_id)])
779
        transform.set_executability(None, wiz_id)
1534.7.59 by Aaron Bentley
Simplified tests
780
        transform.apply()
6973.10.1 by Jelmer Vernooij
Fix some tests.
781
        self.assertEqual(self.wt.path2id(ozpath(link_name1)), b'wizard-id')
4241.14.17 by Vincent Ladeuil
Add more tests for unicode symlinks to test_transform.
782
        self.assertEqual('symlink',
783
                         file_kind(self.wt.abspath(ozpath(link_name1))))
784
        self.assertEqual(link_target2,
785
                         osutils.readlink(self.wt.abspath(ozpath(link_name2))))
786
        self.assertEqual(link_target1,
787
                         osutils.readlink(self.wt.abspath(ozpath(link_name1))))
788
789
    def test_symlinks(self):
790
        self._test_symlinks('wizard', 'wizard-target',
791
                            'wizard2', 'behind_curtain')
792
793
    def test_symlinks_unicode(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
794
        self.requireFeature(features.UnicodeFilenameFeature)
4241.14.17 by Vincent Ladeuil
Add more tests for unicode symlinks to test_transform.
795
        self._test_symlinks(u'\N{Euro Sign}wizard',
796
                            u'wizard-targ\N{Euro Sign}t',
797
                            u'\N{Euro Sign}wizard2',
798
                            u'b\N{Euro Sign}hind_curtain')
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
799
3006.2.2 by Alexander Belchenko
tests added.
800
    def test_unable_create_symlink(self):
801
        def tt_helper():
802
            wt = self.make_branch_and_tree('.')
803
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
804
            try:
805
                tt.new_symlink('foo', tt.root, 'bar')
806
                tt.apply()
807
            finally:
808
                wt.unlock()
809
        os_symlink = getattr(os, 'symlink', None)
810
        os.symlink = None
811
        try:
812
            err = self.assertRaises(errors.UnableCreateSymlink, tt_helper)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
813
            self.assertEqual(
3006.2.2 by Alexander Belchenko
tests added.
814
                "Unable to create symlink 'foo' on this platform",
815
                str(err))
816
        finally:
817
            if os_symlink:
818
                os.symlink = os_symlink
819
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
820
    def get_conflicted(self):
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
821
        create, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
822
        create.new_file('dorothy', root, [b'dorothy'], b'dorothy-id')
823
        oz = create.new_directory('oz', root, b'oz-id')
824
        create.new_directory('emeraldcity', oz, b'emerald-id')
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
825
        create.apply()
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
826
        conflicts, root = self.get_transform()
1534.7.65 by Aaron Bentley
Text cleaup/docs
827
        # set up duplicate entry, duplicate id
6973.10.1 by Jelmer Vernooij
Fix some tests.
828
        new_dorothy = conflicts.new_file('dorothy', root, [b'dorothy'],
829
                                         b'dorothy-id')
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
830
        old_dorothy = conflicts.trans_id_tree_path('dorothy')
831
        oz = conflicts.trans_id_tree_path('oz')
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
832
        # set up DeletedParent parent conflict
1534.7.65 by Aaron Bentley
Text cleaup/docs
833
        conflicts.delete_versioned(oz)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
834
        emerald = conflicts.trans_id_tree_path('oz/emeraldcity')
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
835
        # set up MissingParent conflict
6973.10.1 by Jelmer Vernooij
Fix some tests.
836
        munchkincity = conflicts.trans_id_file_id(b'munchkincity-id')
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
837
        conflicts.adjust_path('munchkincity', root, munchkincity)
6973.10.1 by Jelmer Vernooij
Fix some tests.
838
        conflicts.new_directory('auntem', munchkincity, b'auntem-id')
1534.7.65 by Aaron Bentley
Text cleaup/docs
839
        # set up parent loop
1534.7.61 by Aaron Bentley
Handled parent loops, missing parents, unversioned parents
840
        conflicts.adjust_path('emeraldcity', emerald, emerald)
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
841
        return conflicts, emerald, oz, old_dorothy, new_dorothy
842
843
    def test_conflict_resolution(self):
844
        conflicts, emerald, oz, old_dorothy, new_dorothy =\
845
            self.get_conflicted()
1534.7.60 by Aaron Bentley
Tested existing conflict resolution functionality
846
        resolve_conflicts(conflicts)
847
        self.assertEqual(conflicts.final_name(old_dorothy), 'dorothy.moved')
848
        self.assertIs(conflicts.final_file_id(old_dorothy), None)
849
        self.assertEqual(conflicts.final_name(new_dorothy), 'dorothy')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
850
        self.assertEqual(conflicts.final_file_id(new_dorothy), b'dorothy-id')
1534.7.64 by Aaron Bentley
Extra testing
851
        self.assertEqual(conflicts.final_parent(emerald), oz)
1534.7.63 by Aaron Bentley
Ensure transform can be applied after resolution
852
        conflicts.apply()
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
853
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
854
    def test_cook_conflicts(self):
855
        tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
856
        raw_conflicts = resolve_conflicts(tt)
857
        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
858
        duplicate = DuplicateEntry('Moved existing file to', 'dorothy.moved',
6973.10.1 by Jelmer Vernooij
Fix some tests.
859
                                   'dorothy', None, b'dorothy-id')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
860
        self.assertEqual(cooked_conflicts[0], duplicate)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
861
        duplicate_id = DuplicateID('Unversioned existing file',
1534.10.20 by Aaron Bentley
Got all tests passing
862
                                   'dorothy.moved', 'dorothy', None,
6973.10.1 by Jelmer Vernooij
Fix some tests.
863
                                   b'dorothy-id')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
864
        self.assertEqual(cooked_conflicts[1], duplicate_id)
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
865
        missing_parent = MissingParent('Created directory', 'munchkincity',
6973.10.1 by Jelmer Vernooij
Fix some tests.
866
                                       b'munchkincity-id')
867
        deleted_parent = DeletingParent('Not deleting', 'oz', b'oz-id')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
868
        self.assertEqual(cooked_conflicts[2], missing_parent)
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
869
        unversioned_parent = UnversionedParent('Versioned directory',
870
                                               'munchkincity',
6973.10.1 by Jelmer Vernooij
Fix some tests.
871
                                               b'munchkincity-id')
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
872
        unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
6973.10.1 by Jelmer Vernooij
Fix some tests.
873
                                               b'oz-id')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
874
        self.assertEqual(cooked_conflicts[3], unversioned_parent)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
875
        parent_loop = ParentLoop('Cancelled move', 'oz/emeraldcity',
6973.10.1 by Jelmer Vernooij
Fix some tests.
876
                                 'oz/emeraldcity', b'emerald-id', b'emerald-id')
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
877
        self.assertEqual(cooked_conflicts[4], deleted_parent)
878
        self.assertEqual(cooked_conflicts[5], unversioned_parent2)
879
        self.assertEqual(cooked_conflicts[6], parent_loop)
880
        self.assertEqual(len(cooked_conflicts), 7)
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
881
        tt.finalize()
882
883
    def test_string_conflicts(self):
884
        tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
885
        raw_conflicts = resolve_conflicts(tt)
886
        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
887
        tt.finalize()
6973.6.2 by Jelmer Vernooij
Fix more tests.
888
        conflicts_s = [text_type(c) for c in cooked_conflicts]
1534.7.171 by Aaron Bentley
Implemented stringifying filesystem conflicts
889
        self.assertEqual(len(cooked_conflicts), len(conflicts_s))
890
        self.assertEqual(conflicts_s[0], 'Conflict adding file dorothy.  '
891
                                         'Moved existing file to '
892
                                         'dorothy.moved.')
893
        self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy.  '
894
                                         'Unversioned existing file '
895
                                         'dorothy.moved.')
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
896
        self.assertEqual(conflicts_s[2], 'Conflict adding files to'
897
                                         ' munchkincity.  Created directory.')
898
        self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
899
                                         ' versioned, but has versioned'
900
                                         ' children.  Versioned directory.')
1551.8.23 by Aaron Bentley
Tweaked conflict message to be more understandable
901
        self.assertEqualDiff(conflicts_s[4], "Conflict: can't delete oz because it"
902
                                         " is not empty.  Not deleting.")
1551.8.22 by Aaron Bentley
Improve message when OTHER deletes an in-use tree
903
        self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
904
                                         ' versioned, but has versioned'
905
                                         ' children.  Versioned directory.')
906
        self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
4597.8.11 by Vincent Ladeuil
The ParentLoop.format has been updated, fix fallouts.
907
                                         ' oz/emeraldcity. Cancelled move.')
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
908
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
909
    def prepare_wrong_parent_kind(self):
910
        tt, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
911
        tt.new_file('parent', root, [b'contents'], b'parent-id')
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
912
        tt.apply()
913
        tt, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
914
        parent_id = tt.trans_id_file_id(b'parent-id')
915
        tt.new_file('child,', parent_id, [b'contents2'], b'file-id')
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
916
        return tt
917
3144.4.1 by Aaron Bentley
Handle trying to list parents of a non-directory
918
    def test_find_conflicts_wrong_parent_kind(self):
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
919
        tt = self.prepare_wrong_parent_kind()
3144.4.1 by Aaron Bentley
Handle trying to list parents of a non-directory
920
        tt.find_conflicts()
921
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
922
    def test_resolve_conflicts_wrong_existing_parent_kind(self):
923
        tt = self.prepare_wrong_parent_kind()
924
        raw_conflicts = resolve_conflicts(tt)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
925
        self.assertEqual({('non-directory parent', 'Created directory',
926
                         'new-3')}, raw_conflicts)
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
927
        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
928
        self.assertEqual([NonDirectoryParent('Created directory', 'parent.new',
6855.4.1 by Jelmer Vernooij
Yet more bees.
929
        b'parent-id')], cooked_conflicts)
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
930
        tt.apply()
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
931
        self.assertFalse(self.wt.is_versioned('parent'))
6973.13.2 by Jelmer Vernooij
Fix some more tests.
932
        self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
933
934
    def test_resolve_conflicts_wrong_new_parent_kind(self):
935
        tt, root = self.get_transform()
6855.4.1 by Jelmer Vernooij
Yet more bees.
936
        parent_id = tt.new_directory('parent', root, b'parent-id')
6973.10.1 by Jelmer Vernooij
Fix some tests.
937
        tt.new_file('child,', parent_id, [b'contents2'], b'file-id')
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
938
        tt.apply()
939
        tt, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
940
        parent_id = tt.trans_id_file_id(b'parent-id')
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
941
        tt.delete_contents(parent_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
942
        tt.create_file([b'contents'], parent_id)
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
943
        raw_conflicts = resolve_conflicts(tt)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
944
        self.assertEqual({('non-directory parent', 'Created directory',
945
                         'new-3')}, raw_conflicts)
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
946
        tt.apply()
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
947
        self.assertFalse(self.wt.is_versioned('parent'))
6973.10.1 by Jelmer Vernooij
Fix some tests.
948
        self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
949
950
    def test_resolve_conflicts_wrong_parent_kind_unversioned(self):
951
        tt, root = self.get_transform()
952
        parent_id = tt.new_directory('parent', root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
953
        tt.new_file('child,', parent_id, [b'contents2'])
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
954
        tt.apply()
955
        tt, root = self.get_transform()
956
        parent_id = tt.trans_id_tree_path('parent')
957
        tt.delete_contents(parent_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
958
        tt.create_file([b'contents'], parent_id)
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
959
        resolve_conflicts(tt)
960
        tt.apply()
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
961
        self.assertFalse(self.wt.is_versioned('parent'))
962
        self.assertFalse(self.wt.is_versioned('parent.new'))
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
963
5409.5.1 by Vincent Ladeuil
Tweak test_resolve_conflicts_missing_parent (renamed from test_resolve_no_parent), puttinh it in the right place.
964
    def test_resolve_conflicts_missing_parent(self):
965
        wt = self.make_branch_and_tree('.')
966
        tt = TreeTransform(wt)
967
        self.addCleanup(tt.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
968
        parent = tt.trans_id_file_id(b'parent-id')
969
        tt.new_file('file', parent, [b'Contents'])
5409.5.1 by Vincent Ladeuil
Tweak test_resolve_conflicts_missing_parent (renamed from test_resolve_no_parent), puttinh it in the right place.
970
        raw_conflicts = resolve_conflicts(tt)
5409.6.2 by Vincent Ladeuil
Fix typo in the comment.
971
        # Since the directory doesn't exist it's seen as 'missing'.  So
972
        # 'resolve_conflicts' create a conflict asking for it to be created.
5409.5.1 by Vincent Ladeuil
Tweak test_resolve_conflicts_missing_parent (renamed from test_resolve_no_parent), puttinh it in the right place.
973
        self.assertLength(1, raw_conflicts)
974
        self.assertEqual(('missing parent', 'Created directory', 'new-1'),
975
                         raw_conflicts.pop())
5409.6.1 by Vincent Ladeuil
Clarify test intent and behaviour.
976
        # apply fail since the missing directory doesn't exist
977
        self.assertRaises(errors.NoFinalPath, tt.apply)
5409.5.1 by Vincent Ladeuil
Tweak test_resolve_conflicts_missing_parent (renamed from test_resolve_no_parent), puttinh it in the right place.
978
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
979
    def test_moving_versioned_directories(self):
980
        create, root = self.get_transform()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
981
        kansas = create.new_directory('kansas', root, b'kansas-id')
982
        create.new_directory('house', kansas, b'house-id')
983
        create.new_directory('oz', root, b'oz-id')
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
984
        create.apply()
985
        cyclone, root = self.get_transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
986
        oz = cyclone.trans_id_tree_path('oz')
987
        house = cyclone.trans_id_tree_path('house')
1534.7.62 by Aaron Bentley
Fixed moving versioned directories
988
        cyclone.adjust_path('house', oz, house)
989
        cyclone.apply()
1534.7.66 by Aaron Bentley
Ensured we don't accidentally move the root directory
990
991
    def test_moving_root(self):
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
992
        create, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
993
        fun = create.new_directory('fun', root, b'fun-id')
994
        create.new_directory('sun', root, b'sun-id')
995
        create.new_directory('moon', root, b'moon')
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
996
        create.apply()
1534.7.66 by Aaron Bentley
Ensured we don't accidentally move the root directory
997
        transform, root = self.get_transform()
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
998
        transform.adjust_root_path('oldroot', fun)
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
999
        new_root = transform.trans_id_tree_path('')
6973.10.1 by Jelmer Vernooij
Fix some tests.
1000
        transform.version_file(b'new-root', new_root)
1534.7.68 by Aaron Bentley
Got semi-reasonable root directory renaming working
1001
        transform.apply()
1534.7.93 by Aaron Bentley
Added text merge test
1002
1534.7.114 by Aaron Bentley
Added file renaming test case
1003
    def test_renames(self):
1004
        create, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1005
        old = create.new_directory('old-parent', root, b'old-id')
1006
        intermediate = create.new_directory('intermediate', old, b'im-id')
1007
        myfile = create.new_file('myfile', intermediate, [b'myfile-text'],
1008
                                 b'myfile-id')
1534.7.114 by Aaron Bentley
Added file renaming test case
1009
        create.apply()
1010
        rename, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1011
        old = rename.trans_id_file_id(b'old-id')
1534.7.114 by Aaron Bentley
Added file renaming test case
1012
        rename.adjust_path('new', root, old)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1013
        myfile = rename.trans_id_file_id(b'myfile-id')
1534.7.114 by Aaron Bentley
Added file renaming test case
1014
        rename.set_executability(True, myfile)
1015
        rename.apply()
1016
5186.2.4 by Martin Pool
Add failing specific test for 491763
1017
    def test_rename_fails(self):
5050.43.1 by Vincent Ladeuil
Fix one more failure when the test suite is run as root.
1018
        self.requireFeature(features.not_running_as_root)
5186.2.4 by Martin Pool
Add failing specific test for 491763
1019
        # see https://bugs.launchpad.net/bzr/+bug/491763
1020
        create, root_id = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1021
        first_dir = create.new_directory('first-dir', root_id, b'first-id')
1022
        myfile = create.new_file('myfile', root_id, [b'myfile-text'],
1023
                                 b'myfile-id')
5186.2.4 by Martin Pool
Add failing specific test for 491763
1024
        create.apply()
5050.15.2 by Martin
Correct bt.test_transform.TestTreeTransform.test_rename_fails on non-posix platforms
1025
        if os.name == "posix" and sys.platform != "cygwin":
1026
            # posix filesystems fail on renaming if the readonly bit is set
1027
            osutils.make_readonly(self.wt.abspath('first-dir'))
1028
        elif os.name == "nt":
1029
            # windows filesystems fail on renaming open files
6973.7.5 by Jelmer Vernooij
s/file/open.
1030
            self.addCleanup(open(self.wt.abspath('myfile')).close)
5050.15.2 by Martin
Correct bt.test_transform.TestTreeTransform.test_rename_fails on non-posix platforms
1031
        else:
6622.4.1 by Martin
Use skipTest rather than deprecated skip method
1032
            self.skipTest("Can't force a permissions error on rename")
5186.2.4 by Martin Pool
Add failing specific test for 491763
1033
        # now transform to rename
1034
        rename_transform, root_id = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1035
        file_trans_id = rename_transform.trans_id_file_id(b'myfile-id')
1036
        dir_id = rename_transform.trans_id_file_id(b'first-id')
5186.2.4 by Martin Pool
Add failing specific test for 491763
1037
        rename_transform.adjust_path('newname', dir_id, file_trans_id)
5186.2.5 by Martin Pool
Raise a specific clearer error when a rename fails inside transform
1038
        e = self.assertRaises(errors.TransformRenameFailed,
1039
            rename_transform.apply)
5050.15.2 by Martin
Correct bt.test_transform.TestTreeTransform.test_rename_fails on non-posix platforms
1040
        # On nix looks like: 
5186.2.5 by Martin Pool
Raise a specific clearer error when a rename fails inside transform
1041
        # "Failed to rename .../work/.bzr/checkout/limbo/new-1
1042
        # to .../first-dir/newname: [Errno 13] Permission denied"
5050.15.2 by Martin
Correct bt.test_transform.TestTreeTransform.test_rename_fails on non-posix platforms
1043
        # On windows looks like:
1044
        # "Failed to rename .../work/myfile to 
1045
        # .../work/.bzr/checkout/limbo/new-1: [Errno 13] Permission denied"
5582.8.1 by Martin
Make bt.test_transform.TestTreeTransform.test_rename_fails not care about the exact stringification of the exception instance
1046
        # This test isn't concerned with exactly what the error looks like,
1047
        # and the strerror will vary across OS and locales, but the assert
1048
        # that the exeception attributes are what we expect
1049
        self.assertEqual(e.errno, errno.EACCES)
1050
        if os.name == "posix":
1051
            self.assertEndsWith(e.to_path, "/first-dir/newname")
1052
        else:
1053
            self.assertEqual(os.path.basename(e.from_path), "myfile")
5186.2.4 by Martin Pool
Add failing specific test for 491763
1054
1740.2.4 by Aaron Bentley
Update transform tests and docs
1055
    def test_set_executability_order(self):
1056
        """Ensure that executability behaves the same, no matter what order.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1057
1740.2.4 by Aaron Bentley
Update transform tests and docs
1058
        - create file and set executability simultaneously
1059
        - create file and set executability afterward
1060
        - unsetting the executability of a file whose executability has not been
1061
        declared should throw an exception (this may happen when a
1062
        merge attempts to create a file with a duplicate ID)
1063
        """
1064
        transform, root = self.get_transform()
1065
        wt = transform._tree
3034.2.1 by Aaron Bentley
Fix is_executable tests for win32
1066
        wt.lock_read()
1067
        self.addCleanup(wt.unlock)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1068
        transform.new_file('set_on_creation', root, [b'Set on creation'], 'soc',
1740.2.4 by Aaron Bentley
Update transform tests and docs
1069
                           True)
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
1070
        sac = transform.new_file('set_after_creation', root,
6973.10.1 by Jelmer Vernooij
Fix some tests.
1071
                                 [b'Set after creation'], 'sac')
1740.2.4 by Aaron Bentley
Update transform tests and docs
1072
        transform.set_executability(True, sac)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1073
        uws = transform.new_file('unset_without_set', root, [b'Unset badly'],
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
1074
                                 'uws')
1740.2.4 by Aaron Bentley
Update transform tests and docs
1075
        self.assertRaises(KeyError, transform.set_executability, None, uws)
1076
        transform.apply()
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
1077
        self.assertTrue(wt.is_executable('set_on_creation'))
1078
        self.assertTrue(wt.is_executable('set_after_creation'))
1740.2.4 by Aaron Bentley
Update transform tests and docs
1079
1534.12.2 by Aaron Bentley
Added test for preserving file mode
1080
    def test_preserve_mode(self):
1081
        """File mode is preserved when replacing content"""
1082
        if sys.platform == 'win32':
1083
            raise TestSkipped('chmod has no effect on win32')
1084
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1085
        transform.new_file('file1', root, [b'contents'], b'file1-id', True)
1534.12.2 by Aaron Bentley
Added test for preserving file mode
1086
        transform.apply()
3146.4.12 by Aaron Bentley
Add needed write lock to test
1087
        self.wt.lock_write()
1088
        self.addCleanup(self.wt.unlock)
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
1089
        self.assertTrue(self.wt.is_executable('file1'))
1534.12.2 by Aaron Bentley
Added test for preserving file mode
1090
        transform, root = self.get_transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1091
        file1_id = transform.trans_id_tree_path('file1')
1534.12.2 by Aaron Bentley
Added test for preserving file mode
1092
        transform.delete_contents(file1_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1093
        transform.create_file([b'contents2'], file1_id)
1534.12.2 by Aaron Bentley
Added test for preserving file mode
1094
        transform.apply()
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
1095
        self.assertTrue(self.wt.is_executable('file1'))
1534.12.2 by Aaron Bentley
Added test for preserving file mode
1096
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
1097
    def test__set_mode_stats_correctly(self):
1098
        """_set_mode stats to determine file mode."""
1099
        if sys.platform == 'win32':
1100
            raise TestSkipped('chmod has no effect on win32')
1101
1102
        stat_paths = []
1103
        real_stat = os.stat
1104
        def instrumented_stat(path):
1105
            stat_paths.append(path)
1106
            return real_stat(path)
1107
1108
        transform, root = self.get_transform()
1109
6973.10.1 by Jelmer Vernooij
Fix some tests.
1110
        bar1_id = transform.new_file('bar', root, [b'bar contents 1\n'],
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1111
                                     file_id=b'bar-id-1', executable=False)
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
1112
        transform.apply()
1113
1114
        transform, root = self.get_transform()
1115
        bar1_id = transform.trans_id_tree_path('bar')
1116
        bar2_id = transform.trans_id_tree_path('bar2')
1117
        try:
1118
            os.stat = instrumented_stat
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1119
            transform.create_file([b'bar2 contents\n'], bar2_id, mode_id=bar1_id)
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
1120
        finally:
1121
            os.stat = real_stat
1122
            transform.finalize()
1123
1124
        bar1_abspath = self.wt.abspath('bar')
1125
        self.assertEqual([bar1_abspath], stat_paths)
1126
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1127
    def test_iter_changes(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
1128
        self.wt.set_root_id(b'eert_toor')
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1129
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1130
        transform.new_file('old', root, [b'blah'], b'id-1', True)
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1131
        transform.apply()
1132
        transform, root = self.get_transform()
1133
        try:
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1134
            self.assertEqual([], list(transform.iter_changes()))
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1135
            old = transform.trans_id_tree_path('old')
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1136
            transform.unversion_file(old)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1137
            self.assertEqual([(b'id-1', ('old', None), False, (True, False),
1138
                (b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1139
                (True, True))], list(transform.iter_changes()))
6973.10.1 by Jelmer Vernooij
Fix some tests.
1140
            transform.new_directory('new', root, b'id-1')
1141
            self.assertEqual([(b'id-1', ('old', 'new'), True, (True, True),
1142
                (b'eert_toor', b'eert_toor'), ('old', 'new'),
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1143
                ('file', 'directory'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1144
                (True, False))], list(transform.iter_changes()))
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1145
        finally:
1146
            transform.finalize()
1147
1148
    def test_iter_changes_new(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
1149
        self.wt.set_root_id(b'eert_toor')
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1150
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1151
        transform.new_file('old', root, [b'blah'])
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1152
        transform.apply()
1153
        transform, root = self.get_transform()
1154
        try:
1155
            old = transform.trans_id_tree_path('old')
6973.10.1 by Jelmer Vernooij
Fix some tests.
1156
            transform.version_file(b'id-1', old)
1157
            self.assertEqual([(b'id-1', (None, 'old'), False, (False, True),
1158
                (b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1159
                (False, False))], list(transform.iter_changes()))
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1160
        finally:
1161
            transform.finalize()
1162
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1163
    def test_iter_changes_modifications(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
1164
        self.wt.set_root_id(b'eert_toor')
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1165
        transform, root = self.get_transform()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1166
        transform.new_file('old', root, [b'blah'], b'id-1')
6973.10.1 by Jelmer Vernooij
Fix some tests.
1167
        transform.new_file('new', root, [b'blah'])
6973.13.2 by Jelmer Vernooij
Fix some more tests.
1168
        transform.new_directory('subdir', root, b'subdir-id')
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1169
        transform.apply()
1170
        transform, root = self.get_transform()
1171
        try:
1172
            old = transform.trans_id_tree_path('old')
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1173
            subdir = transform.trans_id_tree_path('subdir')
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1174
            new = transform.trans_id_tree_path('new')
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1175
            self.assertEqual([], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1176
1177
            #content deletion
1178
            transform.delete_contents(old)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1179
            self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1180
                (b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', None),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1181
                (False, False))], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1182
1183
            #content change
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1184
            transform.create_file([b'blah'], old)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1185
            self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1186
                (b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1187
                (False, False))], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1188
            transform.cancel_deletion(old)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1189
            self.assertEqual([('id-1', ('old', 'old'), True, (True, True),
6973.10.1 by Jelmer Vernooij
Fix some tests.
1190
                (b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1191
                (False, False))], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1192
            transform.cancel_creation(old)
1193
1194
            # move file_id to a different file
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1195
            self.assertEqual([], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1196
            transform.unversion_file(old)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1197
            transform.version_file(b'id-1', new)
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1198
            transform.adjust_path('old', root, new)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1199
            self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
2100.3.33 by Aaron Bentley
Handle unique roots in tests for TreeTransform.iter_changes
1200
                ('eert_toor', 'eert_toor'), ('old', 'old'), ('file', 'file'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1201
                (False, False))], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1202
            transform.cancel_versioning(new)
1203
            transform._removed_id = set()
1204
1205
            #execute bit
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1206
            self.assertEqual([], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1207
            transform.set_executability(True, old)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1208
            self.assertEqual([(b'id-1', ('old', 'old'), False, (True, True),
1209
                (b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1210
                (False, True))], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1211
            transform.set_executability(None, old)
1212
1213
            # filename
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1214
            self.assertEqual([], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1215
            transform.adjust_path('new', root, old)
1216
            transform._new_parent = {}
6973.10.1 by Jelmer Vernooij
Fix some tests.
1217
            self.assertEqual([(b'id-1', ('old', 'new'), False, (True, True),
1218
                (b'eert_toor', b'eert_toor'), ('old', 'new'), ('file', 'file'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1219
                (False, False))], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1220
            transform._new_name = {}
1221
1222
            # parent directory
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1223
            self.assertEqual([], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1224
            transform.adjust_path('new', subdir, old)
1225
            transform._new_name = {}
6973.10.1 by Jelmer Vernooij
Fix some tests.
1226
            self.assertEqual([(b'id-1', ('old', 'subdir/old'), False,
1227
                (True, True), (b'eert_toor', b'subdir-id'), ('old', 'old'),
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
1228
                ('file', 'file'), (False, False))],
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1229
                list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1230
            transform._new_path = {}
1231
1232
        finally:
1233
            transform.finalize()
1234
1551.11.7 by Aaron Bentley
Stop modified flag bleeding into later changes
1235
    def test_iter_changes_modified_bleed(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
1236
        self.wt.set_root_id(b'eert_toor')
1551.11.7 by Aaron Bentley
Stop modified flag bleeding into later changes
1237
        """Modified flag should not bleed from one change to another"""
1238
        # unfortunately, we have no guarantee that file1 (which is modified)
1239
        # will be applied before file2.  And if it's applied after file2, it
1240
        # obviously can't bleed into file2's change output.  But for now, it
1241
        # works.
1242
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1243
        transform.new_file('file1', root, [b'blah'], b'id-1')
1244
        transform.new_file('file2', root, [b'blah'], b'id-2')
1551.11.7 by Aaron Bentley
Stop modified flag bleeding into later changes
1245
        transform.apply()
1246
        transform, root = self.get_transform()
1247
        try:
6973.10.1 by Jelmer Vernooij
Fix some tests.
1248
            transform.delete_contents(transform.trans_id_file_id(b'id-1'))
1551.11.7 by Aaron Bentley
Stop modified flag bleeding into later changes
1249
            transform.set_executability(True,
6973.10.1 by Jelmer Vernooij
Fix some tests.
1250
            transform.trans_id_file_id(b'id-2'))
1251
            self.assertEqual([(b'id-1', (u'file1', u'file1'), True, (True, True),
1252
                (b'eert_toor', b'eert_toor'), ('file1', u'file1'),
1551.11.7 by Aaron Bentley
Stop modified flag bleeding into later changes
1253
                ('file', None), (False, False)),
6973.10.1 by Jelmer Vernooij
Fix some tests.
1254
                (b'id-2', (u'file2', u'file2'), False, (True, True),
1255
                (b'eert_toor', b'eert_toor'), ('file2', u'file2'),
1551.11.7 by Aaron Bentley
Stop modified flag bleeding into later changes
1256
                ('file', 'file'), (False, True))],
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1257
                list(transform.iter_changes()))
1551.11.7 by Aaron Bentley
Stop modified flag bleeding into later changes
1258
        finally:
1259
            transform.finalize()
1260
1551.10.37 by Aaron Bentley
recommit of TreeTransform._iter_changes fix with missing files
1261
    def test_iter_changes_move_missing(self):
1262
        """Test moving ids with no files around"""
6855.4.1 by Jelmer Vernooij
Yet more bees.
1263
        self.wt.set_root_id(b'toor_eert')
1551.10.37 by Aaron Bentley
recommit of TreeTransform._iter_changes fix with missing files
1264
        # Need two steps because versioning a non-existant file is a conflict.
1265
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1266
        transform.new_directory('floater', root, b'floater-id')
1551.10.37 by Aaron Bentley
recommit of TreeTransform._iter_changes fix with missing files
1267
        transform.apply()
1268
        transform, root = self.get_transform()
1269
        transform.delete_contents(transform.trans_id_tree_path('floater'))
1270
        transform.apply()
1271
        transform, root = self.get_transform()
1272
        floater = transform.trans_id_tree_path('floater')
1273
        try:
1274
            transform.adjust_path('flitter', root, floater)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1275
            self.assertEqual([(b'floater-id', ('floater', 'flitter'), False,
1551.10.37 by Aaron Bentley
recommit of TreeTransform._iter_changes fix with missing files
1276
            (True, True), ('toor_eert', 'toor_eert'), ('floater', 'flitter'),
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1277
            (None, None), (False, False))], list(transform.iter_changes()))
1551.10.37 by Aaron Bentley
recommit of TreeTransform._iter_changes fix with missing files
1278
        finally:
1279
            transform.finalize()
1280
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1281
    def test_iter_changes_pointless(self):
1282
        """Ensure that no-ops are not treated as modifications"""
6855.4.1 by Jelmer Vernooij
Yet more bees.
1283
        self.wt.set_root_id(b'eert_toor')
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1284
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1285
        transform.new_file('old', root, [b'blah'], b'id-1')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1286
        transform.new_directory('subdir', root, b'subdir-id')
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1287
        transform.apply()
1288
        transform, root = self.get_transform()
1289
        try:
1290
            old = transform.trans_id_tree_path('old')
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1291
            subdir = transform.trans_id_tree_path('subdir')
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1292
            self.assertEqual([], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1293
            transform.delete_contents(subdir)
1294
            transform.create_directory(subdir)
1295
            transform.set_executability(False, old)
1296
            transform.unversion_file(old)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1297
            transform.version_file(b'id-1', old)
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1298
            transform.adjust_path('old', root, old)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
1299
            self.assertEqual([], list(transform.iter_changes()))
1551.11.2 by Aaron Bentley
Get kind change detection working for iter_changes
1300
        finally:
1301
            transform.finalize()
1534.7.93 by Aaron Bentley
Added text merge test
1302
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
1303
    def test_rename_count(self):
1304
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1305
        transform.new_file('name1', root, [b'contents'])
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
1306
        self.assertEqual(transform.rename_count, 0)
1307
        transform.apply()
1308
        self.assertEqual(transform.rename_count, 1)
1309
        transform2, root = self.get_transform()
2502.1.8 by Aaron Bentley
Updates from review comments
1310
        transform2.adjust_path('name2', root,
1311
                               transform2.trans_id_tree_path('name1'))
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
1312
        self.assertEqual(transform2.rename_count, 0)
1313
        transform2.apply()
1314
        self.assertEqual(transform2.rename_count, 2)
1315
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1316
    def test_change_parent(self):
2502.1.8 by Aaron Bentley
Updates from review comments
1317
        """Ensure that after we change a parent, the results are still right.
1318
1319
        Renames and parent changes on pending transforms can happen as part
1320
        of conflict resolution, and are explicitly permitted by the
1321
        TreeTransform API.
1322
1323
        This test ensures they work correctly with the rename-avoidance
1324
        optimization.
1325
        """
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1326
        transform, root = self.get_transform()
2502.1.8 by Aaron Bentley
Updates from review comments
1327
        parent1 = transform.new_directory('parent1', root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1328
        child1 = transform.new_file('child1', parent1, [b'contents'])
2502.1.8 by Aaron Bentley
Updates from review comments
1329
        parent2 = transform.new_directory('parent2', root)
1330
        transform.adjust_path('child1', parent2, child1)
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1331
        transform.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1332
        self.assertPathDoesNotExist(self.wt.abspath('parent1/child1'))
1333
        self.assertPathExists(self.wt.abspath('parent2/child1'))
2502.1.8 by Aaron Bentley
Updates from review comments
1334
        # rename limbo/new-1 => parent1, rename limbo/new-3 => parent2
1335
        # no rename for child1 (counting only renames during apply)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1336
        self.assertEqual(2, transform.rename_count)
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1337
1338
    def test_cancel_parent(self):
1339
        """Cancelling a parent doesn't cause deletion of a non-empty directory
1340
1341
        This is like the test_change_parent, except that we cancel the parent
1342
        before adjusting the path.  The transform must detect that the
1343
        directory is non-empty, and move children to safe locations.
1344
        """
1345
        transform, root = self.get_transform()
2502.1.8 by Aaron Bentley
Updates from review comments
1346
        parent1 = transform.new_directory('parent1', root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1347
        child1 = transform.new_file('child1', parent1, [b'contents'])
1348
        child2 = transform.new_file('child2', parent1, [b'contents'])
2502.1.8 by Aaron Bentley
Updates from review comments
1349
        try:
1350
            transform.cancel_creation(parent1)
1351
        except OSError:
1352
            self.fail('Failed to move child1 before deleting parent1')
1353
        transform.cancel_creation(child2)
1354
        transform.create_directory(parent1)
1355
        try:
1356
            transform.cancel_creation(parent1)
1357
        # If the transform incorrectly believes that child2 is still in
1358
        # parent1's limbo directory, it will try to rename it and fail
1359
        # because was already moved by the first cancel_creation.
1360
        except OSError:
1361
            self.fail('Transform still thinks child2 is a child of parent1')
1362
        parent2 = transform.new_directory('parent2', root)
1363
        transform.adjust_path('child1', parent2, child1)
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1364
        transform.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1365
        self.assertPathDoesNotExist(self.wt.abspath('parent1'))
1366
        self.assertPathExists(self.wt.abspath('parent2/child1'))
2502.1.8 by Aaron Bentley
Updates from review comments
1367
        # rename limbo/new-3 => parent2, rename limbo/new-2 => child1
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1368
        self.assertEqual(2, transform.rename_count)
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1369
1370
    def test_adjust_and_cancel(self):
2502.1.8 by Aaron Bentley
Updates from review comments
1371
        """Make sure adjust_path keeps track of limbo children properly"""
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1372
        transform, root = self.get_transform()
2502.1.8 by Aaron Bentley
Updates from review comments
1373
        parent1 = transform.new_directory('parent1', root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1374
        child1 = transform.new_file('child1', parent1, [b'contents'])
2502.1.8 by Aaron Bentley
Updates from review comments
1375
        parent2 = transform.new_directory('parent2', root)
1376
        transform.adjust_path('child1', parent2, child1)
1377
        transform.cancel_creation(child1)
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1378
        try:
2502.1.8 by Aaron Bentley
Updates from review comments
1379
            transform.cancel_creation(parent1)
1380
        # if the transform thinks child1 is still in parent1's limbo
1381
        # directory, it will attempt to move it and fail.
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1382
        except OSError:
2502.1.8 by Aaron Bentley
Updates from review comments
1383
            self.fail('Transform still thinks child1 is a child of parent1')
2502.1.2 by Aaron Bentley
Make the limited-renames functionality safer in the general case
1384
        transform.finalize()
1385
2502.1.3 by Aaron Bentley
Don't cause errors when creating contents for trans_ids with no parent/name
1386
    def test_noname_contents(self):
2502.1.8 by Aaron Bentley
Updates from review comments
1387
        """TreeTransform should permit deferring naming files."""
2502.1.3 by Aaron Bentley
Don't cause errors when creating contents for trans_ids with no parent/name
1388
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1389
        parent = transform.trans_id_file_id(b'parent-id')
2502.1.3 by Aaron Bentley
Don't cause errors when creating contents for trans_ids with no parent/name
1390
        try:
2502.1.8 by Aaron Bentley
Updates from review comments
1391
            transform.create_directory(parent)
2502.1.3 by Aaron Bentley
Don't cause errors when creating contents for trans_ids with no parent/name
1392
        except KeyError:
1393
            self.fail("Can't handle contents with no name")
1394
        transform.finalize()
1395
2502.1.9 by Aaron Bentley
Add additional test for no-name contents
1396
    def test_noname_contents_nested(self):
1397
        """TreeTransform should permit deferring naming files."""
1398
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1399
        parent = transform.trans_id_file_id(b'parent-id')
2502.1.9 by Aaron Bentley
Add additional test for no-name contents
1400
        try:
1401
            transform.create_directory(parent)
1402
        except KeyError:
1403
            self.fail("Can't handle contents with no name")
1404
        child = transform.new_directory('child', parent)
1405
        transform.adjust_path('parent', root, parent)
1406
        transform.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1407
        self.assertPathExists(self.wt.abspath('parent/child'))
2502.1.9 by Aaron Bentley
Add additional test for no-name contents
1408
        self.assertEqual(1, transform.rename_count)
1409
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1410
    def test_reuse_name(self):
1411
        """Avoid reusing the same limbo name for different files"""
1412
        transform, root = self.get_transform()
2502.1.8 by Aaron Bentley
Updates from review comments
1413
        parent = transform.new_directory('parent', root)
1414
        child1 = transform.new_directory('child', parent)
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1415
        try:
2502.1.8 by Aaron Bentley
Updates from review comments
1416
            child2 = transform.new_directory('child', parent)
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1417
        except OSError:
1418
            self.fail('Tranform tried to use the same limbo name twice')
2502.1.8 by Aaron Bentley
Updates from review comments
1419
        transform.adjust_path('child2', parent, child2)
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1420
        transform.apply()
2502.1.8 by Aaron Bentley
Updates from review comments
1421
        # limbo/new-1 => parent, limbo/new-3 => parent/child2
1422
        # child2 is put into top-level limbo because child1 has already
1423
        # claimed the direct limbo path when child2 is created.  There is no
1424
        # advantage in renaming files once they're in top-level limbo, except
1425
        # as part of apply.
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1426
        self.assertEqual(2, transform.rename_count)
1427
1428
    def test_reuse_when_first_moved(self):
1429
        """Don't avoid direct paths when it is safe to use them"""
1430
        transform, root = self.get_transform()
2502.1.8 by Aaron Bentley
Updates from review comments
1431
        parent = transform.new_directory('parent', root)
1432
        child1 = transform.new_directory('child', parent)
1433
        transform.adjust_path('child1', parent, child1)
1434
        child2 = transform.new_directory('child', parent)
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1435
        transform.apply()
2502.1.8 by Aaron Bentley
Updates from review comments
1436
        # limbo/new-1 => parent
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1437
        self.assertEqual(1, transform.rename_count)
1438
1439
    def test_reuse_after_cancel(self):
1440
        """Don't avoid direct paths when it is safe to use them"""
1441
        transform, root = self.get_transform()
2502.1.8 by Aaron Bentley
Updates from review comments
1442
        parent2 = transform.new_directory('parent2', root)
1443
        child1 = transform.new_directory('child1', parent2)
1444
        transform.cancel_creation(parent2)
1445
        transform.create_directory(parent2)
1446
        child2 = transform.new_directory('child1', parent2)
1447
        transform.adjust_path('child2', parent2, child1)
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1448
        transform.apply()
2502.1.8 by Aaron Bentley
Updates from review comments
1449
        # limbo/new-1 => parent2, limbo/new-2 => parent2/child1
2502.1.4 by Aaron Bentley
Ensure we only reuse limbo names appropriately
1450
        self.assertEqual(2, transform.rename_count)
1451
2502.1.7 by Aaron Bentley
Fix finalize deletion ordering
1452
    def test_finalize_order(self):
2502.1.8 by Aaron Bentley
Updates from review comments
1453
        """Finalize must be done in child-to-parent order"""
2502.1.7 by Aaron Bentley
Fix finalize deletion ordering
1454
        transform, root = self.get_transform()
2502.1.8 by Aaron Bentley
Updates from review comments
1455
        parent = transform.new_directory('parent', root)
1456
        child = transform.new_directory('child', parent)
2502.1.7 by Aaron Bentley
Fix finalize deletion ordering
1457
        try:
1458
            transform.finalize()
1459
        except OSError:
2502.1.8 by Aaron Bentley
Updates from review comments
1460
            self.fail('Tried to remove parent before child1')
2502.1.7 by Aaron Bentley
Fix finalize deletion ordering
1461
2502.1.13 by Aaron Bentley
Updates from review
1462
    def test_cancel_with_cancelled_child_should_succeed(self):
2502.1.12 by Aaron Bentley
Avoid renaming children with no content
1463
        transform, root = self.get_transform()
1464
        parent = transform.new_directory('parent', root)
1465
        child = transform.new_directory('child', parent)
1466
        transform.cancel_creation(child)
2502.1.13 by Aaron Bentley
Updates from review
1467
        transform.cancel_creation(parent)
2502.1.12 by Aaron Bentley
Avoid renaming children with no content
1468
        transform.finalize()
1469
3638.3.15 by Vincent Ladeuil
Fix test_case_insensitive_clash to pass on all platforms (renamed too).
1470
    def test_rollback_on_directory_clash(self):
3063.1.1 by Alexander Belchenko
Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).
1471
        def tt_helper():
3638.3.17 by Vincent Ladeuil
Fixed as per Aaron's review.
1472
            wt = self.make_branch_and_tree('.')
3063.1.1 by Alexander Belchenko
Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).
1473
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
1474
            try:
3638.3.15 by Vincent Ladeuil
Fix test_case_insensitive_clash to pass on all platforms (renamed too).
1475
                foo = tt.new_directory('foo', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1476
                tt.new_file('bar', foo, [b'foobar'])
3638.3.15 by Vincent Ladeuil
Fix test_case_insensitive_clash to pass on all platforms (renamed too).
1477
                baz = tt.new_directory('baz', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1478
                tt.new_file('qux', baz, [b'quux'])
3638.3.15 by Vincent Ladeuil
Fix test_case_insensitive_clash to pass on all platforms (renamed too).
1479
                # Ask for a rename 'foo' -> 'baz'
1480
                tt.adjust_path('baz', tt.root, foo)
3063.1.3 by Aaron Bentley
Update for Linux
1481
                # Lie to tt that we've already resolved all conflicts.
3063.1.1 by Alexander Belchenko
Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).
1482
                tt.apply(no_conflicts=True)
3063.1.3 by Aaron Bentley
Update for Linux
1483
            except:
3063.1.1 by Alexander Belchenko
Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).
1484
                wt.unlock()
3063.1.3 by Aaron Bentley
Update for Linux
1485
                raise
3638.3.17 by Vincent Ladeuil
Fixed as per Aaron's review.
1486
        # The rename will fail because the target directory is not empty (but
1487
        # raises FileExists anyway).
3063.1.1 by Alexander Belchenko
Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).
1488
        err = self.assertRaises(errors.FileExists, tt_helper)
6269.1.1 by Martin Packman
Only assert FileExists path in test_transform directory clash tests to avoid stringification fallout
1489
        self.assertEndsWith(err.path, "/baz")
3063.1.1 by Alexander Belchenko
Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).
1490
3063.1.2 by Alexander Belchenko
test for two directories clash
1491
    def test_two_directories_clash(self):
1492
        def tt_helper():
1493
            wt = self.make_branch_and_tree('.')
1494
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
1495
            try:
3063.1.3 by Aaron Bentley
Update for Linux
1496
                foo_1 = tt.new_directory('foo', tt.root)
1497
                tt.new_directory('bar', foo_1)
3638.3.15 by Vincent Ladeuil
Fix test_case_insensitive_clash to pass on all platforms (renamed too).
1498
                # Adding the same directory with a different content
3063.1.3 by Aaron Bentley
Update for Linux
1499
                foo_2 = tt.new_directory('foo', tt.root)
1500
                tt.new_directory('baz', foo_2)
1501
                # Lie to tt that we've already resolved all conflicts.
3063.1.2 by Alexander Belchenko
test for two directories clash
1502
                tt.apply(no_conflicts=True)
3063.1.3 by Aaron Bentley
Update for Linux
1503
            except:
3063.1.2 by Alexander Belchenko
test for two directories clash
1504
                wt.unlock()
3063.1.3 by Aaron Bentley
Update for Linux
1505
                raise
3063.1.2 by Alexander Belchenko
test for two directories clash
1506
        err = self.assertRaises(errors.FileExists, tt_helper)
6269.1.1 by Martin Packman
Only assert FileExists path in test_transform directory clash tests to avoid stringification fallout
1507
        self.assertEndsWith(err.path, "/foo")
3063.1.2 by Alexander Belchenko
test for two directories clash
1508
3100.1.1 by Aaron Bentley
Fix ImmortalLimbo errors when transforms fail
1509
    def test_two_directories_clash_finalize(self):
1510
        def tt_helper():
1511
            wt = self.make_branch_and_tree('.')
1512
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
1513
            try:
1514
                foo_1 = tt.new_directory('foo', tt.root)
1515
                tt.new_directory('bar', foo_1)
3638.3.15 by Vincent Ladeuil
Fix test_case_insensitive_clash to pass on all platforms (renamed too).
1516
                # Adding the same directory with a different content
3100.1.1 by Aaron Bentley
Fix ImmortalLimbo errors when transforms fail
1517
                foo_2 = tt.new_directory('foo', tt.root)
1518
                tt.new_directory('baz', foo_2)
1519
                # Lie to tt that we've already resolved all conflicts.
1520
                tt.apply(no_conflicts=True)
1521
            except:
1522
                tt.finalize()
1523
                raise
1524
        err = self.assertRaises(errors.FileExists, tt_helper)
6269.1.1 by Martin Packman
Only assert FileExists path in test_transform directory clash tests to avoid stringification fallout
1525
        self.assertEndsWith(err.path, "/foo")
3100.1.1 by Aaron Bentley
Fix ImmortalLimbo errors when transforms fail
1526
3535.6.1 by James Westby
Handle a file turning in to a directory in TreeTransform.
1527
    def test_file_to_directory(self):
1528
        wt = self.make_branch_and_tree('.')
3535.6.2 by James Westby
Fixes from review. Thanks Aaron and John.
1529
        self.build_tree(['foo'])
3535.6.1 by James Westby
Handle a file turning in to a directory in TreeTransform.
1530
        wt.add(['foo'])
3590.3.1 by James Westby
Make TreeTransform update the inventory with new kind information.
1531
        wt.commit("one")
3535.6.1 by James Westby
Handle a file turning in to a directory in TreeTransform.
1532
        tt = TreeTransform(wt)
3535.6.2 by James Westby
Fixes from review. Thanks Aaron and John.
1533
        self.addCleanup(tt.finalize)
3535.6.3 by James Westby
Fix the test to not create transform conflicts.
1534
        foo_trans_id = tt.trans_id_tree_path("foo")
1535
        tt.delete_contents(foo_trans_id)
1536
        tt.create_directory(foo_trans_id)
1537
        bar_trans_id = tt.trans_id_tree_path("foo/bar")
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1538
        tt.create_file([b"aa\n"], bar_trans_id)
3535.6.3 by James Westby
Fix the test to not create transform conflicts.
1539
        tt.version_file("bar-1", bar_trans_id)
3535.6.2 by James Westby
Fixes from review. Thanks Aaron and John.
1540
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1541
        self.assertPathExists("foo/bar")
3590.3.2 by James Westby
Handle ->symlink changes as well.
1542
        wt.lock_read()
1543
        try:
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
1544
            self.assertEqual(wt.kind("foo"), "directory")
3590.3.2 by James Westby
Handle ->symlink changes as well.
1545
        finally:
1546
            wt.unlock()
3590.3.1 by James Westby
Make TreeTransform update the inventory with new kind information.
1547
        wt.commit("two")
1548
        changes = wt.changes_from(wt.basis_tree())
1549
        self.assertFalse(changes.has_changed(), changes)
3535.6.1 by James Westby
Handle a file turning in to a directory in TreeTransform.
1550
3590.3.2 by James Westby
Handle ->symlink changes as well.
1551
    def test_file_to_symlink(self):
3590.3.3 by James Westby
Make ->file changes work as well.
1552
        self.requireFeature(SymlinkFeature)
3590.3.2 by James Westby
Handle ->symlink changes as well.
1553
        wt = self.make_branch_and_tree('.')
1554
        self.build_tree(['foo'])
1555
        wt.add(['foo'])
1556
        wt.commit("one")
1557
        tt = TreeTransform(wt)
1558
        self.addCleanup(tt.finalize)
1559
        foo_trans_id = tt.trans_id_tree_path("foo")
1560
        tt.delete_contents(foo_trans_id)
1561
        tt.create_symlink("bar", foo_trans_id)
1562
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1563
        self.assertPathExists("foo")
3590.3.2 by James Westby
Handle ->symlink changes as well.
1564
        wt.lock_read()
1565
        self.addCleanup(wt.unlock)
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
1566
        self.assertEqual(wt.kind("foo"), "symlink")
3590.3.2 by James Westby
Handle ->symlink changes as well.
1567
3590.3.3 by James Westby
Make ->file changes work as well.
1568
    def test_dir_to_file(self):
1569
        wt = self.make_branch_and_tree('.')
1570
        self.build_tree(['foo/', 'foo/bar'])
1571
        wt.add(['foo', 'foo/bar'])
1572
        wt.commit("one")
1573
        tt = TreeTransform(wt)
1574
        self.addCleanup(tt.finalize)
1575
        foo_trans_id = tt.trans_id_tree_path("foo")
1576
        bar_trans_id = tt.trans_id_tree_path("foo/bar")
1577
        tt.delete_contents(foo_trans_id)
1578
        tt.delete_versioned(bar_trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1579
        tt.create_file([b"aa\n"], foo_trans_id)
3590.3.3 by James Westby
Make ->file changes work as well.
1580
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1581
        self.assertPathExists("foo")
3590.3.3 by James Westby
Make ->file changes work as well.
1582
        wt.lock_read()
1583
        self.addCleanup(wt.unlock)
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
1584
        self.assertEqual(wt.kind("foo"), "file")
3590.3.3 by James Westby
Make ->file changes work as well.
1585
3590.3.4 by James Westby
Add a test for creating hardlinks as well.
1586
    def test_dir_to_hardlink(self):
3590.3.5 by James Westby
Use HardlinkFeature for the hardlink test.
1587
        self.requireFeature(HardlinkFeature)
3590.3.4 by James Westby
Add a test for creating hardlinks as well.
1588
        wt = self.make_branch_and_tree('.')
1589
        self.build_tree(['foo/', 'foo/bar'])
1590
        wt.add(['foo', 'foo/bar'])
1591
        wt.commit("one")
1592
        tt = TreeTransform(wt)
1593
        self.addCleanup(tt.finalize)
1594
        foo_trans_id = tt.trans_id_tree_path("foo")
1595
        bar_trans_id = tt.trans_id_tree_path("foo/bar")
1596
        tt.delete_contents(foo_trans_id)
1597
        tt.delete_versioned(bar_trans_id)
1598
        self.build_tree(['baz'])
1599
        tt.create_hardlink("baz", foo_trans_id)
1600
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1601
        self.assertPathExists("foo")
1602
        self.assertPathExists("baz")
3590.3.4 by James Westby
Add a test for creating hardlinks as well.
1603
        wt.lock_read()
1604
        self.addCleanup(wt.unlock)
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
1605
        self.assertEqual(wt.kind("foo"), "file")
3590.3.4 by James Westby
Add a test for creating hardlinks as well.
1606
3619.2.10 by Aaron Bentley
Compensate for stale entries in TT._needs_rename
1607
    def test_no_final_path(self):
1608
        transform, root = self.get_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1609
        trans_id = transform.trans_id_file_id(b'foo')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1610
        transform.create_file([b'bar'], trans_id)
3619.2.10 by Aaron Bentley
Compensate for stale entries in TT._needs_rename
1611
        transform.cancel_creation(trans_id)
1612
        transform.apply()
1613
3363.17.24 by Aaron Bentley
Implement create_by_tree
1614
    def test_create_from_tree(self):
1615
        tree1 = self.make_branch_and_tree('tree1')
6855.4.1 by Jelmer Vernooij
Yet more bees.
1616
        self.build_tree_contents([('tree1/foo/',), ('tree1/bar', b'baz')])
1617
        tree1.add(['foo', 'bar'], [b'foo-id', b'bar-id'])
3363.17.24 by Aaron Bentley
Implement create_by_tree
1618
        tree2 = self.make_branch_and_tree('tree2')
1619
        tt = TreeTransform(tree2)
1620
        foo_trans_id = tt.create_path('foo', tt.root)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1621
        create_from_tree(tt, foo_trans_id, tree1, 'foo', file_id=b'foo-id')
3363.17.24 by Aaron Bentley
Implement create_by_tree
1622
        bar_trans_id = tt.create_path('bar', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1623
        create_from_tree(tt, bar_trans_id, tree1, 'bar', file_id=b'bar-id')
3363.17.24 by Aaron Bentley
Implement create_by_tree
1624
        tt.apply()
1625
        self.assertEqual('directory', osutils.file_kind('tree2/foo'))
6973.10.1 by Jelmer Vernooij
Fix some tests.
1626
        self.assertFileEqual(b'baz', 'tree2/bar')
3363.17.24 by Aaron Bentley
Implement create_by_tree
1627
3363.17.25 by Aaron Bentley
remove get_inventory_entry, replace with create_from_tree
1628
    def test_create_from_tree_bytes(self):
1629
        """Provided lines are used instead of tree content."""
1630
        tree1 = self.make_branch_and_tree('tree1')
6973.10.1 by Jelmer Vernooij
Fix some tests.
1631
        self.build_tree_contents([('tree1/foo', b'bar'),])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1632
        tree1.add('foo', b'foo-id')
3363.17.25 by Aaron Bentley
remove get_inventory_entry, replace with create_from_tree
1633
        tree2 = self.make_branch_and_tree('tree2')
1634
        tt = TreeTransform(tree2)
1635
        foo_trans_id = tt.create_path('foo', tt.root)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1636
        create_from_tree(tt, foo_trans_id, tree1, 'foo', file_id=b'foo-id',
6973.10.1 by Jelmer Vernooij
Fix some tests.
1637
                         chunks=[b'qux'])
3363.17.25 by Aaron Bentley
remove get_inventory_entry, replace with create_from_tree
1638
        tt.apply()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1639
        self.assertFileEqual(b'qux', 'tree2/foo')
3363.17.25 by Aaron Bentley
remove get_inventory_entry, replace with create_from_tree
1640
1641
    def test_create_from_tree_symlink(self):
3363.17.24 by Aaron Bentley
Implement create_by_tree
1642
        self.requireFeature(SymlinkFeature)
1643
        tree1 = self.make_branch_and_tree('tree1')
1644
        os.symlink('bar', 'tree1/foo')
6855.4.1 by Jelmer Vernooij
Yet more bees.
1645
        tree1.add('foo', b'foo-id')
3363.17.24 by Aaron Bentley
Implement create_by_tree
1646
        tt = TreeTransform(self.make_branch_and_tree('tree2'))
1647
        foo_trans_id = tt.create_path('foo', tt.root)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1648
        create_from_tree(tt, foo_trans_id, tree1, 'foo', file_id=b'foo-id')
3363.17.24 by Aaron Bentley
Implement create_by_tree
1649
        tt.apply()
1650
        self.assertEqual('bar', os.readlink('tree2/foo'))
1651
2502.1.3 by Aaron Bentley
Don't cause errors when creating contents for trans_ids with no parent/name
1652
1534.7.93 by Aaron Bentley
Added text merge test
1653
class TransformGroup(object):
3063.1.1 by Alexander Belchenko
Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).
1654
1731.1.33 by Aaron Bentley
Revert no-special-root changes
1655
    def __init__(self, dirname, root_id):
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
1656
        self.name = dirname
1534.7.93 by Aaron Bentley
Added text merge test
1657
        os.mkdir(dirname)
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
1658
        self.wt = ControlDir.create_standalone_workingtree(dirname)
1731.1.33 by Aaron Bentley
Revert no-special-root changes
1659
        self.wt.set_root_id(root_id)
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
1660
        self.b = self.wt.branch
1534.7.93 by Aaron Bentley
Added text merge test
1661
        self.tt = TreeTransform(self.wt)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1662
        self.root = self.tt.trans_id_tree_path('')
1534.7.93 by Aaron Bentley
Added text merge test
1663
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
1664
1534.7.95 by Aaron Bentley
Added more text merge tests
1665
def conflict_text(tree, merge):
6973.10.1 by Jelmer Vernooij
Fix some tests.
1666
    template = b'%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
1667
    return template % (b'<' * 7, tree, b'=' * 7, merge, b'>' * 7)
1534.7.95 by Aaron Bentley
Added more text merge tests
1668
1534.7.93 by Aaron Bentley
Added text merge test
1669
5954.2.2 by Aaron Bentley
Include parent id changes for changed inventory entries.
1670
class TestInventoryAltered(tests.TestCaseWithTransport):
1671
1672
    def test_inventory_altered_unchanged(self):
1673
        tree = self.make_branch_and_tree('tree')
1674
        self.build_tree(['tree/foo'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1675
        tree.add('foo', b'foo-id')
5954.2.2 by Aaron Bentley
Include parent id changes for changed inventory entries.
1676
        with TransformPreview(tree) as tt:
1677
            self.assertEqual([], tt._inventory_altered())
1678
1679
    def test_inventory_altered_changed_parent_id(self):
1680
        tree = self.make_branch_and_tree('tree')
1681
        self.build_tree(['tree/foo'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1682
        tree.add('foo', b'foo-id')
5954.2.2 by Aaron Bentley
Include parent id changes for changed inventory entries.
1683
        with TransformPreview(tree) as tt:
1684
            tt.unversion_file(tt.root)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1685
            tt.version_file(b'new-id', tt.root)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1686
            foo_trans_id = tt.trans_id_tree_path('foo')
5954.2.2 by Aaron Bentley
Include parent id changes for changed inventory entries.
1687
            foo_tuple = ('foo', foo_trans_id)
1688
            root_tuple = ('', tt.root)
1689
            self.assertEqual([root_tuple, foo_tuple], tt._inventory_altered())
1690
1691
    def test_inventory_altered_noop_changed_parent_id(self):
1692
        tree = self.make_branch_and_tree('tree')
1693
        self.build_tree(['tree/foo'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1694
        tree.add('foo', b'foo-id')
5954.2.2 by Aaron Bentley
Include parent id changes for changed inventory entries.
1695
        with TransformPreview(tree) as tt:
1696
            tt.unversion_file(tt.root)
1697
            tt.version_file(tree.get_root_id(), tt.root)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1698
            foo_trans_id = tt.trans_id_tree_path('foo')
5954.2.2 by Aaron Bentley
Include parent id changes for changed inventory entries.
1699
            self.assertEqual([], tt._inventory_altered())
1700
1701
1534.7.93 by Aaron Bentley
Added text merge test
1702
class TestTransformMerge(TestCaseInTempDir):
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
1703
1534.7.93 by Aaron Bentley
Added text merge test
1704
    def test_text_merge(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
1705
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
1706
        base = TransformGroup("base", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1707
        base.tt.new_file('a', base.root, [b'a\nb\nc\nd\be\n'], b'a')
1708
        base.tt.new_file('b', base.root, [b'b1'], b'b')
1709
        base.tt.new_file('c', base.root, [b'c'], b'c')
1710
        base.tt.new_file('d', base.root, [b'd'], b'd')
1711
        base.tt.new_file('e', base.root, [b'e'], b'e')
1712
        base.tt.new_file('f', base.root, [b'f'], b'f')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1713
        base.tt.new_directory('g', base.root, b'g')
1714
        base.tt.new_directory('h', base.root, b'h')
1534.7.93 by Aaron Bentley
Added text merge test
1715
        base.tt.apply()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
1716
        other = TransformGroup("other", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1717
        other.tt.new_file('a', other.root, [b'y\nb\nc\nd\be\n'], b'a')
1718
        other.tt.new_file('b', other.root, [b'b2'], b'b')
1719
        other.tt.new_file('c', other.root, [b'c2'], b'c')
1720
        other.tt.new_file('d', other.root, [b'd'], b'd')
1721
        other.tt.new_file('e', other.root, [b'e2'], b'e')
1722
        other.tt.new_file('f', other.root, [b'f'], b'f')
1723
        other.tt.new_file('g', other.root, [b'g'], b'g')
1724
        other.tt.new_file('h', other.root, [b'h\ni\nj\nk\n'], b'h')
1725
        other.tt.new_file('i', other.root, [b'h\ni\nj\nk\n'], b'i')
1534.7.93 by Aaron Bentley
Added text merge test
1726
        other.tt.apply()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
1727
        this = TransformGroup("this", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1728
        this.tt.new_file('a', this.root, [b'a\nb\nc\nd\bz\n'], b'a')
1729
        this.tt.new_file('b', this.root, [b'b'], b'b')
1730
        this.tt.new_file('c', this.root, [b'c'], b'c')
1731
        this.tt.new_file('d', this.root, [b'd2'], b'd')
1732
        this.tt.new_file('e', this.root, [b'e2'], b'e')
1733
        this.tt.new_file('f', this.root, [b'f'], b'f')
1734
        this.tt.new_file('g', this.root, [b'g'], b'g')
1735
        this.tt.new_file('h', this.root, [b'1\n2\n3\n4\n'], b'h')
1736
        this.tt.new_file('i', this.root, [b'1\n2\n3\n4\n'], b'i')
1534.7.93 by Aaron Bentley
Added text merge test
1737
        this.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
1738
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
3008.1.6 by Michael Hudson
chop up Merge3Merger.__init__ into pieces
1739
1534.7.95 by Aaron Bentley
Added more text merge tests
1740
        # textual merge
6973.10.1 by Jelmer Vernooij
Fix some tests.
1741
        with this.wt.get_file(this.wt.id2path(b'a')) as f:
1742
            self.assertEqual(f.read(), b'y\nb\nc\nd\bz\n')
1534.7.95 by Aaron Bentley
Added more text merge tests
1743
        # three-way text conflict
6973.10.1 by Jelmer Vernooij
Fix some tests.
1744
        with this.wt.get_file(this.wt.id2path(b'b')) as f:
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1745
            self.assertEqual(f.read(), conflict_text(b'b', b'b2'))
1534.7.95 by Aaron Bentley
Added more text merge tests
1746
        # OTHER wins
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1747
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'c')).read(), b'c2')
1534.7.95 by Aaron Bentley
Added more text merge tests
1748
        # THIS wins
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1749
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'd')).read(), b'd2')
1534.7.95 by Aaron Bentley
Added more text merge tests
1750
        # Ambigious clean merge
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1751
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'e')).read(), b'e2')
1534.7.95 by Aaron Bentley
Added more text merge tests
1752
        # No change
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1753
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'f')).read(), b'f')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1754
        # Correct correct results when THIS == OTHER
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1755
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'g')).read(), b'g')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
1756
        # Text conflict when THIS & OTHER are text and BASE is dir
6855.4.1 by Jelmer Vernooij
Yet more bees.
1757
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'h')).read(),
6973.10.1 by Jelmer Vernooij
Fix some tests.
1758
                         conflict_text(b'1\n2\n3\n4\n', b'h\ni\nj\nk\n'))
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
1759
        self.assertEqual(this.wt.get_file('h.THIS').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1760
                         b'1\n2\n3\n4\n')
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
1761
        self.assertEqual(this.wt.get_file('h.OTHER').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1762
                         b'h\ni\nj\nk\n')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
1763
        self.assertEqual(file_kind(this.wt.abspath('h.BASE')), 'directory')
6855.4.1 by Jelmer Vernooij
Yet more bees.
1764
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'i')).read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1765
                         conflict_text(b'1\n2\n3\n4\n', b'h\ni\nj\nk\n'))
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
1766
        self.assertEqual(this.wt.get_file('i.THIS').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1767
                         b'1\n2\n3\n4\n')
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
1768
        self.assertEqual(this.wt.get_file('i.OTHER').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1769
                         b'h\ni\nj\nk\n')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
1770
        self.assertEqual(os.path.exists(this.wt.abspath('i.BASE')), False)
1534.7.192 by Aaron Bentley
Record hashes produced by merges
1771
        modified = ['a', 'b', 'c', 'h', 'i']
1772
        merge_modified = this.wt.merge_modified()
1773
        self.assertSubset(merge_modified, modified)
1774
        self.assertEqual(len(merge_modified), len(modified))
6973.7.5 by Jelmer Vernooij
s/file/open.
1775
        with open(this.wt.abspath(this.wt.id2path('a')), 'wb') as f: f.write(b'booga')
1534.7.192 by Aaron Bentley
Record hashes produced by merges
1776
        modified.pop(0)
1777
        merge_modified = this.wt.merge_modified()
1778
        self.assertSubset(merge_modified, modified)
1779
        self.assertEqual(len(merge_modified), len(modified))
1558.12.10 by Aaron Bentley
Be robust when merge_hash file_id not in inventory
1780
        this.wt.remove('b')
2796.1.4 by Aaron Bentley
Fix up various test cases
1781
        this.wt.revert()
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
1782
1783
    def test_file_merge(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
1784
        self.requireFeature(SymlinkFeature)
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
1785
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
1786
        base = TransformGroup("BASE", root_id)
1787
        this = TransformGroup("THIS", root_id)
1788
        other = TransformGroup("OTHER", root_id)
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
1789
        for tg in this, base, other:
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1790
            tg.tt.new_directory('a', tg.root, b'a')
6973.10.1 by Jelmer Vernooij
Fix some tests.
1791
            tg.tt.new_symlink('b', tg.root, 'b', b'b')
1792
            tg.tt.new_file('c', tg.root, [b'c'], b'c')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1793
            tg.tt.new_symlink('d', tg.root, tg.name, b'd')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1794
        targets = ((base, 'base-e', 'base-f', None, None),
1795
                   (this, 'other-e', 'this-f', 'other-g', 'this-h'),
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
1796
                   (other, 'other-e', None, 'other-g', 'other-h'))
1797
        for tg, e_target, f_target, g_target, h_target in targets:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1798
            for link, target in (('e', e_target), ('f', f_target),
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
1799
                                 ('g', g_target), ('h', h_target)):
1800
                if target is not None:
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1801
                    tg.tt.new_symlink(link, tg.root, target, link.encode('ascii'))
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
1802
1803
        for tg in this, base, other:
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
1804
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
1805
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
1806
        self.assertIs(os.path.isdir(this.wt.abspath('a')), True)
1807
        self.assertIs(os.path.islink(this.wt.abspath('b')), True)
1808
        self.assertIs(os.path.isfile(this.wt.abspath('c')), True)
1809
        for suffix in ('THIS', 'BASE', 'OTHER'):
1810
            self.assertEqual(os.readlink(this.wt.abspath('d.'+suffix)), suffix)
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
1811
        self.assertIs(os.path.lexists(this.wt.abspath('d')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1812
        self.assertEqual(this.wt.id2path(b'd'), 'd.OTHER')
1813
        self.assertEqual(this.wt.id2path(b'f'), 'f.THIS')
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
1814
        self.assertEqual(os.readlink(this.wt.abspath('e')), 'other-e')
1815
        self.assertIs(os.path.lexists(this.wt.abspath('e.THIS')), False)
1816
        self.assertIs(os.path.lexists(this.wt.abspath('e.OTHER')), False)
1817
        self.assertIs(os.path.lexists(this.wt.abspath('e.BASE')), False)
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
1818
        self.assertIs(os.path.lexists(this.wt.abspath('g')), True)
1819
        self.assertIs(os.path.lexists(this.wt.abspath('g.BASE')), False)
1820
        self.assertIs(os.path.lexists(this.wt.abspath('h')), False)
1821
        self.assertIs(os.path.lexists(this.wt.abspath('h.BASE')), False)
1822
        self.assertIs(os.path.lexists(this.wt.abspath('h.THIS')), True)
1823
        self.assertIs(os.path.lexists(this.wt.abspath('h.OTHER')), True)
1534.7.105 by Aaron Bentley
Got merge with rename working
1824
1825
    def test_filename_merge(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
1826
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
1827
        base = TransformGroup("BASE", root_id)
1828
        this = TransformGroup("THIS", root_id)
1829
        other = TransformGroup("OTHER", root_id)
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1830
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, b'a')
1831
                                   for t in [base, this, other]]
1832
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, b'b')
1833
                                   for t in [base, this, other]]
1834
        base.tt.new_directory('c', base_a, b'c')
1835
        this.tt.new_directory('c1', this_a, b'c')
1836
        other.tt.new_directory('c', other_b, b'c')
1837
1838
        base.tt.new_directory('d', base_a, b'd')
1839
        this.tt.new_directory('d1', this_b, b'd')
1840
        other.tt.new_directory('d', other_a, b'd')
1841
1842
        base.tt.new_directory('e', base_a, b'e')
1843
        this.tt.new_directory('e', this_a, b'e')
1844
        other.tt.new_directory('e1', other_b, b'e')
1845
1846
        base.tt.new_directory('f', base_a, b'f')
1847
        this.tt.new_directory('f1', this_b, b'f')
1848
        other.tt.new_directory('f1', other_b, b'f')
1534.7.105 by Aaron Bentley
Got merge with rename working
1849
1850
        for tg in [this, base, other]:
1851
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
1852
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1853
        self.assertEqual(this.wt.id2path(b'c'), pathjoin('b/c1'))
1854
        self.assertEqual(this.wt.id2path(b'd'), pathjoin('b/d1'))
1855
        self.assertEqual(this.wt.id2path(b'e'), pathjoin('b/e1'))
1856
        self.assertEqual(this.wt.id2path(b'f'), pathjoin('b/f1'))
1534.7.105 by Aaron Bentley
Got merge with rename working
1857
1858
    def test_filename_merge_conflicts(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
1859
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
1860
        base = TransformGroup("BASE", root_id)
1861
        this = TransformGroup("THIS", root_id)
1862
        other = TransformGroup("OTHER", root_id)
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1863
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, b'a')
1534.7.105 by Aaron Bentley
Got merge with rename working
1864
                                   for t in [base, this, other]]
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
1865
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, b'b')
1534.7.105 by Aaron Bentley
Got merge with rename working
1866
                                   for t in [base, this, other]]
1867
6973.10.1 by Jelmer Vernooij
Fix some tests.
1868
        base.tt.new_file('g', base_a, [b'g'], b'g')
1869
        other.tt.new_file('g1', other_b, [b'g1'], b'g')
1870
1871
        base.tt.new_file('h', base_a, [b'h'], b'h')
1872
        this.tt.new_file('h1', this_b, [b'h1'], b'h')
1873
1874
        base.tt.new_file('i', base.root, [b'i'], b'i')
1875
        other.tt.new_directory('i1', this_b, b'i')
1534.7.105 by Aaron Bentley
Got merge with rename working
1876
1877
        for tg in [this, base, other]:
1878
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
1879
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.105 by Aaron Bentley
Got merge with rename working
1880
6855.4.1 by Jelmer Vernooij
Yet more bees.
1881
        self.assertEqual(this.wt.id2path(b'g'), pathjoin('b/g1.OTHER'))
1534.7.105 by Aaron Bentley
Got merge with rename working
1882
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.BASE')), True)
1883
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.THIS')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1884
        self.assertEqual(this.wt.id2path(b'h'), pathjoin('b/h1.THIS'))
1534.7.105 by Aaron Bentley
Got merge with rename working
1885
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.BASE')), True)
1886
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.OTHER')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1887
        self.assertEqual(this.wt.id2path(b'i'), pathjoin('b/i1.OTHER'))
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
1888
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
1889
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1890
class TestBuildTree(tests.TestCaseWithTransport):
1891
3006.2.2 by Alexander Belchenko
tests added.
1892
    def test_build_tree_with_symlinks(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
1893
        self.requireFeature(SymlinkFeature)
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
1894
        os.mkdir('a')
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
1895
        a = ControlDir.create_standalone_workingtree('a')
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
1896
        os.mkdir('a/foo')
6973.7.5 by Jelmer Vernooij
s/file/open.
1897
        with open('a/foo/bar', 'wb') as f: f.write(b'contents')
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
1898
        os.symlink('a/foo/bar', 'a/foo/baz')
1899
        a.add(['foo', 'foo/bar', 'foo/baz'])
1900
        a.commit('initial commit')
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
1901
        b = ControlDir.create_standalone_workingtree('b')
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
1902
        basis = a.basis_tree()
1903
        basis.lock_read()
1904
        self.addCleanup(basis.unlock)
1905
        build_tree(basis, b)
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
1906
        self.assertIs(os.path.isdir('b/foo'), True)
6973.7.5 by Jelmer Vernooij
s/file/open.
1907
        with open('b/foo/bar', 'rb') as f:
1908
            self.assertEqual(f.read(), "contents")
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
1909
        self.assertEqual(os.readlink('b/foo/baz'), 'a/foo/bar')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1910
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
1911
    def test_build_with_references(self):
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
1912
        tree = self.make_branch_and_tree('source',
6437.14.2 by Jelmer Vernooij
Run subtree tests with development-subtree rather than deprecated dirstate-with-subtree.
1913
            format='development-subtree')
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
1914
        subtree = self.make_branch_and_tree('source/subtree',
6437.14.2 by Jelmer Vernooij
Run subtree tests with development-subtree rather than deprecated dirstate-with-subtree.
1915
            format='development-subtree')
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
1916
        tree.add_reference(subtree)
1917
        tree.commit('a revision')
1918
        tree.branch.create_checkout('target')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1919
        self.assertPathExists('target')
1920
        self.assertPathExists('target/subtree')
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
1921
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1922
    def test_file_conflict_handling(self):
1923
        """Ensure that when building trees, conflict handling is done"""
1924
        source = self.make_branch_and_tree('source')
1925
        target = self.make_branch_and_tree('target')
1926
        self.build_tree(['source/file', 'target/file'])
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1927
        source.add('file', b'new-file')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1928
        source.commit('added file')
1929
        build_tree(source.basis_tree(), target)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1930
        self.assertEqual([DuplicateEntry('Moved existing file to',
1931
                          'file.moved', 'file', None, 'new-file')],
1932
                         target.conflicts())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1933
        target2 = self.make_branch_and_tree('target2')
6973.7.5 by Jelmer Vernooij
s/file/open.
1934
        with open('target2/file', 'wb') as target_file, \
1935
                open('source/file', 'rb') as source_file:
1936
            target_file.write(source_file.read())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1937
        build_tree(source.basis_tree(), target2)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1938
        self.assertEqual([], target2.conflicts())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1939
1940
    def test_symlink_conflict_handling(self):
1941
        """Ensure that when building trees, conflict handling is done"""
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
1942
        self.requireFeature(SymlinkFeature)
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1943
        source = self.make_branch_and_tree('source')
1944
        os.symlink('foo', 'source/symlink')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1945
        source.add('symlink', b'new-symlink')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1946
        source.commit('added file')
1947
        target = self.make_branch_and_tree('target')
1948
        os.symlink('bar', 'target/symlink')
1949
        build_tree(source.basis_tree(), target)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1950
        self.assertEqual([DuplicateEntry('Moved existing file to',
1951
            'symlink.moved', 'symlink', None, 'new-symlink')],
1952
            target.conflicts())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1953
        target = self.make_branch_and_tree('target2')
1954
        os.symlink('foo', 'target2/symlink')
1955
        build_tree(source.basis_tree(), target)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1956
        self.assertEqual([], target.conflicts())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1957
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1958
    def test_directory_conflict_handling(self):
1959
        """Ensure that when building trees, conflict handling is done"""
1960
        source = self.make_branch_and_tree('source')
1961
        target = self.make_branch_and_tree('target')
1962
        self.build_tree(['source/dir1/', 'source/dir1/file', 'target/dir1/'])
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
1963
        source.add(['dir1', 'dir1/file'], [b'new-dir1', b'new-file'])
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1964
        source.commit('added file')
1965
        build_tree(source.basis_tree(), target)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1966
        self.assertEqual([], target.conflicts())
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1967
        self.assertPathExists('target/dir1/file')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1968
1969
        # Ensure contents are merged
1970
        target = self.make_branch_and_tree('target2')
1971
        self.build_tree(['target2/dir1/', 'target2/dir1/file2'])
1972
        build_tree(source.basis_tree(), target)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1973
        self.assertEqual([], target.conflicts())
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1974
        self.assertPathExists('target2/dir1/file2')
1975
        self.assertPathExists('target2/dir1/file')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1976
1977
        # Ensure new contents are suppressed for existing branches
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1978
        target = self.make_branch_and_tree('target3')
1979
        self.make_branch('target3/dir1')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1980
        self.build_tree(['target3/dir1/file2'])
1981
        build_tree(source.basis_tree(), target)
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1982
        self.assertPathDoesNotExist('target3/dir1/file')
1983
        self.assertPathExists('target3/dir1/file2')
1984
        self.assertPathExists('target3/dir1.diverted/file')
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1985
        self.assertEqual([DuplicateEntry('Diverted to',
1986
            'dir1.diverted', 'dir1', 'new-dir1', None)],
1987
            target.conflicts())
1988
1989
        target = self.make_branch_and_tree('target4')
1990
        self.build_tree(['target4/dir1/'])
1991
        self.make_branch('target4/dir1/file')
1992
        build_tree(source.basis_tree(), target)
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1993
        self.assertPathExists('target4/dir1/file')
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1994
        self.assertEqual('directory', file_kind('target4/dir1/file'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
1995
        self.assertPathExists('target4/dir1/file.diverted')
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
1996
        self.assertEqual([DuplicateEntry('Diverted to',
1997
            'dir1/file.diverted', 'dir1/file', 'new-file', None)],
1998
            target.conflicts())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1999
2000
    def test_mixed_conflict_handling(self):
2001
        """Ensure that when building trees, conflict handling is done"""
2002
        source = self.make_branch_and_tree('source')
2003
        target = self.make_branch_and_tree('target')
2004
        self.build_tree(['source/name', 'target/name/'])
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
2005
        source.add('name', b'new-name')
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
2006
        source.commit('added file')
2007
        build_tree(source.basis_tree(), target)
2008
        self.assertEqual([DuplicateEntry('Moved existing file to',
2009
            'name.moved', 'name', None, 'new-name')], target.conflicts())
2010
2011
    def test_raises_in_populated(self):
2012
        source = self.make_branch_and_tree('source')
2013
        self.build_tree(['source/name'])
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
2014
        source.add('name')
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
2015
        source.commit('added name')
2016
        target = self.make_branch_and_tree('target')
2017
        self.build_tree(['target/name'])
2018
        target.add('name')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2019
        self.assertRaises(errors.WorkingTreeAlreadyPopulated,
2090.2.1 by Martin Pool
Fix some code which relies on assertions and breaks under python -O
2020
            build_tree, source.basis_tree(), target)
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
2021
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
2022
    def test_build_tree_rename_count(self):
2023
        source = self.make_branch_and_tree('source')
2024
        self.build_tree(['source/file1', 'source/dir1/'])
2025
        source.add(['file1', 'dir1'])
2026
        source.commit('add1')
2027
        target1 = self.make_branch_and_tree('target1')
2502.1.6 by Aaron Bentley
Update from review comments
2028
        transform_result = build_tree(source.basis_tree(), target1)
2029
        self.assertEqual(2, transform_result.rename_count)
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
2030
2031
        self.build_tree(['source/dir1/file2'])
2032
        source.add(['dir1/file2'])
2033
        source.commit('add3')
2034
        target2 = self.make_branch_and_tree('target2')
2502.1.6 by Aaron Bentley
Update from review comments
2035
        transform_result = build_tree(source.basis_tree(), target2)
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
2036
        # children of non-root directories should not be renamed
2502.1.6 by Aaron Bentley
Update from review comments
2037
        self.assertEqual(2, transform_result.rename_count)
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
2038
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2039
    def create_ab_tree(self):
2040
        """Create a committed test tree with two files"""
2041
        source = self.make_branch_and_tree('source')
6855.4.1 by Jelmer Vernooij
Yet more bees.
2042
        self.build_tree_contents([('source/file1', b'A')])
2043
        self.build_tree_contents([('source/file2', b'B')])
2044
        source.add(['file1', 'file2'], [b'file1-id', b'file2-id'])
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2045
        source.commit('commit files')
2046
        source.lock_write()
2047
        self.addCleanup(source.unlock)
2048
        return source
2049
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
2050
    def test_build_tree_accelerator_tree(self):
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2051
        source = self.create_ab_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
2052
        self.build_tree_contents([('source/file2', b'C')])
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
2053
        calls = []
2054
        real_source_get_file = source.get_file
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
2055
        def get_file(path, file_id=None):
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
2056
            calls.append(file_id)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
2057
            return real_source_get_file(path, file_id)
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
2058
        source.get_file = get_file
2059
        target = self.make_branch_and_tree('target')
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
2060
        revision_tree = source.basis_tree()
2061
        revision_tree.lock_read()
2062
        self.addCleanup(revision_tree.unlock)
2063
        build_tree(revision_tree, target, source)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2064
        self.assertEqual([b'file1-id'], calls)
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
2065
        target.lock_read()
2066
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2067
        self.assertEqual([], list(target.iter_changes(revision_tree)))
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
2068
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
2069
    def test_build_tree_accelerator_tree_observes_sha1(self):
2070
        source = self.create_ab_tree()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2071
        sha1 = osutils.sha_string(b'A')
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
2072
        target = self.make_branch_and_tree('target')
2073
        target.lock_write()
2074
        self.addCleanup(target.unlock)
2075
        state = target.current_dirstate()
2076
        state._cutoff_time = time.time() + 60
2077
        build_tree(source.basis_tree(), target, source)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2078
        entry = state._get_entry(0, path_utf8=b'file1')
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
2079
        self.assertEqual(sha1, entry[1][0][1])
2080
3123.5.4 by Aaron Bentley
Use an accelerator tree when branching, handle no-such-id correctly
2081
    def test_build_tree_accelerator_tree_missing_file(self):
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2082
        source = self.create_ab_tree()
3123.5.4 by Aaron Bentley
Use an accelerator tree when branching, handle no-such-id correctly
2083
        os.unlink('source/file1')
2084
        source.remove(['file2'])
2085
        target = self.make_branch_and_tree('target')
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
2086
        revision_tree = source.basis_tree()
2087
        revision_tree.lock_read()
2088
        self.addCleanup(revision_tree.unlock)
2089
        build_tree(revision_tree, target, source)
2090
        target.lock_read()
2091
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2092
        self.assertEqual([], list(target.iter_changes(revision_tree)))
3123.5.4 by Aaron Bentley
Use an accelerator tree when branching, handle no-such-id correctly
2093
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
2094
    def test_build_tree_accelerator_wrong_kind(self):
3146.4.8 by Aaron Bentley
Add missing symlink requirement
2095
        self.requireFeature(SymlinkFeature)
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
2096
        source = self.make_branch_and_tree('source')
6855.4.1 by Jelmer Vernooij
Yet more bees.
2097
        self.build_tree_contents([('source/file1', b'')])
2098
        self.build_tree_contents([('source/file2', b'')])
2099
        source.add(['file1', 'file2'], [b'file1-id', b'file2-id'])
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
2100
        source.commit('commit files')
2101
        os.unlink('source/file2')
6855.4.1 by Jelmer Vernooij
Yet more bees.
2102
        self.build_tree_contents([('source/file2/', b'C')])
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
2103
        os.unlink('source/file1')
2104
        os.symlink('file2', 'source/file1')
2105
        calls = []
2106
        real_source_get_file = source.get_file
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
2107
        def get_file(path, file_id=None):
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
2108
            calls.append(file_id)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
2109
            return real_source_get_file(path, file_id)
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
2110
        source.get_file = get_file
2111
        target = self.make_branch_and_tree('target')
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
2112
        revision_tree = source.basis_tree()
2113
        revision_tree.lock_read()
2114
        self.addCleanup(revision_tree.unlock)
2115
        build_tree(revision_tree, target, source)
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
2116
        self.assertEqual([], calls)
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
2117
        target.lock_read()
2118
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2119
        self.assertEqual([], list(target.iter_changes(revision_tree)))
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
2120
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2121
    def test_build_tree_hardlink(self):
2122
        self.requireFeature(HardlinkFeature)
2123
        source = self.create_ab_tree()
2124
        target = self.make_branch_and_tree('target')
2125
        revision_tree = source.basis_tree()
2126
        revision_tree.lock_read()
2127
        self.addCleanup(revision_tree.unlock)
2128
        build_tree(revision_tree, target, source, hardlink=True)
2129
        target.lock_read()
2130
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2131
        self.assertEqual([], list(target.iter_changes(revision_tree)))
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2132
        source_stat = os.stat('source/file1')
2133
        target_stat = os.stat('target/file1')
2134
        self.assertEqual(source_stat, target_stat)
2135
2136
        # Explicitly disallowing hardlinks should prevent them.
2137
        target2 = self.make_branch_and_tree('target2')
2138
        build_tree(revision_tree, target2, source, hardlink=False)
2139
        target2.lock_read()
2140
        self.addCleanup(target2.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2141
        self.assertEqual([], list(target2.iter_changes(revision_tree)))
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2142
        source_stat = os.stat('source/file1')
2143
        target2_stat = os.stat('target2/file1')
2144
        self.assertNotEqual(source_stat, target2_stat)
2145
3137.1.1 by Aaron Bentley
Fix build_tree acceleration when file is moved in accelerator_tree
2146
    def test_build_tree_accelerator_tree_moved(self):
2147
        source = self.make_branch_and_tree('source')
6855.4.1 by Jelmer Vernooij
Yet more bees.
2148
        self.build_tree_contents([('source/file1', b'A')])
2149
        source.add(['file1'], [b'file1-id'])
3137.1.1 by Aaron Bentley
Fix build_tree acceleration when file is moved in accelerator_tree
2150
        source.commit('commit files')
2151
        source.rename_one('file1', 'file2')
2152
        source.lock_read()
2153
        self.addCleanup(source.unlock)
2154
        target = self.make_branch_and_tree('target')
2155
        revision_tree = source.basis_tree()
2156
        revision_tree.lock_read()
2157
        self.addCleanup(revision_tree.unlock)
2158
        build_tree(revision_tree, target, source)
2159
        target.lock_read()
2160
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2161
        self.assertEqual([], list(target.iter_changes(revision_tree)))
3137.1.1 by Aaron Bentley
Fix build_tree acceleration when file is moved in accelerator_tree
2162
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2163
    def test_build_tree_hardlinks_preserve_execute(self):
2164
        self.requireFeature(HardlinkFeature)
2165
        source = self.create_ab_tree()
2166
        tt = TreeTransform(source)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
2167
        trans_id = tt.trans_id_tree_path('file1')
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2168
        tt.set_executability(True, trans_id)
2169
        tt.apply()
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
2170
        self.assertTrue(source.is_executable('file1'))
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2171
        target = self.make_branch_and_tree('target')
2172
        revision_tree = source.basis_tree()
2173
        revision_tree.lock_read()
2174
        self.addCleanup(revision_tree.unlock)
2175
        build_tree(revision_tree, target, source, hardlink=True)
2176
        target.lock_read()
2177
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2178
        self.assertEqual([], list(target.iter_changes(revision_tree)))
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
2179
        self.assertTrue(source.is_executable('file1'))
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
2180
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
2181
    def install_rot13_content_filter(self, pattern):
4985.2.1 by Vincent Ladeuil
Deploy addAttrCleanup on the whole test suite.
2182
        # We could use
2183
        # self.addCleanup(filters._reset_registry, filters._reset_registry())
2184
        # below, but that looks a bit... hard to read even if it's exactly
2185
        # the same thing.
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
2186
        original_registry = filters._reset_registry()
2187
        def restore_registry():
2188
            filters._reset_registry(original_registry)
2189
        self.addCleanup(restore_registry)
2190
        def rot13(chunks, context=None):
6973.10.1 by Jelmer Vernooij
Fix some tests.
2191
            return [b''.join(chunks).encode('rot13')]
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
2192
        rot13filter = filters.ContentFilter(rot13, rot13)
6498.5.3 by Jelmer Vernooij
Fix tests.
2193
        filters.filter_stacks_registry.register(
2194
            'rot13', {'yes': [rot13filter]}.get)
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
2195
        os.mkdir(self.test_home_dir + '/.bazaar')
2196
        rules_filename = self.test_home_dir + '/.bazaar/rules'
6973.7.5 by Jelmer Vernooij
s/file/open.
2197
        with open(rules_filename, 'wb') as f:
2198
            f.write(b'[name %s]\nrot13=yes\n' % (pattern,))
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
2199
        def uninstall_rules():
2200
            os.remove(rules_filename)
2201
            rules.reset_rules()
2202
        self.addCleanup(uninstall_rules)
2203
        rules.reset_rules()
2204
2205
    def test_build_tree_content_filtered_files_are_not_hardlinked(self):
2206
        """build_tree will not hardlink files that have content filtering rules
2207
        applied to them (but will still hardlink other files from the same tree
2208
        if it can).
2209
        """
2210
        self.requireFeature(HardlinkFeature)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2211
        self.install_rot13_content_filter(b'file1')
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
2212
        source = self.create_ab_tree()
2213
        target = self.make_branch_and_tree('target')
2214
        revision_tree = source.basis_tree()
2215
        revision_tree.lock_read()
2216
        self.addCleanup(revision_tree.unlock)
2217
        build_tree(revision_tree, target, source, hardlink=True)
2218
        target.lock_read()
2219
        self.addCleanup(target.unlock)
2220
        self.assertEqual([], list(target.iter_changes(revision_tree)))
2221
        source_stat = os.stat('source/file1')
2222
        target_stat = os.stat('target/file1')
2223
        self.assertNotEqual(source_stat, target_stat)
2224
        source_stat = os.stat('source/file2')
2225
        target_stat = os.stat('target/file2')
4826.1.8 by Andrew Bennetts
Tweaks suggested by John.
2226
        self.assertEqualStat(source_stat, target_stat)
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
2227
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
2228
    def test_case_insensitive_build_tree_inventory(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
2229
        if (features.CaseInsensitiveFilesystemFeature.available()
2230
            or features.CaseInsCasePresFilenameFeature.available()):
4241.9.4 by Vincent Ladeuil
Fix test_case_insensitive_build_tree_inventory failure on OSX.
2231
            raise tests.UnavailableFeature('Fully case sensitive filesystem')
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
2232
        source = self.make_branch_and_tree('source')
2233
        self.build_tree(['source/file', 'source/FILE'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2234
        source.add(['file', 'FILE'], [b'lower-id', b'upper-id'])
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
2235
        source.commit('added files')
2236
        # Don't try this at home, kids!
2237
        # Force the tree to report that it is case insensitive
2238
        target = self.make_branch_and_tree('target')
2239
        target.case_sensitive = False
3453.2.6 by Aaron Bentley
Rename mutate_tree to delta_from_tree, add comment
2240
        build_tree(source.basis_tree(), target, source, delta_from_tree=True)
6855.4.1 by Jelmer Vernooij
Yet more bees.
2241
        self.assertEqual('file.moved', target.id2path(b'lower-id'))
2242
        self.assertEqual('FILE', target.id2path(b'upper-id'))
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
2243
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
2244
    def test_build_tree_observes_sha(self):
2245
        source = self.make_branch_and_tree('source')
2246
        self.build_tree(['source/file1', 'source/dir/', 'source/dir/file2'])
2247
        source.add(['file1', 'dir', 'dir/file2'],
6855.4.1 by Jelmer Vernooij
Yet more bees.
2248
                   [b'file1-id', b'dir-id', b'file2-id'])
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
2249
        source.commit('new files')
2250
        target = self.make_branch_and_tree('target')
2251
        target.lock_write()
2252
        self.addCleanup(target.unlock)
2253
        # We make use of the fact that DirState caches its cutoff time. So we
2254
        # set the 'safe' time to one minute in the future.
2255
        state = target.current_dirstate()
2256
        state._cutoff_time = time.time() + 60
2257
        build_tree(source.basis_tree(), target)
2258
        entry1_sha = osutils.sha_file_by_name('source/file1')
2259
        entry2_sha = osutils.sha_file_by_name('source/dir/file2')
2260
        # entry[1] is the state information, entry[1][0] is the state of the
2261
        # working tree, entry[1][0][1] is the sha value for the current working
2262
        # tree
2263
        entry1 = state._get_entry(0, path_utf8='file1')
2264
        self.assertEqual(entry1_sha, entry1[1][0][1])
2265
        # The 'size' field must also be set.
2266
        self.assertEqual(25, entry1[1][0][2])
2267
        entry1_state = entry1[1][0]
2268
        entry2 = state._get_entry(0, path_utf8='dir/file2')
2269
        self.assertEqual(entry2_sha, entry2[1][0][1])
2270
        self.assertEqual(29, entry2[1][0][2])
2271
        entry2_state = entry2[1][0]
2272
        # Now, make sure that we don't have to re-read the content. The
2273
        # packed_stat should match exactly.
6855.4.1 by Jelmer Vernooij
Yet more bees.
2274
        self.assertEqual(entry1_sha, target.get_file_sha1('file1', b'file1-id'))
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
2275
        self.assertEqual(entry2_sha,
6855.4.1 by Jelmer Vernooij
Yet more bees.
2276
                         target.get_file_sha1('dir/file2', b'file2-id'))
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
2277
        self.assertEqual(entry1_state, entry1[1][0])
2278
        self.assertEqual(entry2_state, entry2[1][0])
2279
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
2280
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
2281
class TestCommitTransform(tests.TestCaseWithTransport):
2282
2283
    def get_branch(self):
2284
        tree = self.make_branch_and_tree('tree')
2285
        tree.lock_write()
2286
        self.addCleanup(tree.unlock)
2287
        tree.commit('empty commit')
2288
        return tree.branch
2289
2290
    def get_branch_and_transform(self):
2291
        branch = self.get_branch()
2292
        tt = TransformPreview(branch.basis_tree())
2293
        self.addCleanup(tt.finalize)
2294
        return branch, tt
2295
2296
    def test_commit_wrong_basis(self):
2297
        branch = self.get_branch()
2298
        basis = branch.repository.revision_tree(
2299
            _mod_revision.NULL_REVISION)
2300
        tt = TransformPreview(basis)
2301
        self.addCleanup(tt.finalize)
4526.8.5 by Aaron Bentley
Updates from review.
2302
        e = self.assertRaises(ValueError, tt.commit, branch, '')
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
2303
        self.assertEqual('TreeTransform not based on branch basis: null:',
2304
                         str(e))
2305
2306
    def test_empy_commit(self):
2307
        branch, tt = self.get_branch_and_transform()
2308
        rev = tt.commit(branch, 'my message')
2309
        self.assertEqual(2, branch.revno())
2310
        repo = branch.repository
2311
        self.assertEqual('my message', repo.get_revision(rev).message)
2312
2313
    def test_merge_parents(self):
2314
        branch, tt = self.get_branch_and_transform()
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
2315
        rev = tt.commit(branch, 'my message', [b'rev1b', b'rev1c'])
2316
        self.assertEqual([b'rev1b', b'rev1c'],
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
2317
                         branch.basis_tree().get_parent_ids()[1:])
2318
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
2319
    def test_first_commit(self):
2320
        branch = self.make_branch('branch')
2321
        branch.lock_write()
2322
        self.addCleanup(branch.unlock)
2323
        tt = TransformPreview(branch.basis_tree())
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
2324
        self.addCleanup(tt.finalize)
6973.13.2 by Jelmer Vernooij
Fix some more tests.
2325
        tt.new_directory('', ROOT_PARENT, b'TREE_ROOT')
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
2326
        rev = tt.commit(branch, 'my message')
2327
        self.assertEqual([], branch.basis_tree().get_parent_ids())
4526.8.5 by Aaron Bentley
Updates from review.
2328
        self.assertNotEqual(_mod_revision.NULL_REVISION,
2329
                            branch.last_revision())
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
2330
4526.8.5 by Aaron Bentley
Updates from review.
2331
    def test_first_commit_with_merge_parents(self):
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
2332
        branch = self.make_branch('branch')
2333
        branch.lock_write()
2334
        self.addCleanup(branch.unlock)
2335
        tt = TransformPreview(branch.basis_tree())
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
2336
        self.addCleanup(tt.finalize)
4526.8.5 by Aaron Bentley
Updates from review.
2337
        e = self.assertRaises(ValueError, tt.commit, branch,
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
2338
                          'my message', [b'rev1b-id'])
4526.8.5 by Aaron Bentley
Updates from review.
2339
        self.assertEqual('Cannot supply merge parents for first commit.',
2340
                         str(e))
2341
        self.assertEqual(_mod_revision.NULL_REVISION, branch.last_revision())
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
2342
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
2343
    def test_add_files(self):
2344
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2345
        tt.new_file('file', tt.root, [b'contents'], b'file-id')
2346
        trans_id = tt.new_directory('dir', tt.root, b'dir-id')
4789.25.2 by John Arbash Meinel
Fix 3 tests that meant to skip exec or symlink testing on win32
2347
        if SymlinkFeature.available():
6973.10.1 by Jelmer Vernooij
Fix some tests.
2348
            tt.new_symlink('symlink', trans_id, 'target', b'symlink-id')
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
2349
        rev = tt.commit(branch, 'message')
2350
        tree = branch.basis_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
2351
        self.assertEqual('file', tree.id2path(b'file-id'))
6973.7.3 by Jelmer Vernooij
Fix some more tests.
2352
        self.assertEqual(b'contents', tree.get_file_text('file', b'file-id'))
6855.4.1 by Jelmer Vernooij
Yet more bees.
2353
        self.assertEqual('dir', tree.id2path(b'dir-id'))
4789.25.2 by John Arbash Meinel
Fix 3 tests that meant to skip exec or symlink testing on win32
2354
        if SymlinkFeature.available():
6855.4.1 by Jelmer Vernooij
Yet more bees.
2355
            self.assertEqual('dir/symlink', tree.id2path(b'symlink-id'))
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
2356
            self.assertEqual('target', tree.get_symlink_target('dir/symlink'))
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
2357
4526.8.2 by Aaron Bentley
Proved strict commit handling.
2358
    def test_add_unversioned(self):
2359
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2360
        tt.new_file('file', tt.root, [b'contents'])
4526.8.2 by Aaron Bentley
Proved strict commit handling.
2361
        self.assertRaises(errors.StrictCommitFailed, tt.commit, branch,
2362
                          'message', strict=True)
2363
2364
    def test_modify_strict(self):
2365
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2366
        tt.new_file('file', tt.root, [b'contents'], b'file-id')
4526.8.2 by Aaron Bentley
Proved strict commit handling.
2367
        tt.commit(branch, 'message', strict=True)
2368
        tt = TransformPreview(branch.basis_tree())
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
2369
        self.addCleanup(tt.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2370
        trans_id = tt.trans_id_file_id(b'file-id')
4526.8.2 by Aaron Bentley
Proved strict commit handling.
2371
        tt.delete_contents(trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
2372
        tt.create_file([b'contents'], trans_id)
4526.8.2 by Aaron Bentley
Proved strict commit handling.
2373
        tt.commit(branch, 'message', strict=True)
2374
4526.8.6 by Aaron Bentley
Check for malformed transforms before committing.
2375
    def test_commit_malformed(self):
2376
        """Committing a malformed transform should raise an exception.
2377
2378
        In this case, we are adding a file without adding its parent.
2379
        """
2380
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2381
        parent_id = tt.trans_id_file_id(b'parent-id')
2382
        tt.new_file('file', parent_id, [b'contents'], b'file-id')
4526.8.6 by Aaron Bentley
Check for malformed transforms before committing.
2383
        self.assertRaises(errors.MalformedTransform, tt.commit, branch,
2384
                          'message')
2385
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
2386
    def test_commit_rich_revision_data(self):
2387
        branch, tt = self.get_branch_and_transform()
5162.4.3 by Aaron Bentley
Fix failing test.
2388
        rev_id = tt.commit(branch, 'message', timestamp=1, timezone=43201,
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
2389
                           committer='me <me@example.com>',
6973.12.5 by Jelmer Vernooij
Add some u's for revision property names.
2390
                           revprops={u'foo': 'bar'}, revision_id=b'revid-1',
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
2391
                           authors=['Author1 <author1@example.com>',
2392
                              'Author2 <author2@example.com>',
2393
                               ])
6973.10.1 by Jelmer Vernooij
Fix some tests.
2394
        self.assertEqual(b'revid-1', rev_id)
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
2395
        revision = branch.repository.get_revision(rev_id)
2396
        self.assertEqual(1, revision.timestamp)
5162.4.3 by Aaron Bentley
Fix failing test.
2397
        self.assertEqual(43201, revision.timezone)
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
2398
        self.assertEqual('me <me@example.com>', revision.committer)
2399
        self.assertEqual(['Author1 <author1@example.com>',
2400
                          'Author2 <author2@example.com>'],
2401
                         revision.get_apparent_authors())
2402
        del revision.properties['authors']
2403
        self.assertEqual({'foo': 'bar',
2404
                          'branch-nick': 'tree'},
2405
                         revision.properties)
2406
2407
    def test_no_explicit_revprops(self):
2408
        branch, tt = self.get_branch_and_transform()
2409
        rev_id = tt.commit(branch, 'message', authors=[
2410
            'Author1 <author1@example.com>',
2411
            'Author2 <author2@example.com>', ])
2412
        revision = branch.repository.get_revision(rev_id)
2413
        self.assertEqual(['Author1 <author1@example.com>',
2414
                          'Author2 <author2@example.com>'],
2415
                         revision.get_apparent_authors())
2416
        self.assertEqual('tree', revision.properties['branch-nick'])
2417
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
2418
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
2419
class TestFileMover(tests.TestCaseWithTransport):
2420
2421
    def test_file_mover(self):
2422
        self.build_tree(['a/', 'a/b', 'c/', 'c/d'])
2423
        mover = _FileMover()
2424
        mover.rename('a', 'q')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2425
        self.assertPathExists('q')
2426
        self.assertPathDoesNotExist('a')
2427
        self.assertPathExists('q/b')
2428
        self.assertPathExists('c')
2429
        self.assertPathExists('c/d')
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
2430
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
2431
    def test_pre_delete_rollback(self):
2432
        self.build_tree(['a/'])
2433
        mover = _FileMover()
2434
        mover.pre_delete('a', 'q')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2435
        self.assertPathExists('q')
2436
        self.assertPathDoesNotExist('a')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
2437
        mover.rollback()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2438
        self.assertPathDoesNotExist('q')
2439
        self.assertPathExists('a')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
2440
2441
    def test_apply_deletions(self):
2733.2.12 by Aaron Bentley
Updates from review
2442
        self.build_tree(['a/', 'b/'])
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
2443
        mover = _FileMover()
2444
        mover.pre_delete('a', 'q')
2733.2.12 by Aaron Bentley
Updates from review
2445
        mover.pre_delete('b', 'r')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2446
        self.assertPathExists('q')
2447
        self.assertPathExists('r')
2448
        self.assertPathDoesNotExist('a')
2449
        self.assertPathDoesNotExist('b')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
2450
        mover.apply_deletions()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2451
        self.assertPathDoesNotExist('q')
2452
        self.assertPathDoesNotExist('r')
2453
        self.assertPathDoesNotExist('a')
2454
        self.assertPathDoesNotExist('b')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
2455
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
2456
    def test_file_mover_rollback(self):
2457
        self.build_tree(['a/', 'a/b', 'c/', 'c/d/', 'c/e/'])
2458
        mover = _FileMover()
2459
        mover.rename('c/d', 'c/f')
2460
        mover.rename('c/e', 'c/d')
2461
        try:
2462
            mover.rename('a', 'c')
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
2463
        except errors.FileExists as e:
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
2464
            mover.rollback()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2465
        self.assertPathExists('a')
2466
        self.assertPathExists('c/d')
2733.2.3 by Aaron Bentley
Test tranform rollback
2467
2468
2469
class Bogus(Exception):
2470
    pass
2471
2472
2473
class TestTransformRollback(tests.TestCaseWithTransport):
2474
2475
    class ExceptionFileMover(_FileMover):
2476
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
2477
        def __init__(self, bad_source=None, bad_target=None):
2478
            _FileMover.__init__(self)
2479
            self.bad_source = bad_source
2480
            self.bad_target = bad_target
2481
2733.2.3 by Aaron Bentley
Test tranform rollback
2482
        def rename(self, source, target):
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
2483
            if (self.bad_source is not None and
2484
                source.endswith(self.bad_source)):
2485
                raise Bogus
2486
            elif (self.bad_target is not None and
2487
                target.endswith(self.bad_target)):
2733.2.3 by Aaron Bentley
Test tranform rollback
2488
                raise Bogus
2489
            else:
2490
                _FileMover.rename(self, source, target)
2491
2492
    def test_rollback_rename(self):
2493
        tree = self.make_branch_and_tree('.')
2494
        self.build_tree(['a/', 'a/b'])
2495
        tt = TreeTransform(tree)
2496
        self.addCleanup(tt.finalize)
2497
        a_id = tt.trans_id_tree_path('a')
2498
        tt.adjust_path('c', tt.root, a_id)
2499
        tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
2500
        self.assertRaises(Bogus, tt.apply,
2501
                          _mover=self.ExceptionFileMover(bad_source='a'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2502
        self.assertPathExists('a')
2503
        self.assertPathExists('a/b')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
2504
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2505
        self.assertPathExists('c')
2506
        self.assertPathExists('c/d')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
2507
2508
    def test_rollback_rename_into_place(self):
2509
        tree = self.make_branch_and_tree('.')
2510
        self.build_tree(['a/', 'a/b'])
2511
        tt = TreeTransform(tree)
2512
        self.addCleanup(tt.finalize)
2513
        a_id = tt.trans_id_tree_path('a')
2514
        tt.adjust_path('c', tt.root, a_id)
2515
        tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
2516
        self.assertRaises(Bogus, tt.apply,
2517
                          _mover=self.ExceptionFileMover(bad_target='c/d'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2518
        self.assertPathExists('a')
2519
        self.assertPathExists('a/b')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
2520
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2521
        self.assertPathExists('c')
2522
        self.assertPathExists('c/d')
2733.2.6 by Aaron Bentley
Make TreeTransform commits rollbackable
2523
2524
    def test_rollback_deletion(self):
2525
        tree = self.make_branch_and_tree('.')
2526
        self.build_tree(['a/', 'a/b'])
2527
        tt = TreeTransform(tree)
2528
        self.addCleanup(tt.finalize)
2529
        a_id = tt.trans_id_tree_path('a')
2530
        tt.delete_contents(a_id)
2531
        tt.adjust_path('d', tt.root, tt.trans_id_tree_path('a/b'))
2532
        self.assertRaises(Bogus, tt.apply,
2533
                          _mover=self.ExceptionFileMover(bad_target='d'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
2534
        self.assertPathExists('a')
2535
        self.assertPathExists('a/b')
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2536
2537
5876.3.3 by Martin
Use better test class name
2538
class TestFinalizeRobustness(tests.TestCaseWithTransport):
2539
    """Ensure treetransform creation errors can be safely cleaned up after"""
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2540
2541
    def _override_globals_in_method(self, instance, method_name, globals):
2542
        """Replace method on instance with one with updated globals"""
2543
        import types
6619.3.24 by Jelmer Vernooij
Run 2to3 methodattrs fixer.
2544
        func = getattr(instance, method_name).__func__
6619.3.16 by Jelmer Vernooij
Run 2to3 funcattrs fixer.
2545
        new_globals = dict(func.__globals__)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2546
        new_globals.update(globals)
6619.3.16 by Jelmer Vernooij
Run 2to3 funcattrs fixer.
2547
        new_func = types.FunctionType(func.__code__, new_globals,
2548
            func.__name__, func.__defaults__)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2549
        setattr(instance, method_name,
2550
            types.MethodType(new_func, instance, instance.__class__))
2551
        self.addCleanup(delattr, instance, method_name)
2552
2553
    @staticmethod
2554
    def _fake_open_raises_before(name, mode):
2555
        """Like open() but raises before doing anything"""
2556
        raise RuntimeError
2557
2558
    @staticmethod
2559
    def _fake_open_raises_after(name, mode):
2560
        """Like open() but raises after creating file without returning"""
2561
        open(name, mode).close()
2562
        raise RuntimeError
2563
2564
    def create_transform_and_root_trans_id(self):
2565
        """Setup a transform creating a file in limbo"""
2566
        tree = self.make_branch_and_tree('.')
2567
        tt = TreeTransform(tree)
2568
        return tt, tt.create_path("a", tt.root)
2569
2570
    def create_transform_and_subdir_trans_id(self):
2571
        """Setup a transform creating a directory containing a file in limbo"""
2572
        tree = self.make_branch_and_tree('.')
2573
        tt = TreeTransform(tree)
2574
        d_trans_id = tt.create_path("d", tt.root)
2575
        tt.create_directory(d_trans_id)
2576
        f_trans_id = tt.create_path("a", d_trans_id)
2577
        tt.adjust_path("a", d_trans_id, f_trans_id)
2578
        return tt, f_trans_id
2579
2580
    def test_root_create_file_open_raises_before_creation(self):
2581
        tt, trans_id = self.create_transform_and_root_trans_id()
2582
        self._override_globals_in_method(tt, "create_file",
2583
            {"open": self._fake_open_raises_before})
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
2584
        self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2585
        path = tt._limbo_name(trans_id)
2586
        self.assertPathDoesNotExist(path)
2587
        tt.finalize()
2588
        self.assertPathDoesNotExist(tt._limbodir)
2589
2590
    def test_root_create_file_open_raises_after_creation(self):
2591
        tt, trans_id = self.create_transform_and_root_trans_id()
2592
        self._override_globals_in_method(tt, "create_file",
2593
            {"open": self._fake_open_raises_after})
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
2594
        self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2595
        path = tt._limbo_name(trans_id)
2596
        self.assertPathExists(path)
5876.3.2 by Martin
Change test that expects ImmortalLimbo to want the sensible thing instead, and fail for now
2597
        tt.finalize()
2598
        self.assertPathDoesNotExist(path)
2599
        self.assertPathDoesNotExist(tt._limbodir)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2600
2601
    def test_subdir_create_file_open_raises_before_creation(self):
2602
        tt, trans_id = self.create_transform_and_subdir_trans_id()
2603
        self._override_globals_in_method(tt, "create_file",
2604
            {"open": self._fake_open_raises_before})
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
2605
        self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2606
        path = tt._limbo_name(trans_id)
2607
        self.assertPathDoesNotExist(path)
2608
        tt.finalize()
2609
        self.assertPathDoesNotExist(tt._limbodir)
2610
2611
    def test_subdir_create_file_open_raises_after_creation(self):
2612
        tt, trans_id = self.create_transform_and_subdir_trans_id()
2613
        self._override_globals_in_method(tt, "create_file",
2614
            {"open": self._fake_open_raises_after})
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
2615
        self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2616
        path = tt._limbo_name(trans_id)
2617
        self.assertPathExists(path)
2618
        tt.finalize()
2619
        self.assertPathDoesNotExist(path)
2620
        self.assertPathDoesNotExist(tt._limbodir)
2621
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
2622
    def test_rename_in_limbo_rename_raises_after_rename(self):
2623
        tt, trans_id = self.create_transform_and_root_trans_id()
2624
        parent1 = tt.new_directory('parent1', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2625
        child1 = tt.new_file('child1', parent1, [b'contents'])
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
2626
        parent2 = tt.new_directory('parent2', tt.root)
2627
2628
        class FakeOSModule(object):
2629
            def rename(self, old, new):
2630
                os.rename(old, new)
2631
                raise RuntimeError
2632
        self._override_globals_in_method(tt, "_rename_in_limbo",
2633
            {"os": FakeOSModule()})
2634
        self.assertRaises(
2635
            RuntimeError, tt.adjust_path, "child1", parent2, child1)
2636
        path = osutils.pathjoin(tt._limbo_name(parent2), "child1")
2637
        self.assertPathExists(path)
2638
        tt.finalize()
2639
        self.assertPathDoesNotExist(path)
2640
        self.assertPathDoesNotExist(tt._limbodir)
2641
2642
    def test_rename_in_limbo_rename_raises_before_rename(self):
2643
        tt, trans_id = self.create_transform_and_root_trans_id()
2644
        parent1 = tt.new_directory('parent1', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2645
        child1 = tt.new_file('child1', parent1, [b'contents'])
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
2646
        parent2 = tt.new_directory('parent2', tt.root)
2647
2648
        class FakeOSModule(object):
2649
            def rename(self, old, new):
2650
                raise RuntimeError
2651
        self._override_globals_in_method(tt, "_rename_in_limbo",
2652
            {"os": FakeOSModule()})
2653
        self.assertRaises(
2654
            RuntimeError, tt.adjust_path, "child1", parent2, child1)
2655
        path = osutils.pathjoin(tt._limbo_name(parent1), "child1")
2656
        self.assertPathExists(path)
2657
        tt.finalize()
2658
        self.assertPathDoesNotExist(path)
2659
        self.assertPathDoesNotExist(tt._limbodir)
2660
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
2661
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
2662
class TestTransformMissingParent(tests.TestCaseWithTransport):
2663
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
2664
    def make_tt_with_versioned_dir(self):
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
2665
        wt = self.make_branch_and_tree('.')
2666
        self.build_tree(['dir/',])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2667
        wt.add(['dir'], [b'dir-id'])
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
2668
        wt.commit('Create dir')
2669
        tt = TreeTransform(wt)
2670
        self.addCleanup(tt.finalize)
2671
        return wt, tt
2672
2673
    def test_resolve_create_parent_for_versioned_file(self):
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
2674
        wt, tt = self.make_tt_with_versioned_dir()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
2675
        dir_tid = tt.trans_id_tree_path('dir')
6973.10.1 by Jelmer Vernooij
Fix some tests.
2676
        file_tid = tt.new_file('file', dir_tid, [b'Contents'], file_id=b'file-id')
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
2677
        tt.delete_contents(dir_tid)
2678
        tt.unversion_file(dir_tid)
2679
        conflicts = resolve_conflicts(tt)
2680
        # one conflict for the missing directory, one for the unversioned
2681
        # parent
2682
        self.assertLength(2, conflicts)
2683
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
2684
    def test_non_versioned_file_create_conflict(self):
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
2685
        wt, tt = self.make_tt_with_versioned_dir()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
2686
        dir_tid = tt.trans_id_tree_path('dir')
6973.10.1 by Jelmer Vernooij
Fix some tests.
2687
        tt.new_file('file', dir_tid, [b'Contents'])
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
2688
        tt.delete_contents(dir_tid)
2689
        tt.unversion_file(dir_tid)
2690
        conflicts = resolve_conflicts(tt)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
2691
        # no conflicts or rather: orphaning 'file' resolve the 'dir' conflict
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
2692
        self.assertLength(1, conflicts)
2693
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
2694
                         conflicts.pop())
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
2695
2696
6973.10.1 by Jelmer Vernooij
Fix some tests.
2697
A_ENTRY = (b'a-id', ('a', 'a'), True, (True, True),
2698
                  (b'TREE_ROOT', b'TREE_ROOT'), ('a', 'a'), ('file', 'file'),
3363.19.1 by Aaron Bentley
Make PreviewTree.iter_changes accept all options.
2699
                  (False, False))
6973.10.1 by Jelmer Vernooij
Fix some tests.
2700
ROOT_ENTRY = (b'TREE_ROOT', ('', ''), False, (True, True), (None, None),
5050.57.1 by Aaron Bentley
Make is_executable treat symlinks and directories the same across tree types.
2701
              ('', ''), ('directory', 'directory'), (False, False))
3363.19.1 by Aaron Bentley
Make PreviewTree.iter_changes accept all options.
2702
2703
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2704
class TestTransformPreview(tests.TestCaseWithTransport):
2705
2706
    def create_tree(self):
2707
        tree = self.make_branch_and_tree('.')
6855.4.1 by Jelmer Vernooij
Yet more bees.
2708
        self.build_tree_contents([('a', b'content 1')])
2709
        tree.set_root_id(b'TREE_ROOT')
2710
        tree.add('a', b'a-id')
2711
        tree.commit('rev1', rev_id=b'rev1')
6973.5.2 by Jelmer Vernooij
Add more bees.
2712
        return tree.branch.repository.revision_tree(b'rev1')
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2713
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
2714
    def get_empty_preview(self):
2715
        repository = self.make_repository('repo')
2716
        tree = repository.revision_tree(_mod_revision.NULL_REVISION)
3199.1.4 by Vincent Ladeuil
Fix 16 leaked tmp dirs. Probably indicates a lock handling problem with TransformPreview
2717
        preview = TransformPreview(tree)
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
2718
        self.addCleanup(preview.finalize)
3199.1.4 by Vincent Ladeuil
Fix 16 leaked tmp dirs. Probably indicates a lock handling problem with TransformPreview
2719
        return preview
2720
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2721
    def test_transform_preview(self):
2722
        revision_tree = self.create_tree()
2723
        preview = TransformPreview(revision_tree)
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
2724
        self.addCleanup(preview.finalize)
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2725
2726
    def test_transform_preview_tree(self):
2727
        revision_tree = self.create_tree()
2728
        preview = TransformPreview(revision_tree)
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
2729
        self.addCleanup(preview.finalize)
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2730
        preview.get_preview_tree()
2731
3008.1.5 by Michael Hudson
a more precise test
2732
    def test_transform_new_file(self):
2733
        revision_tree = self.create_tree()
2734
        preview = TransformPreview(revision_tree)
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
2735
        self.addCleanup(preview.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2736
        preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id')
3008.1.5 by Michael Hudson
a more precise test
2737
        preview_tree = preview.get_preview_tree()
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
2738
        self.assertEqual(preview_tree.kind('file2'), 'file')
6973.10.1 by Jelmer Vernooij
Fix some tests.
2739
        with preview_tree.get_file('file2', b'file2-id') as f:
2740
            self.assertEqual(f.read(), b'content B\n')
3008.1.5 by Michael Hudson
a more precise test
2741
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2742
    def test_diff_preview_tree(self):
2743
        revision_tree = self.create_tree()
2744
        preview = TransformPreview(revision_tree)
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
2745
        self.addCleanup(preview.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2746
        preview.new_file('file2', preview.root, [b'content B\n'], b'file2-id')
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2747
        preview_tree = preview.get_preview_tree()
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
2748
        out = BytesIO()
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
2749
        show_diff_trees(revision_tree, preview_tree, out)
3008.1.4 by Michael Hudson
Merge test enhancements
2750
        lines = out.getvalue().splitlines()
2751
        self.assertEqual(lines[0], "=== added file 'file2'")
2752
        # 3 lines of diff administrivia
2753
        self.assertEqual(lines[4], "+content B")
3008.2.1 by Aaron Bentley
Ensure conflict resolution works
2754
2755
    def test_transform_conflicts(self):
2756
        revision_tree = self.create_tree()
2757
        preview = TransformPreview(revision_tree)
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
2758
        self.addCleanup(preview.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2759
        preview.new_file('a', preview.root, [b'content 2'])
3008.2.1 by Aaron Bentley
Ensure conflict resolution works
2760
        resolve_conflicts(preview)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2761
        trans_id = preview.trans_id_file_id(b'a-id')
3008.2.1 by Aaron Bentley
Ensure conflict resolution works
2762
        self.assertEqual('a.moved', preview.final_name(trans_id))
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2763
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2764
    def get_tree_and_preview_tree(self):
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2765
        revision_tree = self.create_tree()
2766
        preview = TransformPreview(revision_tree)
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
2767
        self.addCleanup(preview.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2768
        a_trans_id = preview.trans_id_file_id(b'a-id')
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2769
        preview.delete_contents(a_trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
2770
        preview.create_file([b'b content'], a_trans_id)
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2771
        preview_tree = preview.get_preview_tree()
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2772
        return revision_tree, preview_tree
2773
2774
    def test_iter_changes(self):
2775
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
6405.2.10 by Jelmer Vernooij
Fix more tests.
2776
        root = revision_tree.get_root_id()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2777
        self.assertEqual([(b'a-id', ('a', 'a'), True, (True, True),
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2778
                          (root, root), ('a', 'a'), ('file', 'file'),
2779
                          (False, False))],
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2780
                          list(preview_tree.iter_changes(revision_tree)))
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2781
3363.19.1 by Aaron Bentley
Make PreviewTree.iter_changes accept all options.
2782
    def test_include_unchanged_succeeds(self):
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2783
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
3363.19.1 by Aaron Bentley
Make PreviewTree.iter_changes accept all options.
2784
        changes = preview_tree.iter_changes(revision_tree,
2785
                                            include_unchanged=True)
6405.2.10 by Jelmer Vernooij
Fix more tests.
2786
        root = revision_tree.get_root_id()
3363.19.1 by Aaron Bentley
Make PreviewTree.iter_changes accept all options.
2787
2788
        self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes))
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2789
2790
    def test_specific_files(self):
2791
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
3363.19.1 by Aaron Bentley
Make PreviewTree.iter_changes accept all options.
2792
        changes = preview_tree.iter_changes(revision_tree,
2793
                                            specific_files=[''])
5050.57.1 by Aaron Bentley
Make is_executable treat symlinks and directories the same across tree types.
2794
        self.assertEqual([A_ENTRY], list(changes))
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2795
3363.19.1 by Aaron Bentley
Make PreviewTree.iter_changes accept all options.
2796
    def test_want_unversioned(self):
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2797
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
3363.19.1 by Aaron Bentley
Make PreviewTree.iter_changes accept all options.
2798
        changes = preview_tree.iter_changes(revision_tree,
2799
                                            want_unversioned=True)
5050.57.1 by Aaron Bentley
Make is_executable treat symlinks and directories the same across tree types.
2800
        self.assertEqual([A_ENTRY], list(changes))
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2801
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2802
    def test_ignore_extra_trees_no_specific_files(self):
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2803
        # extra_trees is harmless without specific_files, so we'll silently
2804
        # accept it, even though we won't use it.
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2805
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2806
        preview_tree.iter_changes(revision_tree, extra_trees=[preview_tree])
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2807
2808
    def test_ignore_require_versioned_no_specific_files(self):
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2809
        # require_versioned is meaningless without specific_files.
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2810
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
2811
        preview_tree.iter_changes(revision_tree, require_versioned=False)
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2812
2813
    def test_ignore_pb(self):
3008.1.17 by Aaron Bentley
Test unused parameters of preview_tree._iter_changes
2814
        # pb could be supported, but TT.iter_changes doesn't support it.
3008.1.31 by Aaron Bentley
Split PreviewTree._iter_changes parameter tests into smaller tests
2815
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
4961.2.9 by Martin Pool
Rip out most remaining uses of DummyProgressBar
2816
        preview_tree.iter_changes(revision_tree)
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
2817
2818
    def test_kind(self):
2819
        revision_tree = self.create_tree()
2820
        preview = TransformPreview(revision_tree)
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
2821
        self.addCleanup(preview.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2822
        preview.new_file('file', preview.root, [b'contents'], b'file-id')
6973.13.2 by Jelmer Vernooij
Fix some more tests.
2823
        preview.new_directory('directory', preview.root, b'dir-id')
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
2824
        preview_tree = preview.get_preview_tree()
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
2825
        self.assertEqual('file', preview_tree.kind('file'))
2826
        self.assertEqual('directory', preview_tree.kind('directory'))
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
2827
2828
    def test_get_file_mtime(self):
2829
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2830
        file_trans_id = preview.new_file('file', preview.root, [b'contents'],
6855.4.2 by Jelmer Vernooij
Fix test.
2831
                                         b'file-id')
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
2832
        limbo_path = preview._limbo_name(file_trans_id)
2833
        preview_tree = preview.get_preview_tree()
2834
        self.assertEqual(os.stat(limbo_path).st_mtime,
6855.4.1 by Jelmer Vernooij
Yet more bees.
2835
                         preview_tree.get_file_mtime('file', b'file-id'))
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
2836
4635.1.1 by Aaron Bentley
Fix OSError with renamed files in PreviewTree.
2837
    def test_get_file_mtime_renamed(self):
2838
        work_tree = self.make_branch_and_tree('tree')
2839
        self.build_tree(['tree/file'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2840
        work_tree.add('file', b'file-id')
4635.1.1 by Aaron Bentley
Fix OSError with renamed files in PreviewTree.
2841
        preview = TransformPreview(work_tree)
2842
        self.addCleanup(preview.finalize)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
2843
        file_trans_id = preview.trans_id_tree_path('file')
4635.1.1 by Aaron Bentley
Fix OSError with renamed files in PreviewTree.
2844
        preview.adjust_path('renamed', preview.root, file_trans_id)
2845
        preview_tree = preview.get_preview_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
2846
        preview_mtime = preview_tree.get_file_mtime('renamed', b'file-id')
2847
        work_mtime = work_tree.get_file_mtime('file', b'file-id')
4635.1.1 by Aaron Bentley
Fix OSError with renamed files in PreviewTree.
2848
5809.3.6 by Aaron Bentley
Fix PreviewTree.get_file_size.
2849
    def test_get_file_size(self):
2850
        work_tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
2851
        self.build_tree_contents([('tree/old', b'old')])
2852
        work_tree.add('old', b'old-id')
5809.3.6 by Aaron Bentley
Fix PreviewTree.get_file_size.
2853
        preview = TransformPreview(work_tree)
2854
        self.addCleanup(preview.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2855
        new_id = preview.new_file('name', preview.root, [b'contents'], b'new-id',
5809.3.6 by Aaron Bentley
Fix PreviewTree.get_file_size.
2856
                                  'executable')
2857
        tree = preview.get_preview_tree()
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
2858
        self.assertEqual(len('old'), tree.get_file_size('old'))
2859
        self.assertEqual(len('contents'), tree.get_file_size('name'))
5809.3.6 by Aaron Bentley
Fix PreviewTree.get_file_size.
2860
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
2861
    def test_get_file(self):
2862
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2863
        preview.new_file('file', preview.root, [b'contents'], b'file-id')
3008.1.18 by Aaron Bentley
Get supported PreviewTree functionality under test
2864
        preview_tree = preview.get_preview_tree()
6973.10.1 by Jelmer Vernooij
Fix some tests.
2865
        with preview_tree.get_file('file') as tree_file:
2866
            self.assertEqual(b'contents', tree_file.read())
3228.1.2 by James Henstridge
Simplify test, and move it down to be next to the other _PreviewTree tests.
2867
2868
    def test_get_symlink_target(self):
2869
        self.requireFeature(SymlinkFeature)
2870
        preview = self.get_empty_preview()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
2871
        preview.new_symlink('symlink', preview.root, 'target', b'symlink-id')
3228.1.2 by James Henstridge
Simplify test, and move it down to be next to the other _PreviewTree tests.
2872
        preview_tree = preview.get_preview_tree()
2873
        self.assertEqual('target',
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
2874
                         preview_tree.get_symlink_target('symlink'))
3363.2.18 by Aaron Bentley
Implement correct all_file_ids for PreviewTree
2875
2876
    def test_all_file_ids(self):
2877
        tree = self.make_branch_and_tree('tree')
2878
        self.build_tree(['tree/a', 'tree/b', 'tree/c'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2879
        tree.add(['a', 'b', 'c'], [b'a-id', b'b-id', b'c-id'])
3363.2.18 by Aaron Bentley
Implement correct all_file_ids for PreviewTree
2880
        preview = TransformPreview(tree)
2881
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
2882
        preview.unversion_file(preview.trans_id_file_id(b'b-id'))
2883
        c_trans_id = preview.trans_id_file_id(b'c-id')
3363.2.18 by Aaron Bentley
Implement correct all_file_ids for PreviewTree
2884
        preview.unversion_file(c_trans_id)
6855.4.1 by Jelmer Vernooij
Yet more bees.
2885
        preview.version_file(b'c-id', c_trans_id)
3363.2.18 by Aaron Bentley
Implement correct all_file_ids for PreviewTree
2886
        preview_tree = preview.get_preview_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
2887
        self.assertEqual({b'a-id', b'c-id', tree.get_root_id()},
3363.2.18 by Aaron Bentley
Implement correct all_file_ids for PreviewTree
2888
                         preview_tree.all_file_ids())
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2889
2890
    def test_path2id_deleted_unchanged(self):
2891
        tree = self.make_branch_and_tree('tree')
2892
        self.build_tree(['tree/unchanged', 'tree/deleted'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2893
        tree.add(['unchanged', 'deleted'], [b'unchanged-id', b'deleted-id'])
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2894
        preview = TransformPreview(tree)
2895
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
2896
        preview.unversion_file(preview.trans_id_file_id(b'deleted-id'))
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2897
        preview_tree = preview.get_preview_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
2898
        self.assertEqual(b'unchanged-id', preview_tree.path2id('unchanged'))
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
2899
        self.assertFalse(preview_tree.is_versioned('deleted'))
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2900
2901
    def test_path2id_created(self):
2902
        tree = self.make_branch_and_tree('tree')
2903
        self.build_tree(['tree/unchanged'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2904
        tree.add(['unchanged'], [b'unchanged-id'])
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2905
        preview = TransformPreview(tree)
2906
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
2907
        preview.new_file('new', preview.trans_id_file_id(b'unchanged-id'),
6973.10.1 by Jelmer Vernooij
Fix some tests.
2908
            [b'contents'], b'new-id')
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2909
        preview_tree = preview.get_preview_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
2910
        self.assertEqual(b'new-id', preview_tree.path2id('unchanged/new'))
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2911
2912
    def test_path2id_moved(self):
2913
        tree = self.make_branch_and_tree('tree')
2914
        self.build_tree(['tree/old_parent/', 'tree/old_parent/child'])
2915
        tree.add(['old_parent', 'old_parent/child'],
6855.4.1 by Jelmer Vernooij
Yet more bees.
2916
                 [b'old_parent-id', b'child-id'])
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2917
        preview = TransformPreview(tree)
2918
        self.addCleanup(preview.finalize)
2919
        new_parent = preview.new_directory('new_parent', preview.root,
6855.4.1 by Jelmer Vernooij
Yet more bees.
2920
                                           b'new_parent-id')
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2921
        preview.adjust_path('child', new_parent,
6855.4.1 by Jelmer Vernooij
Yet more bees.
2922
                            preview.trans_id_file_id(b'child-id'))
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2923
        preview_tree = preview.get_preview_tree()
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
2924
        self.assertFalse(preview_tree.is_versioned('old_parent/child'))
6855.4.1 by Jelmer Vernooij
Yet more bees.
2925
        self.assertEqual(b'child-id', preview_tree.path2id('new_parent/child'))
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2926
2927
    def test_path2id_renamed_parent(self):
2928
        tree = self.make_branch_and_tree('tree')
2929
        self.build_tree(['tree/old_name/', 'tree/old_name/child'])
2930
        tree.add(['old_name', 'old_name/child'],
6855.4.1 by Jelmer Vernooij
Yet more bees.
2931
                 [b'parent-id', b'child-id'])
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2932
        preview = TransformPreview(tree)
2933
        self.addCleanup(preview.finalize)
2934
        preview.adjust_path('new_name', preview.root,
6855.4.1 by Jelmer Vernooij
Yet more bees.
2935
                            preview.trans_id_file_id(b'parent-id'))
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
2936
        preview_tree = preview.get_preview_tree()
6852.3.1 by Jelmer Vernooij
add Tree.is_versioned.
2937
        self.assertFalse(preview_tree.is_versioned('old_name/child'))
6855.4.1 by Jelmer Vernooij
Yet more bees.
2938
        self.assertEqual(b'child-id', preview_tree.path2id('new_name/child'))
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2939
6885.6.1 by Jelmer Vernooij
Support specific_files argument to Tree.iter_entries_by_dir.
2940
    def assertMatchingIterEntries(self, tt, specific_files=None):
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2941
        preview_tree = tt.get_preview_tree()
2942
        preview_result = list(preview_tree.iter_entries_by_dir(
6885.6.1 by Jelmer Vernooij
Support specific_files argument to Tree.iter_entries_by_dir.
2943
                              specific_files=specific_files))
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2944
        tree = tt._tree
2945
        tt.apply()
6885.6.2 by Jelmer Vernooij
Use specific_files.
2946
        actual_result = list(tree.iter_entries_by_dir(
2947
            specific_files=specific_files))
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2948
        self.assertEqual(actual_result, preview_result)
2949
2950
    def test_iter_entries_by_dir_new(self):
2951
        tree = self.make_branch_and_tree('tree')
2952
        tt = TreeTransform(tree)
6973.10.1 by Jelmer Vernooij
Fix some tests.
2953
        tt.new_file('new', tt.root, [b'contents'], b'new-id')
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2954
        self.assertMatchingIterEntries(tt)
2955
2956
    def test_iter_entries_by_dir_deleted(self):
2957
        tree = self.make_branch_and_tree('tree')
2958
        self.build_tree(['tree/deleted'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2959
        tree.add('deleted', b'deleted-id')
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2960
        tt = TreeTransform(tree)
6855.4.1 by Jelmer Vernooij
Yet more bees.
2961
        tt.delete_contents(tt.trans_id_file_id(b'deleted-id'))
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2962
        self.assertMatchingIterEntries(tt)
2963
2964
    def test_iter_entries_by_dir_unversioned(self):
2965
        tree = self.make_branch_and_tree('tree')
2966
        self.build_tree(['tree/removed'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2967
        tree.add('removed', b'removed-id')
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2968
        tt = TreeTransform(tree)
6855.4.1 by Jelmer Vernooij
Yet more bees.
2969
        tt.unversion_file(tt.trans_id_file_id(b'removed-id'))
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2970
        self.assertMatchingIterEntries(tt)
2971
2972
    def test_iter_entries_by_dir_moved(self):
2973
        tree = self.make_branch_and_tree('tree')
2974
        self.build_tree(['tree/moved', 'tree/new_parent/'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2975
        tree.add(['moved', 'new_parent'], [b'moved-id', b'new_parent-id'])
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2976
        tt = TreeTransform(tree)
6855.4.1 by Jelmer Vernooij
Yet more bees.
2977
        tt.adjust_path('moved', tt.trans_id_file_id(b'new_parent-id'),
2978
                       tt.trans_id_file_id(b'moved-id'))
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2979
        self.assertMatchingIterEntries(tt)
2980
6885.6.4 by Jelmer Vernooij
Tree transform - avoid iter_entries_by_dir(specific_file_ids=).
2981
    def test_iter_entries_by_dir_specific_files(self):
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2982
        tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
2983
        tree.set_root_id(b'tree-root-id')
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2984
        self.build_tree(['tree/parent/', 'tree/parent/child'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
2985
        tree.add(['parent', 'parent/child'], [b'parent-id', b'child-id'])
3363.2.21 by Aaron Bentley
Implement iter_entries_by_dir
2986
        tt = TreeTransform(tree)
6885.6.1 by Jelmer Vernooij
Support specific_files argument to Tree.iter_entries_by_dir.
2987
        self.assertMatchingIterEntries(tt, ['', 'parent/child'])
3363.2.26 by Aaron Bentley
Get symlinks working
2988
2989
    def test_symlink_content_summary(self):
2990
        self.requireFeature(SymlinkFeature)
2991
        preview = self.get_empty_preview()
6855.4.1 by Jelmer Vernooij
Yet more bees.
2992
        preview.new_symlink('path', preview.root, 'target', b'path-id')
3363.2.26 by Aaron Bentley
Get symlinks working
2993
        summary = preview.get_preview_tree().path_content_summary('path')
2994
        self.assertEqual(('symlink', None, None, 'target'), summary)
3363.2.27 by Aaron Bentley
Make path_content_summary a core API
2995
2996
    def test_missing_content_summary(self):
2997
        preview = self.get_empty_preview()
2998
        summary = preview.get_preview_tree().path_content_summary('path')
2999
        self.assertEqual(('missing', None, None, None), summary)
3000
3001
    def test_deleted_content_summary(self):
3002
        tree = self.make_branch_and_tree('tree')
3003
        self.build_tree(['tree/path/'])
3004
        tree.add('path')
3005
        preview = TransformPreview(tree)
3006
        self.addCleanup(preview.finalize)
3007
        preview.delete_contents(preview.trans_id_tree_path('path'))
3008
        summary = preview.get_preview_tree().path_content_summary('path')
3009
        self.assertEqual(('missing', None, None, None), summary)
3010
3363.2.30 by Aaron Bentley
Improve execute bit testing
3011
    def test_file_content_summary_executable(self):
3012
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3013
        path_id = preview.new_file('path', preview.root, [b'contents'], b'path-id')
3363.2.30 by Aaron Bentley
Improve execute bit testing
3014
        preview.set_executability(True, path_id)
3015
        summary = preview.get_preview_tree().path_content_summary('path')
3016
        self.assertEqual(4, len(summary))
3017
        self.assertEqual('file', summary[0])
3018
        # size must be known
3019
        self.assertEqual(len('contents'), summary[1])
3020
        # executable
3021
        self.assertEqual(True, summary[2])
3363.2.31 by Aaron Bentley
Tweak tests
3022
        # will not have hash (not cheap to determine)
3023
        self.assertIs(None, summary[3])
3363.2.30 by Aaron Bentley
Improve execute bit testing
3024
3025
    def test_change_executability(self):
3026
        tree = self.make_branch_and_tree('tree')
3027
        self.build_tree(['tree/path'])
3028
        tree.add('path')
3029
        preview = TransformPreview(tree)
3030
        self.addCleanup(preview.finalize)
3031
        path_id = preview.trans_id_tree_path('path')
3032
        preview.set_executability(True, path_id)
3033
        summary = preview.get_preview_tree().path_content_summary('path')
3034
        self.assertEqual(True, summary[2])
3035
3363.2.27 by Aaron Bentley
Make path_content_summary a core API
3036
    def test_file_content_summary_non_exec(self):
3037
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3038
        preview.new_file('path', preview.root, [b'contents'], b'path-id')
3363.2.27 by Aaron Bentley
Make path_content_summary a core API
3039
        summary = preview.get_preview_tree().path_content_summary('path')
3040
        self.assertEqual(4, len(summary))
3041
        self.assertEqual('file', summary[0])
3042
        # size must be known
3363.2.30 by Aaron Bentley
Improve execute bit testing
3043
        self.assertEqual(len('contents'), summary[1])
3363.2.27 by Aaron Bentley
Make path_content_summary a core API
3044
        # not executable
4789.15.3 by John Arbash Meinel
PreviewTree now returns False for exec bit properly.
3045
        self.assertEqual(False, summary[2])
3363.2.31 by Aaron Bentley
Tweak tests
3046
        # will not have hash (not cheap to determine)
3047
        self.assertIs(None, summary[3])
3363.2.27 by Aaron Bentley
Make path_content_summary a core API
3048
3049
    def test_dir_content_summary(self):
3050
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3051
        preview.new_directory('path', preview.root, b'path-id')
3363.2.27 by Aaron Bentley
Make path_content_summary a core API
3052
        summary = preview.get_preview_tree().path_content_summary('path')
3053
        self.assertEqual(('directory', None, None, None), summary)
3054
3055
    def test_tree_content_summary(self):
3056
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3057
        path = preview.new_directory('path', preview.root, b'path-id')
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
3058
        preview.set_tree_reference(b'rev-1', path)
3363.2.27 by Aaron Bentley
Make path_content_summary a core API
3059
        summary = preview.get_preview_tree().path_content_summary('path')
3060
        self.assertEqual(4, len(summary))
3061
        self.assertEqual('tree-reference', summary[0])
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3062
3063
    def test_annotate(self):
3064
        tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3065
        self.build_tree_contents([('tree/file', b'a\n')])
3066
        tree.add('file', b'file-id')
3067
        tree.commit('a', rev_id=b'one')
3068
        self.build_tree_contents([('tree/file', b'a\nb\n')])
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3069
        preview = TransformPreview(tree)
3070
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3071
        file_trans_id = preview.trans_id_file_id(b'file-id')
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3072
        preview.delete_contents(file_trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3073
        preview.create_file([b'a\nb\nc\n'], file_trans_id)
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3074
        preview_tree = preview.get_preview_tree()
3075
        expected = [
6973.10.1 by Jelmer Vernooij
Fix some tests.
3076
            (b'one', b'a\n'),
3077
            (b'me:', b'b\n'),
3078
            (b'me:', b'c\n'),
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3079
        ]
6855.4.1 by Jelmer Vernooij
Yet more bees.
3080
        annotation = preview_tree.annotate_iter('file', default_revision=b'me:')
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3081
        self.assertEqual(expected, annotation)
3082
3083
    def test_annotate_missing(self):
3084
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3085
        preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id')
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3086
        preview_tree = preview.get_preview_tree()
3087
        expected = [
6973.10.1 by Jelmer Vernooij
Fix some tests.
3088
            (b'me:', b'a\n'),
3089
            (b'me:', b'b\n'),
3090
            (b'me:', b'c\n'),
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3091
         ]
6855.4.1 by Jelmer Vernooij
Yet more bees.
3092
        annotation = preview_tree.annotate_iter('file', default_revision=b'me:')
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3093
        self.assertEqual(expected, annotation)
3094
3363.7.3 by Aaron Bentley
Add test that annotate correctly handles renames
3095
    def test_annotate_rename(self):
3096
        tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3097
        self.build_tree_contents([('tree/file', b'a\n')])
3098
        tree.add('file', b'file-id')
3099
        tree.commit('a', rev_id=b'one')
3363.7.3 by Aaron Bentley
Add test that annotate correctly handles renames
3100
        preview = TransformPreview(tree)
3101
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3102
        file_trans_id = preview.trans_id_file_id(b'file-id')
3363.7.3 by Aaron Bentley
Add test that annotate correctly handles renames
3103
        preview.adjust_path('newname', preview.root, file_trans_id)
3104
        preview_tree = preview.get_preview_tree()
3105
        expected = [
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
3106
            (b'one', b'a\n'),
3363.7.3 by Aaron Bentley
Add test that annotate correctly handles renames
3107
        ]
6855.4.1 by Jelmer Vernooij
Yet more bees.
3108
        annotation = preview_tree.annotate_iter('file', default_revision=b'me:')
3363.7.3 by Aaron Bentley
Add test that annotate correctly handles renames
3109
        self.assertEqual(expected, annotation)
3110
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3111
    def test_annotate_deleted(self):
3112
        tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3113
        self.build_tree_contents([('tree/file', b'a\n')])
3114
        tree.add('file', b'file-id')
3115
        tree.commit('a', rev_id=b'one')
3116
        self.build_tree_contents([('tree/file', b'a\nb\n')])
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3117
        preview = TransformPreview(tree)
3118
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3119
        file_trans_id = preview.trans_id_file_id(b'file-id')
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3120
        preview.delete_contents(file_trans_id)
3121
        preview_tree = preview.get_preview_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
3122
        annotation = preview_tree.annotate_iter('file', default_revision=b'me:')
3363.2.33 by Aaron Bentley
Implement PreviewTree.annotate_iter
3123
        self.assertIs(None, annotation)
3124
3363.2.36 by Aaron Bentley
Fix PreviewTree.stored_kind
3125
    def test_stored_kind(self):
3126
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3127
        preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id')
3363.2.36 by Aaron Bentley
Fix PreviewTree.stored_kind
3128
        preview_tree = preview.get_preview_tree()
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
3129
        self.assertEqual('file', preview_tree.stored_kind('file'))
3363.2.37 by Aaron Bentley
Fix is_executable
3130
3131
    def test_is_executable(self):
3132
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3133
        preview.new_file('file', preview.root, [b'a\nb\nc\n'], b'file-id')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3134
        preview.set_executability(True, preview.trans_id_file_id(b'file-id'))
3363.2.37 by Aaron Bentley
Fix is_executable
3135
        preview_tree = preview.get_preview_tree()
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
3136
        self.assertEqual(True, preview_tree.is_executable('file'))
3363.9.1 by Aaron Bentley
Implement plan_merge, refactoring various bits
3137
3571.1.1 by Aaron Bentley
Allow set/get of parent_ids in PreviewTree
3138
    def test_get_set_parent_ids(self):
3139
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
3140
        self.assertEqual([], preview_tree.get_parent_ids())
6855.4.1 by Jelmer Vernooij
Yet more bees.
3141
        preview_tree.set_parent_ids([b'rev-1'])
3142
        self.assertEqual([b'rev-1'], preview_tree.get_parent_ids())
3571.1.1 by Aaron Bentley
Allow set/get of parent_ids in PreviewTree
3143
3363.9.1 by Aaron Bentley
Implement plan_merge, refactoring various bits
3144
    def test_plan_file_merge(self):
3145
        work_a = self.make_branch_and_tree('wta')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3146
        self.build_tree_contents([('wta/file', b'a\nb\nc\nd\n')])
3147
        work_a.add('file', b'file-id')
3363.9.7 by Aaron Bentley
Fix up to use set_parent_ids
3148
        base_id = work_a.commit('base version')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
3149
        tree_b = work_a.controldir.sprout('wtb').open_workingtree()
3363.9.1 by Aaron Bentley
Implement plan_merge, refactoring various bits
3150
        preview = TransformPreview(work_a)
3151
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3152
        trans_id = preview.trans_id_file_id(b'file-id')
3363.9.1 by Aaron Bentley
Implement plan_merge, refactoring various bits
3153
        preview.delete_contents(trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3154
        preview.create_file([b'b\nc\nd\ne\n'], trans_id)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3155
        self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')])
3363.9.1 by Aaron Bentley
Implement plan_merge, refactoring various bits
3156
        tree_a = preview.get_preview_tree()
3363.9.7 by Aaron Bentley
Fix up to use set_parent_ids
3157
        tree_a.set_parent_ids([base_id])
3363.9.1 by Aaron Bentley
Implement plan_merge, refactoring various bits
3158
        self.assertEqual([
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
3159
            ('killed-a', b'a\n'),
3160
            ('killed-b', b'b\n'),
3161
            ('unchanged', b'c\n'),
3162
            ('unchanged', b'd\n'),
3163
            ('new-a', b'e\n'),
3164
            ('new-b', b'f\n'),
6855.4.1 by Jelmer Vernooij
Yet more bees.
3165
        ], list(tree_a.plan_file_merge(b'file-id', tree_b)))
3363.9.8 by Aaron Bentley
Ensure plan_file_merge works with a RevisionTree as the basis
3166
3167
    def test_plan_file_merge_revision_tree(self):
3168
        work_a = self.make_branch_and_tree('wta')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3169
        self.build_tree_contents([('wta/file', b'a\nb\nc\nd\n')])
3170
        work_a.add('file', b'file-id')
3363.9.8 by Aaron Bentley
Ensure plan_file_merge works with a RevisionTree as the basis
3171
        base_id = work_a.commit('base version')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
3172
        tree_b = work_a.controldir.sprout('wtb').open_workingtree()
3363.9.8 by Aaron Bentley
Ensure plan_file_merge works with a RevisionTree as the basis
3173
        preview = TransformPreview(work_a.basis_tree())
3174
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3175
        trans_id = preview.trans_id_file_id(b'file-id')
3363.9.8 by Aaron Bentley
Ensure plan_file_merge works with a RevisionTree as the basis
3176
        preview.delete_contents(trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3177
        preview.create_file([b'b\nc\nd\ne\n'], trans_id)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3178
        self.build_tree_contents([('wtb/file', b'a\nc\nd\nf\n')])
3363.9.8 by Aaron Bentley
Ensure plan_file_merge works with a RevisionTree as the basis
3179
        tree_a = preview.get_preview_tree()
3180
        tree_a.set_parent_ids([base_id])
3181
        self.assertEqual([
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
3182
            ('killed-a', b'a\n'),
3183
            ('killed-b', b'b\n'),
3184
            ('unchanged', b'c\n'),
3185
            ('unchanged', b'd\n'),
3186
            ('new-a', b'e\n'),
3187
            ('new-b', b'f\n'),
6855.4.1 by Jelmer Vernooij
Yet more bees.
3188
        ], list(tree_a.plan_file_merge(b'file-id', tree_b)))
3363.9.9 by Aaron Bentley
Implement walkdirs in terms of TreeTransform
3189
3190
    def test_walkdirs(self):
3191
        preview = self.get_empty_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3192
        root = preview.new_directory('', ROOT_PARENT, b'tree-root')
4634.57.3 by Aaron Bentley
Fix failing test.
3193
        # FIXME: new_directory should mark root.
4634.122.6 by John Arbash Meinel
Fix a test that used 'adjust_path' to set the root.
3194
        preview.fixup_new_roots()
3363.9.9 by Aaron Bentley
Implement walkdirs in terms of TreeTransform
3195
        preview_tree = preview.get_preview_tree()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3196
        file_trans_id = preview.new_file('a', preview.root, [b'contents'],
6855.4.1 by Jelmer Vernooij
Yet more bees.
3197
                                         b'a-id')
3198
        expected = [(('', b'tree-root'),
3199
                    [('a', 'a', 'file', None, b'a-id', 'file')])]
3363.9.9 by Aaron Bentley
Implement walkdirs in terms of TreeTransform
3200
        self.assertEqual(expected, list(preview_tree.walkdirs()))
3363.13.2 by Aaron Bentley
Test specific cases for PreviewTree.extras
3201
3202
    def test_extras(self):
3203
        work_tree = self.make_branch_and_tree('tree')
3204
        self.build_tree(['tree/removed-file', 'tree/existing-file',
3205
                         'tree/not-removed-file'])
3206
        work_tree.add(['removed-file', 'not-removed-file'])
3207
        preview = TransformPreview(work_tree)
3363.13.3 by Aaron Bentley
Add cleanup
3208
        self.addCleanup(preview.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
3209
        preview.new_file('new-file', preview.root, [b'contents'])
3210
        preview.new_file('new-versioned-file', preview.root, [b'contents'],
6855.4.1 by Jelmer Vernooij
Yet more bees.
3211
                         b'new-versioned-id')
3363.13.2 by Aaron Bentley
Test specific cases for PreviewTree.extras
3212
        tree = preview.get_preview_tree()
3213
        preview.unversion_file(preview.trans_id_tree_path('removed-file'))
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
3214
        self.assertEqual({'new-file', 'removed-file', 'existing-file'},
3363.13.2 by Aaron Bentley
Test specific cases for PreviewTree.extras
3215
                         set(tree.extras()))
3363.17.1 by Aaron Bentley
Avoid inventory for merge and transform code
3216
3363.17.2 by Aaron Bentley
Add text checking
3217
    def test_merge_into_preview(self):
3363.17.1 by Aaron Bentley
Avoid inventory for merge and transform code
3218
        work_tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3219
        self.build_tree_contents([('tree/file', b'b\n')])
3220
        work_tree.add('file', b'file-id')
3363.17.1 by Aaron Bentley
Avoid inventory for merge and transform code
3221
        work_tree.commit('first commit')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
3222
        child_tree = work_tree.controldir.sprout('child').open_workingtree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
3223
        self.build_tree_contents([('child/file', b'b\nc\n')])
3363.17.1 by Aaron Bentley
Avoid inventory for merge and transform code
3224
        child_tree.commit('child commit')
3225
        child_tree.lock_write()
3226
        self.addCleanup(child_tree.unlock)
3227
        work_tree.lock_write()
3228
        self.addCleanup(work_tree.unlock)
3229
        preview = TransformPreview(work_tree)
3230
        self.addCleanup(preview.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3231
        file_trans_id = preview.trans_id_file_id(b'file-id')
3363.17.6 by Aaron Bentley
Improve test scenario
3232
        preview.delete_contents(file_trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3233
        preview.create_file([b'a\nb\n'], file_trans_id)
4634.57.2 by Aaron Bentley
Fix failing test.
3234
        preview_tree = preview.get_preview_tree()
6719.1.4 by Jelmer Vernooij
Fix remaining tests.
3235
        merger = Merger.from_revision_ids(preview_tree,
3363.17.1 by Aaron Bentley
Avoid inventory for merge and transform code
3236
                                          child_tree.branch.last_revision(),
3237
                                          other_branch=child_tree.branch,
3238
                                          tree_branch=work_tree.branch)
3239
        merger.merge_type = Merge3Merger
3240
        tt = merger.make_merger().make_preview_transform()
3363.17.2 by Aaron Bentley
Add text checking
3241
        self.addCleanup(tt.finalize)
3242
        final_tree = tt.get_preview_tree()
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
3243
        self.assertEqual(
6973.7.3 by Jelmer Vernooij
Fix some more tests.
3244
                b'a\nb\nc\n',
6855.4.1 by Jelmer Vernooij
Yet more bees.
3245
                final_tree.get_file_text(final_tree.id2path(b'file-id')))
3363.17.17 by Aaron Bentley
Start testing merging PreviewTree as OTHER
3246
3247
    def test_merge_preview_into_workingtree(self):
3248
        tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3249
        tree.set_root_id(b'TREE_ROOT')
3363.17.17 by Aaron Bentley
Start testing merging PreviewTree as OTHER
3250
        tt = TransformPreview(tree)
3251
        self.addCleanup(tt.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
3252
        tt.new_file('name', tt.root, [b'content'], b'file-id')
3363.17.17 by Aaron Bentley
Start testing merging PreviewTree as OTHER
3253
        tree2 = self.make_branch_and_tree('tree2')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3254
        tree2.set_root_id(b'TREE_ROOT')
3363.17.17 by Aaron Bentley
Start testing merging PreviewTree as OTHER
3255
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
6719.1.4 by Jelmer Vernooij
Fix remaining tests.
3256
                                         tree.basis_tree())
3363.17.17 by Aaron Bentley
Start testing merging PreviewTree as OTHER
3257
        merger.merge_type = Merge3Merger
3258
        merger.do_merge()
3363.17.18 by Aaron Bentley
Fix is_executable for PreviewTree
3259
3363.17.21 by Aaron Bentley
Conflicts are handled when merging from preview trees
3260
    def test_merge_preview_into_workingtree_handles_conflicts(self):
3261
        tree = self.make_branch_and_tree('tree')
6855.4.1 by Jelmer Vernooij
Yet more bees.
3262
        self.build_tree_contents([('tree/foo', b'bar')])
3263
        tree.add('foo', b'foo-id')
3363.17.21 by Aaron Bentley
Conflicts are handled when merging from preview trees
3264
        tree.commit('foo')
3265
        tt = TransformPreview(tree)
3266
        self.addCleanup(tt.finalize)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3267
        trans_id = tt.trans_id_file_id(b'foo-id')
3363.17.21 by Aaron Bentley
Conflicts are handled when merging from preview trees
3268
        tt.delete_contents(trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3269
        tt.create_file([b'baz'], trans_id)
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
3270
        tree2 = tree.controldir.sprout('tree2').open_workingtree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
3271
        self.build_tree_contents([('tree2/foo', b'qux')])
3363.17.21 by Aaron Bentley
Conflicts are handled when merging from preview trees
3272
        merger = Merger.from_uncommitted(tree2, tt.get_preview_tree(),
6719.1.4 by Jelmer Vernooij
Fix remaining tests.
3273
                                         tree.basis_tree())
3363.17.21 by Aaron Bentley
Conflicts are handled when merging from preview trees
3274
        merger.merge_type = Merge3Merger
3275
        merger.do_merge()
3276
5809.3.2 by Aaron Bentley
Support PreviewTree.has_filename.
3277
    def test_has_filename(self):
3278
        wt = self.make_branch_and_tree('tree')
3279
        self.build_tree(['tree/unmodified', 'tree/removed', 'tree/modified'])
3280
        tt = TransformPreview(wt)
3281
        removed_id = tt.trans_id_tree_path('removed')
3282
        tt.delete_contents(removed_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
3283
        tt.new_file('new', tt.root, [b'contents'])
5809.3.2 by Aaron Bentley
Support PreviewTree.has_filename.
3284
        modified_id = tt.trans_id_tree_path('modified')
3285
        tt.delete_contents(modified_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
3286
        tt.create_file([b'modified-contents'], modified_id)
5809.3.2 by Aaron Bentley
Support PreviewTree.has_filename.
3287
        self.addCleanup(tt.finalize)
3288
        tree = tt.get_preview_tree()
3289
        self.assertTrue(tree.has_filename('unmodified'))
3290
        self.assertFalse(tree.has_filename('not-present'))
3291
        self.assertFalse(tree.has_filename('removed'))
3292
        self.assertTrue(tree.has_filename('new'))
3293
        self.assertTrue(tree.has_filename('modified'))
3294
3363.17.18 by Aaron Bentley
Fix is_executable for PreviewTree
3295
    def test_is_executable(self):
3296
        tree = self.make_branch_and_tree('tree')
3297
        preview = TransformPreview(tree)
3298
        self.addCleanup(preview.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
3299
        preview.new_file('foo', preview.root, [b'bar'], b'baz-id')
3363.17.18 by Aaron Bentley
Fix is_executable for PreviewTree
3300
        preview_tree = preview.get_preview_tree()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3301
        self.assertEqual(False, preview_tree.is_executable('tree/foo', b'baz-id'))
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
3302
        self.assertEqual(False, preview_tree.is_executable('tree/foo'))
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3303
4354.4.4 by Aaron Bentley
Simplify by using CommitBuilder directly
3304
    def test_commit_preview_tree(self):
3305
        tree = self.make_branch_and_tree('tree')
3306
        rev_id = tree.commit('rev1')
3307
        tree.branch.lock_write()
3308
        self.addCleanup(tree.branch.unlock)
3309
        tt = TransformPreview(tree)
6973.10.1 by Jelmer Vernooij
Fix some tests.
3310
        tt.new_file('file', tt.root, [b'contents'], b'file_id')
4354.4.4 by Aaron Bentley
Simplify by using CommitBuilder directly
3311
        self.addCleanup(tt.finalize)
3312
        preview = tt.get_preview_tree()
3313
        preview.set_parent_ids([rev_id])
3314
        builder = tree.branch.get_commit_builder([rev_id])
3315
        list(builder.record_iter_changes(preview, rev_id, tt.iter_changes()))
3316
        builder.finish_inventory()
3317
        rev2_id = builder.commit('rev2')
3318
        rev2_tree = tree.branch.repository.revision_tree(rev2_id)
6973.7.3 by Jelmer Vernooij
Fix some more tests.
3319
        self.assertEqual(b'contents', rev2_tree.get_file_text('file'))
4354.4.4 by Aaron Bentley
Simplify by using CommitBuilder directly
3320
4634.79.1 by Aaron Bentley
TransformPreview uses ascii-only filenames.
3321
    def test_ascii_limbo_paths(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
3322
        self.requireFeature(features.UnicodeFilenameFeature)
4634.79.1 by Aaron Bentley
TransformPreview uses ascii-only filenames.
3323
        branch = self.make_branch('any')
3324
        tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION)
3325
        tt = TransformPreview(tree)
4789.25.7 by John Arbash Meinel
We can run the executable tests.
3326
        self.addCleanup(tt.finalize)
4634.79.1 by Aaron Bentley
TransformPreview uses ascii-only filenames.
3327
        foo_id = tt.new_directory('', ROOT_PARENT)
6973.10.1 by Jelmer Vernooij
Fix some tests.
3328
        bar_id = tt.new_file(u'\u1234bar', foo_id, [b'contents'])
4634.79.1 by Aaron Bentley
TransformPreview uses ascii-only filenames.
3329
        limbo_path = tt._limbo_name(bar_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
3330
        self.assertEqual(limbo_path, limbo_path)
4634.79.1 by Aaron Bentley
TransformPreview uses ascii-only filenames.
3331
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3332
0.13.13 by Aaron Bentley
Add direct test of serialization records
3333
class FakeSerializer(object):
3334
    """Serializer implementation that simply returns the input.
3335
3336
    The input is returned in the order used by pack.ContainerPushParser.
3337
    """
3338
    @staticmethod
3339
    def bytes_record(bytes, names):
3340
        return names, bytes
3341
3342
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3343
class TestSerializeTransform(tests.TestCaseWithTransport):
3344
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
3345
    _test_needs_features = [features.UnicodeFilenameFeature]
0.13.22 by Aaron Bentley
More unicodeness for Shelf tests
3346
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
3347
    def get_preview(self, tree=None):
3348
        if tree is None:
3349
            tree = self.make_branch_and_tree('tree')
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
3350
        tt = TransformPreview(tree)
3351
        self.addCleanup(tt.finalize)
3352
        return tt
3353
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3354
    def assertSerializesTo(self, expected, tt):
3355
        records = list(tt.serialize(FakeSerializer()))
3356
        self.assertEqual(expected, records)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3357
0.13.13 by Aaron Bentley
Add direct test of serialization records
3358
    @staticmethod
3359
    def default_attribs():
3360
        return {
6973.10.1 by Jelmer Vernooij
Fix some tests.
3361
            b'_id_number': 1,
3362
            b'_new_name': {},
3363
            b'_new_parent': {},
3364
            b'_new_executability': {},
3365
            b'_new_id': {},
3366
            b'_tree_path_ids': {b'': b'new-0'},
3367
            b'_removed_id': [],
3368
            b'_removed_contents': [],
3369
            b'_non_present_ids': {},
0.13.13 by Aaron Bentley
Add direct test of serialization records
3370
            }
3371
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3372
    def make_records(self, attribs, contents):
3373
        records = [
3374
            (((('attribs'),),), bencode.bencode(attribs))]
3375
        records.extend([(((n, k),), c) for n, k, c in contents])
3376
        return records
3377
0.13.13 by Aaron Bentley
Add direct test of serialization records
3378
    def creation_records(self):
3379
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3380
        attribs[b'_id_number'] = 3
3381
        attribs[b'_new_name'] = {
3382
            b'new-1': u'foo\u1234'.encode('utf-8'), b'new-2': b'qux'}
3383
        attribs[b'_new_id'] = {b'new-1': b'baz', b'new-2': b'quxx'}
3384
        attribs[b'_new_parent'] = {b'new-1': b'new-0', b'new-2': b'new-0'}
3385
        attribs[b'_new_executability'] = {b'new-1': 1}
0.13.13 by Aaron Bentley
Add direct test of serialization records
3386
        contents = [
6973.10.1 by Jelmer Vernooij
Fix some tests.
3387
            ('new-1', 'file', b'i 1\nbar\n'),
3388
            ('new-2', 'directory', b''),
0.13.13 by Aaron Bentley
Add direct test of serialization records
3389
            ]
3390
        return self.make_records(attribs, contents)
3391
3392
    def test_serialize_creation(self):
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
3393
        tt = self.get_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3394
        tt.new_file(u'foo\u1234', tt.root, [b'bar'], b'baz', True)
0.13.13 by Aaron Bentley
Add direct test of serialization records
3395
        tt.new_directory('qux', tt.root, 'quxx')
0.13.21 by Aaron Bentley
Use assertSerializesTo in more places
3396
        self.assertSerializesTo(self.creation_records(), tt)
0.13.13 by Aaron Bentley
Add direct test of serialization records
3397
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
3398
    def test_deserialize_creation(self):
3399
        tt = self.get_preview()
3400
        tt.deserialize(iter(self.creation_records()))
3401
        self.assertEqual(3, tt._id_number)
3402
        self.assertEqual({'new-1': u'foo\u1234',
3403
                          'new-2': 'qux'}, tt._new_name)
3404
        self.assertEqual({'new-1': 'baz', 'new-2': 'quxx'}, tt._new_id)
3405
        self.assertEqual({'new-1': tt.root, 'new-2': tt.root}, tt._new_parent)
3406
        self.assertEqual({'baz': 'new-1', 'quxx': 'new-2'}, tt._r_new_id)
3407
        self.assertEqual({'new-1': True}, tt._new_executability)
3408
        self.assertEqual({'new-1': 'file',
3409
                          'new-2': 'directory'}, tt._new_contents)
3410
        foo_limbo = open(tt._limbo_name('new-1'), 'rb')
3411
        try:
3412
            foo_content = foo_limbo.read()
3413
        finally:
3414
            foo_limbo.close()
3415
        self.assertEqual('bar', foo_content)
3416
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3417
    def symlink_creation_records(self):
3418
        attribs = self.default_attribs()
3419
        attribs['_id_number'] = 2
3420
        attribs['_new_name'] = {'new-1': u'foo\u1234'.encode('utf-8')}
3421
        attribs['_new_parent'] = {'new-1': 'new-0'}
3422
        contents = [('new-1', 'symlink', u'bar\u1234'.encode('utf-8'))]
3423
        return self.make_records(attribs, contents)
3424
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
3425
    def test_serialize_symlink_creation(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
3426
        self.requireFeature(features.SymlinkFeature)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
3427
        tt = self.get_preview()
0.13.16 by Aaron Bentley
Add unicode symlink targets to tests
3428
        tt.new_symlink(u'foo\u1234', tt.root, u'bar\u1234')
0.13.21 by Aaron Bentley
Use assertSerializesTo in more places
3429
        self.assertSerializesTo(self.symlink_creation_records(), tt)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
3430
3431
    def test_deserialize_symlink_creation(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
3432
        self.requireFeature(features.SymlinkFeature)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
3433
        tt = self.get_preview()
3434
        tt.deserialize(iter(self.symlink_creation_records()))
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
3435
        abspath = tt._limbo_name('new-1')
4241.14.17 by Vincent Ladeuil
Add more tests for unicode symlinks to test_transform.
3436
        foo_content = osutils.readlink(abspath)
0.13.22 by Aaron Bentley
More unicodeness for Shelf tests
3437
        self.assertEqual(u'bar\u1234', foo_content)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3438
0.13.19 by Aaron Bentley
Clean up serialization tests
3439
    def make_destruction_preview(self):
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3440
        tree = self.make_branch_and_tree('.')
3441
        self.build_tree([u'foo\u1234', 'bar'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
3442
        tree.add([u'foo\u1234', 'bar'], [b'foo-id', b'bar-id'])
0.13.19 by Aaron Bentley
Clean up serialization tests
3443
        return self.get_preview(tree)
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
3444
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3445
    def destruction_records(self):
3446
        attribs = self.default_attribs()
3447
        attribs['_id_number'] = 3
3448
        attribs['_removed_id'] = ['new-1']
3449
        attribs['_removed_contents'] = ['new-2']
3450
        attribs['_tree_path_ids'] = {
3451
            '': 'new-0',
3452
            u'foo\u1234'.encode('utf-8'): 'new-1',
3453
            'bar': 'new-2',
3454
            }
3455
        return self.make_records(attribs, [])
3456
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
3457
    def test_serialize_destruction(self):
0.13.19 by Aaron Bentley
Clean up serialization tests
3458
        tt = self.make_destruction_preview()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
3459
        foo_trans_id = tt.trans_id_tree_path(u'foo\u1234')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3460
        tt.unversion_file(foo_trans_id)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
3461
        bar_trans_id = tt.trans_id_tree_path('bar')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3462
        tt.delete_contents(bar_trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3463
        self.assertSerializesTo(self.destruction_records(), tt)
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
3464
3465
    def test_deserialize_destruction(self):
0.13.19 by Aaron Bentley
Clean up serialization tests
3466
        tt = self.make_destruction_preview()
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
3467
        tt.deserialize(iter(self.destruction_records()))
3468
        self.assertEqual({u'foo\u1234': 'new-1',
3469
                          'bar': 'new-2',
3470
                          '': tt.root}, tt._tree_path_ids)
3471
        self.assertEqual({'new-1': u'foo\u1234',
3472
                          'new-2': 'bar',
3473
                          tt.root: ''}, tt._tree_id_paths)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
3474
        self.assertEqual({'new-1'}, tt._removed_id)
3475
        self.assertEqual({'new-2'}, tt._removed_contents)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3476
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3477
    def missing_records(self):
3478
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3479
        attribs[b'_id_number'] = 2
3480
        attribs[b'_non_present_ids'] = {
3481
            b'boo': b'new-1',}
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3482
        return self.make_records(attribs, [])
3483
3484
    def test_serialize_missing(self):
3485
        tt = self.get_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3486
        boo_trans_id = tt.trans_id_file_id(b'boo')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3487
        self.assertSerializesTo(self.missing_records(), tt)
3488
3489
    def test_deserialize_missing(self):
3490
        tt = self.get_preview()
3491
        tt.deserialize(iter(self.missing_records()))
6973.10.1 by Jelmer Vernooij
Fix some tests.
3492
        self.assertEqual({b'boo': b'new-1'}, tt._non_present_ids)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3493
3494
    def make_modification_preview(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
3495
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
3496
        LINES_TWO = b'z\nbb\nx\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3497
        tree = self.make_branch_and_tree('tree')
3498
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
3499
        tree.add('file', b'file-id')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3500
        return self.get_preview(tree), LINES_TWO
3501
3502
    def modification_records(self):
3503
        attribs = self.default_attribs()
3504
        attribs['_id_number'] = 2
3505
        attribs['_tree_path_ids'] = {
3506
            'file': 'new-1',
3507
            '': 'new-0',}
3508
        attribs['_removed_contents'] = ['new-1']
3509
        contents = [('new-1', 'file',
3510
                     'i 1\nz\n\nc 0 1 1 1\ni 1\nx\n\nc 0 3 3 1\n')]
3511
        return self.make_records(attribs, contents)
3512
3513
    def test_serialize_modification(self):
3514
        tt, LINES = self.make_modification_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3515
        trans_id = tt.trans_id_file_id(b'file-id')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3516
        tt.delete_contents(trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3517
        tt.create_file(LINES, trans_id)
3518
        self.assertSerializesTo(self.modification_records(), tt)
3519
3520
    def test_deserialize_modification(self):
3521
        tt, LINES = self.make_modification_preview()
3522
        tt.deserialize(iter(self.modification_records()))
3523
        self.assertFileEqual(LINES, tt._limbo_name('new-1'))
3524
3525
    def make_kind_change_preview(self):
6973.10.1 by Jelmer Vernooij
Fix some tests.
3526
        LINES = b'a\nb\nc\nd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3527
        tree = self.make_branch_and_tree('tree')
3528
        self.build_tree(['tree/foo/'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
3529
        tree.add('foo', b'foo-id')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3530
        return self.get_preview(tree), LINES
3531
3532
    def kind_change_records(self):
3533
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3534
        attribs[b'_id_number'] = 2
3535
        attribs[b'_tree_path_ids'] = {
3536
            b'foo': b'new-1',
3537
            b'': b'new-0',}
3538
        attribs[b'_removed_contents'] = [b'new-1']
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3539
        contents = [('new-1', 'file',
6973.10.1 by Jelmer Vernooij
Fix some tests.
3540
                     b'i 4\na\nb\nc\nd\n\n')]
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3541
        return self.make_records(attribs, contents)
3542
3543
    def test_serialize_kind_change(self):
3544
        tt, LINES = self.make_kind_change_preview()
6855.4.1 by Jelmer Vernooij
Yet more bees.
3545
        trans_id = tt.trans_id_file_id(b'foo-id')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3546
        tt.delete_contents(trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3547
        tt.create_file(LINES, trans_id)
3548
        self.assertSerializesTo(self.kind_change_records(), tt)
3549
3550
    def test_deserialize_kind_change(self):
3551
        tt, LINES = self.make_kind_change_preview()
3552
        tt.deserialize(iter(self.kind_change_records()))
3553
        self.assertFileEqual(LINES, tt._limbo_name('new-1'))
3554
3555
    def make_add_contents_preview(self):
6973.10.1 by Jelmer Vernooij
Fix some tests.
3556
        LINES = b'a\nb\nc\nd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3557
        tree = self.make_branch_and_tree('tree')
3558
        self.build_tree(['tree/foo'])
3559
        tree.add('foo')
3560
        os.unlink('tree/foo')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3561
        return self.get_preview(tree), LINES
3562
3563
    def add_contents_records(self):
3564
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
3565
        attribs[b'_id_number'] = 2
3566
        attribs[b'_tree_path_ids'] = {
3567
            b'foo': b'new-1',
3568
            b'': b'new-0',}
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3569
        contents = [('new-1', 'file',
6973.10.1 by Jelmer Vernooij
Fix some tests.
3570
                     b'i 4\na\nb\nc\nd\n\n')]
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3571
        return self.make_records(attribs, contents)
3572
3573
    def test_serialize_add_contents(self):
3574
        tt, LINES = self.make_add_contents_preview()
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3575
        trans_id = tt.trans_id_tree_path('foo')
6973.10.1 by Jelmer Vernooij
Fix some tests.
3576
        tt.create_file([LINES], trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3577
        self.assertSerializesTo(self.add_contents_records(), tt)
3578
3579
    def test_deserialize_add_contents(self):
3580
        tt, LINES = self.make_add_contents_preview()
3581
        tt.deserialize(iter(self.add_contents_records()))
3582
        self.assertFileEqual(LINES, tt._limbo_name('new-1'))
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3583
3584
    def test_get_parents_lines(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
3585
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
3586
        LINES_TWO = b'z\nbb\nx\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3587
        tree = self.make_branch_and_tree('tree')
3588
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
3589
        tree.add('file', b'file-id')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3590
        tt = self.get_preview(tree)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3591
        trans_id = tt.trans_id_tree_path('file')
6973.10.1 by Jelmer Vernooij
Fix some tests.
3592
        self.assertEqual(([b'aa\n', b'bb\n', b'cc\n', b'dd\n'],),
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3593
            tt._get_parents_lines(trans_id))
3594
3595
    def test_get_parents_texts(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
3596
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
3597
        LINES_TWO = b'z\nbb\nx\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3598
        tree = self.make_branch_and_tree('tree')
3599
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
3600
        tree.add('file', b'file-id')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
3601
        tt = self.get_preview(tree)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
3602
        trans_id = tt.trans_id_tree_path('file')
3603
        self.assertEqual((LINES_ONE,),
3604
            tt._get_parents_texts(trans_id))
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
3605
3606
3607
class TestOrphan(tests.TestCaseWithTransport):
3608
3609
    def test_no_orphan_for_transform_preview(self):
3610
        tree = self.make_branch_and_tree('tree')
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
3611
        tt = transform.TransformPreview(tree)
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
3612
        self.addCleanup(tt.finalize)
3613
        self.assertRaises(NotImplementedError, tt.new_orphan, 'foo', 'bar')
3614
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
3615
    def _set_orphan_policy(self, wt, policy):
6883.13.1 by Jelmer Vernooij
Rename bzr.transform.orphan_policy -> transform.orphan_policy.
3616
        wt.branch.get_config_stack().set('transform.orphan_policy',
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
3617
                                               policy)
3618
3619
    def _prepare_orphan(self, wt):
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
3620
        self.build_tree(['dir/', 'dir/file', 'dir/foo'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
3621
        wt.add(['dir', 'dir/file'], [b'dir-id', b'file-id'])
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
3622
        wt.commit('add dir and file ignoring foo')
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
3623
        tt = transform.TreeTransform(wt)
3624
        self.addCleanup(tt.finalize)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
3625
        # dir and bar are deleted
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
3626
        dir_tid = tt.trans_id_tree_path('dir')
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
3627
        file_tid = tt.trans_id_tree_path('dir/file')
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
3628
        orphan_tid = tt.trans_id_tree_path('dir/foo')
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
3629
        tt.delete_contents(file_tid)
3630
        tt.unversion_file(file_tid)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
3631
        tt.delete_contents(dir_tid)
3632
        tt.unversion_file(dir_tid)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
3633
        # There should be a conflict because dir still contain foo
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
3634
        raw_conflicts = tt.find_conflicts()
3635
        self.assertLength(1, raw_conflicts)
3636
        self.assertEqual(('missing parent', 'new-1'), raw_conflicts[0])
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
3637
        return tt, orphan_tid
3638
3639
    def test_new_orphan_created(self):
3640
        wt = self.make_branch_and_tree('.')
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
3641
        self._set_orphan_policy(wt, 'move')
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
3642
        tt, orphan_tid = self._prepare_orphan(wt)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
3643
        warnings = []
3644
        def warning(*args):
3645
            warnings.append(args[0] % args[1:])
3646
        self.overrideAttr(trace, 'warning', warning)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
3647
        remaining_conflicts = resolve_conflicts(tt)
6681.2.10 by Jelmer Vernooij
Fix failures.
3648
        self.assertEqual(['dir/foo has been orphaned in brz-orphans'],
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
3649
                          warnings)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
3650
        # Yeah for resolved conflicts !
3651
        self.assertLength(0, remaining_conflicts)
3652
        # We have a new orphan
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3653
        self.assertEqual('foo.~1~', tt.final_name(orphan_tid))
6681.2.10 by Jelmer Vernooij
Fix failures.
3654
        self.assertEqual('brz-orphans',
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
3655
                          tt.final_name(tt.final_parent(orphan_tid)))
3656
3657
    def test_never_orphan(self):
3658
        wt = self.make_branch_and_tree('.')
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
3659
        self._set_orphan_policy(wt, 'conflict')
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
3660
        tt, orphan_tid = self._prepare_orphan(wt)
3661
        remaining_conflicts = resolve_conflicts(tt)
3662
        self.assertLength(1, remaining_conflicts)
3663
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
3664
                         remaining_conflicts.pop())
3665
3666
    def test_orphan_error(self):
3667
        def bogus_orphan(tt, orphan_id, parent_id):
3668
            raise transform.OrphaningError(tt.final_name(orphan_id),
3669
                                           tt.final_name(parent_id))
3670
        transform.orphaning_registry.register('bogus', bogus_orphan,
3671
                                              'Raise an error when orphaning')
3672
        wt = self.make_branch_and_tree('.')
3673
        self._set_orphan_policy(wt, 'bogus')
3674
        tt, orphan_tid = self._prepare_orphan(wt)
3675
        remaining_conflicts = resolve_conflicts(tt)
3676
        self.assertLength(1, remaining_conflicts)
3677
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
3678
                         remaining_conflicts.pop())
5409.1.17 by Vincent Ladeuil
Ensures we fallback to the default policy if a bogus one is specified.
3679
3680
    def test_unknown_orphan_policy(self):
3681
        wt = self.make_branch_and_tree('.')
3682
        # Set a fictional policy nobody ever implemented
3683
        self._set_orphan_policy(wt, 'donttouchmypreciouuus')
3684
        tt, orphan_tid = self._prepare_orphan(wt)
3685
        warnings = []
3686
        def warning(*args):
3687
            warnings.append(args[0] % args[1:])
3688
        self.overrideAttr(trace, 'warning', warning)
3689
        remaining_conflicts = resolve_conflicts(tt)
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
3690
        # We fallback to the default policy which create a conflict
3691
        self.assertLength(1, remaining_conflicts)
3692
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
3693
                         remaining_conflicts.pop())
3694
        self.assertLength(1, warnings)
6449.6.7 by Jelmer Vernooij
Fix tests.
3695
        self.assertStartsWith(warnings[0], 'Value "donttouchmypreciouuus" ')
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
3696
3697
3698
class TestTransformHooks(tests.TestCaseWithTransport):
3699
3700
    def setUp(self):
3701
        super(TestTransformHooks, self).setUp()
3702
        self.wt = self.make_branch_and_tree('.')
3703
        os.chdir('..')
3704
3705
    def get_transform(self):
3706
        transform = TreeTransform(self.wt)
3707
        self.addCleanup(transform.finalize)
3708
        return transform, transform.root
3709
3710
    def test_pre_commit_hooks(self):
3711
        calls = []
3712
        def record_pre_transform(tree, tt):
3713
            calls.append((tree, tt))
3714
        MutableTree.hooks.install_named_hook('pre_transform',
3715
            record_pre_transform, "Pre transform")
3716
        transform, root = self.get_transform()
3717
        old_root_id = transform.tree_file_id(root)
3718
        transform.apply()
3719
        self.assertEqual(old_root_id, self.wt.get_root_id())
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3720
        self.assertEqual([(self.wt, transform)], calls)
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
3721
3722
    def test_post_commit_hooks(self):
3723
        calls = []
3724
        def record_post_transform(tree, tt):
3725
            calls.append((tree, tt))
3726
        MutableTree.hooks.install_named_hook('post_transform',
3727
            record_post_transform, "Post transform")
3728
        transform, root = self.get_transform()
3729
        old_root_id = transform.tree_file_id(root)
3730
        transform.apply()
3731
        self.assertEqual(old_root_id, self.wt.get_root_id())
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3732
        self.assertEqual([(self.wt, transform)], calls)
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
3733
3734
3735
class TestLinkTree(tests.TestCaseWithTransport):
3736
3737
    _test_needs_features = [HardlinkFeature]
3738
3739
    def setUp(self):
3740
        tests.TestCaseWithTransport.setUp(self)
3741
        self.parent_tree = self.make_branch_and_tree('parent')
3742
        self.parent_tree.lock_write()
3743
        self.addCleanup(self.parent_tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
3744
        self.build_tree_contents([('parent/foo', b'bar')])
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
3745
        self.parent_tree.add('foo')
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
3746
        self.parent_tree.commit('added foo')
6652.1.4 by Jelmer Vernooij
Fix test.
3747
        child_controldir = self.parent_tree.controldir.sprout('child')
3748
        self.child_tree = child_controldir.open_workingtree()
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
3749
3750
    def hardlinked(self):
3751
        parent_stat = os.lstat(self.parent_tree.abspath('foo'))
3752
        child_stat = os.lstat(self.child_tree.abspath('foo'))
3753
        return parent_stat.st_ino == child_stat.st_ino
3754
3755
    def test_link_fails_if_modified(self):
3756
        """If the file to be linked has modified text, don't link."""
6855.4.1 by Jelmer Vernooij
Yet more bees.
3757
        self.build_tree_contents([('child/foo', b'baz')])
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
3758
        transform.link_tree(self.child_tree, self.parent_tree)
3759
        self.assertFalse(self.hardlinked())
3760
3761
    def test_link_fails_if_execute_bit_changed(self):
3762
        """If the file to be linked has modified execute bit, don't link."""
3763
        tt = TreeTransform(self.child_tree)
3764
        try:
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
3765
            trans_id = tt.trans_id_tree_path('foo')
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
3766
            tt.set_executability(True, trans_id)
3767
            tt.apply()
3768
        finally:
3769
            tt.finalize()
3770
        transform.link_tree(self.child_tree, self.parent_tree)
3771
        self.assertFalse(self.hardlinked())
3772
3773
    def test_link_succeeds_if_unmodified(self):
3774
        """If the file to be linked is unmodified, link"""
3775
        transform.link_tree(self.child_tree, self.parent_tree)
3776
        self.assertTrue(self.hardlinked())