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