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