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