/brz/remove-bazaar

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