/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
7122.6.1 by Jelmer Vernooij
merge Parth's work into Breezy
19
from io import BytesIO, StringIO
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
20
import os
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
21
import sys
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
22
import time
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
23
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
24
from .. import (
2694.5.4 by Jelmer Vernooij
Move bzrlib.util.bencode to bzrlib._bencode_py.
25
    bencode,
2090.2.1 by Martin Pool
Fix some code which relies on assertions and breaks under python -O
26
    errors,
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
27
    filters,
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
    )
7265.5.1 by Jelmer Vernooij
Move generate_ids to breezy.bzr.
36
from ..bzr import (
37
    generate_ids,
38
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
39
from ..conflicts import (
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
40
    DeletingParent,
41
    DuplicateEntry,
42
    DuplicateID,
43
    MissingParent,
44
    NonDirectoryParent,
45
    ParentLoop,
46
    UnversionedParent,
47
)
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
48
from ..controldir import ControlDir
49
from ..diff import show_diff_trees
50
from ..errors import (
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
51
    DuplicateKey,
52
    ExistingLimbo,
53
    ExistingPendingDeletion,
54
    ImmortalPendingDeletion,
55
    LockError,
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 . import (
5050.44.1 by Vincent Ladeuil
One more fixed test related to bug #646133
64
    features,
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
65
    TestCaseInTempDir,
66
    TestSkipped,
67
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
68
from .features import (
3136.1.1 by Aaron Bentley
Add support for hardlinks to TreeTransform
69
    HardlinkFeature,
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
70
    SymlinkFeature,
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
71
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
72
from ..transform import (
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
73
    build_tree,
74
    create_from_tree,
75
    cook_conflicts,
76
    _FileMover,
77
    FinalPaths,
78
    resolve_conflicts,
79
    resolve_checkout,
80
    ROOT_PARENT,
7490.69.1 by Jelmer Vernooij
Move some more tests to breezy.bzr.
81
    ImmortalLimbo,
82
    MalformedTransform,
83
    NoFinalPath,
84
    ReusingTransform,
7490.77.4 by Jelmer Vernooij
Move some errors around.
85
    TransformRenameFailed,
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
86
)
0.13.13 by Aaron Bentley
Add direct test of serialization records
87
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
88
1534.7.93 by Aaron Bentley
Added text merge test
89
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).
90
1731.1.33 by Aaron Bentley
Revert no-special-root changes
91
    def __init__(self, dirname, root_id):
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
92
        self.name = dirname
1534.7.93 by Aaron Bentley
Added text merge test
93
        os.mkdir(dirname)
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
94
        self.wt = ControlDir.create_standalone_workingtree(dirname)
1731.1.33 by Aaron Bentley
Revert no-special-root changes
95
        self.wt.set_root_id(root_id)
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
96
        self.b = self.wt.branch
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
97
        self.tt = self.wt.transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
98
        self.root = self.tt.trans_id_tree_path('')
1534.7.93 by Aaron Bentley
Added text merge test
99
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
100
1534.7.95 by Aaron Bentley
Added more text merge tests
101
def conflict_text(tree, merge):
6973.10.1 by Jelmer Vernooij
Fix some tests.
102
    template = b'%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
103
    return template % (b'<' * 7, tree, b'=' * 7, merge, b'>' * 7)
1534.7.95 by Aaron Bentley
Added more text merge tests
104
1534.7.93 by Aaron Bentley
Added text merge test
105
106
class TestTransformMerge(TestCaseInTempDir):
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
107
1534.7.93 by Aaron Bentley
Added text merge test
108
    def test_text_merge(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
109
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
110
        base = TransformGroup("base", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
111
        base.tt.new_file('a', base.root, [b'a\nb\nc\nd\be\n'], b'a')
112
        base.tt.new_file('b', base.root, [b'b1'], b'b')
113
        base.tt.new_file('c', base.root, [b'c'], b'c')
114
        base.tt.new_file('d', base.root, [b'd'], b'd')
115
        base.tt.new_file('e', base.root, [b'e'], b'e')
116
        base.tt.new_file('f', base.root, [b'f'], b'f')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
117
        base.tt.new_directory('g', base.root, b'g')
118
        base.tt.new_directory('h', base.root, b'h')
1534.7.93 by Aaron Bentley
Added text merge test
119
        base.tt.apply()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
120
        other = TransformGroup("other", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
121
        other.tt.new_file('a', other.root, [b'y\nb\nc\nd\be\n'], b'a')
122
        other.tt.new_file('b', other.root, [b'b2'], b'b')
123
        other.tt.new_file('c', other.root, [b'c2'], b'c')
124
        other.tt.new_file('d', other.root, [b'd'], b'd')
125
        other.tt.new_file('e', other.root, [b'e2'], b'e')
126
        other.tt.new_file('f', other.root, [b'f'], b'f')
127
        other.tt.new_file('g', other.root, [b'g'], b'g')
128
        other.tt.new_file('h', other.root, [b'h\ni\nj\nk\n'], b'h')
129
        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
130
        other.tt.apply()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
131
        this = TransformGroup("this", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
132
        this.tt.new_file('a', this.root, [b'a\nb\nc\nd\bz\n'], b'a')
133
        this.tt.new_file('b', this.root, [b'b'], b'b')
134
        this.tt.new_file('c', this.root, [b'c'], b'c')
135
        this.tt.new_file('d', this.root, [b'd2'], b'd')
136
        this.tt.new_file('e', this.root, [b'e2'], b'e')
137
        this.tt.new_file('f', this.root, [b'f'], b'f')
138
        this.tt.new_file('g', this.root, [b'g'], b'g')
139
        this.tt.new_file('h', this.root, [b'1\n2\n3\n4\n'], b'h')
140
        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
141
        this.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
142
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
3008.1.6 by Michael Hudson
chop up Merge3Merger.__init__ into pieces
143
1534.7.95 by Aaron Bentley
Added more text merge tests
144
        # textual merge
6973.10.1 by Jelmer Vernooij
Fix some tests.
145
        with this.wt.get_file(this.wt.id2path(b'a')) as f:
146
            self.assertEqual(f.read(), b'y\nb\nc\nd\bz\n')
1534.7.95 by Aaron Bentley
Added more text merge tests
147
        # three-way text conflict
6973.10.1 by Jelmer Vernooij
Fix some tests.
148
        with this.wt.get_file(this.wt.id2path(b'b')) as f:
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
149
            self.assertEqual(f.read(), conflict_text(b'b', b'b2'))
1534.7.95 by Aaron Bentley
Added more text merge tests
150
        # OTHER wins
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
151
        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
152
        # THIS wins
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
153
        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
154
        # Ambigious clean merge
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
155
        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
156
        # No change
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
157
        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
158
        # Correct correct results when THIS == OTHER
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
159
        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
160
        # Text conflict when THIS & OTHER are text and BASE is dir
6855.4.1 by Jelmer Vernooij
Yet more bees.
161
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'h')).read(),
6973.10.1 by Jelmer Vernooij
Fix some tests.
162
                         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_*.
163
        self.assertEqual(this.wt.get_file('h.THIS').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
164
                         b'1\n2\n3\n4\n')
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
165
        self.assertEqual(this.wt.get_file('h.OTHER').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
166
                         b'h\ni\nj\nk\n')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
167
        self.assertEqual(file_kind(this.wt.abspath('h.BASE')), 'directory')
6855.4.1 by Jelmer Vernooij
Yet more bees.
168
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'i')).read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
169
                         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_*.
170
        self.assertEqual(this.wt.get_file('i.THIS').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
171
                         b'1\n2\n3\n4\n')
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
172
        self.assertEqual(this.wt.get_file('i.OTHER').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
173
                         b'h\ni\nj\nk\n')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
174
        self.assertEqual(os.path.exists(this.wt.abspath('i.BASE')), False)
7350.6.4 by Jelmer Vernooij
Drop file_id attribute from MergeHookParams and Tree.plan_file_merge.
175
        modified = ['a', 'b', 'c', 'h', 'i']
1534.7.192 by Aaron Bentley
Record hashes produced by merges
176
        merge_modified = this.wt.merge_modified()
177
        self.assertSubset(merge_modified, modified)
178
        self.assertEqual(len(merge_modified), len(modified))
7143.15.2 by Jelmer Vernooij
Run autopep8.
179
        with open(this.wt.abspath(this.wt.id2path(b'a')), 'wb') as f:
180
            f.write(b'booga')
1534.7.192 by Aaron Bentley
Record hashes produced by merges
181
        modified.pop(0)
182
        merge_modified = this.wt.merge_modified()
183
        self.assertSubset(merge_modified, modified)
184
        self.assertEqual(len(merge_modified), len(modified))
1558.12.10 by Aaron Bentley
Be robust when merge_hash file_id not in inventory
185
        this.wt.remove('b')
2796.1.4 by Aaron Bentley
Fix up various test cases
186
        this.wt.revert()
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
187
188
    def test_file_merge(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
189
        self.requireFeature(SymlinkFeature)
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
190
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
191
        base = TransformGroup("BASE", root_id)
192
        this = TransformGroup("THIS", root_id)
193
        other = TransformGroup("OTHER", root_id)
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
194
        for tg in this, base, other:
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
195
            tg.tt.new_directory('a', tg.root, b'a')
6973.10.1 by Jelmer Vernooij
Fix some tests.
196
            tg.tt.new_symlink('b', tg.root, 'b', b'b')
197
            tg.tt.new_file('c', tg.root, [b'c'], b'c')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
198
            tg.tt.new_symlink('d', tg.root, tg.name, b'd')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
199
        targets = ((base, 'base-e', 'base-f', None, None),
200
                   (this, 'other-e', 'this-f', 'other-g', 'this-h'),
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
201
                   (other, 'other-e', None, 'other-g', 'other-h'))
202
        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
203
            for link, target in (('e', e_target), ('f', f_target),
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
204
                                 ('g', g_target), ('h', h_target)):
205
                if target is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
206
                    tg.tt.new_symlink(link, tg.root, target,
207
                                      link.encode('ascii'))
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
208
209
        for tg in this, base, other:
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
210
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
211
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
212
        self.assertIs(os.path.isdir(this.wt.abspath('a')), True)
213
        self.assertIs(os.path.islink(this.wt.abspath('b')), True)
214
        self.assertIs(os.path.isfile(this.wt.abspath('c')), True)
215
        for suffix in ('THIS', 'BASE', 'OTHER'):
7143.15.2 by Jelmer Vernooij
Run autopep8.
216
            self.assertEqual(os.readlink(
217
                this.wt.abspath('d.' + suffix)), suffix)
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
218
        self.assertIs(os.path.lexists(this.wt.abspath('d')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
219
        self.assertEqual(this.wt.id2path(b'd'), 'd.OTHER')
220
        self.assertEqual(this.wt.id2path(b'f'), 'f.THIS')
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
221
        self.assertEqual(os.readlink(this.wt.abspath('e')), 'other-e')
222
        self.assertIs(os.path.lexists(this.wt.abspath('e.THIS')), False)
223
        self.assertIs(os.path.lexists(this.wt.abspath('e.OTHER')), False)
224
        self.assertIs(os.path.lexists(this.wt.abspath('e.BASE')), False)
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
225
        self.assertIs(os.path.lexists(this.wt.abspath('g')), True)
226
        self.assertIs(os.path.lexists(this.wt.abspath('g.BASE')), False)
227
        self.assertIs(os.path.lexists(this.wt.abspath('h')), False)
228
        self.assertIs(os.path.lexists(this.wt.abspath('h.BASE')), False)
229
        self.assertIs(os.path.lexists(this.wt.abspath('h.THIS')), True)
230
        self.assertIs(os.path.lexists(this.wt.abspath('h.OTHER')), True)
1534.7.105 by Aaron Bentley
Got merge with rename working
231
232
    def test_filename_merge(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
233
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
234
        base = TransformGroup("BASE", root_id)
235
        this = TransformGroup("THIS", root_id)
236
        other = TransformGroup("OTHER", root_id)
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
237
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, b'a')
238
                                   for t in [base, this, other]]
239
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, b'b')
240
                                   for t in [base, this, other]]
241
        base.tt.new_directory('c', base_a, b'c')
242
        this.tt.new_directory('c1', this_a, b'c')
243
        other.tt.new_directory('c', other_b, b'c')
244
245
        base.tt.new_directory('d', base_a, b'd')
246
        this.tt.new_directory('d1', this_b, b'd')
247
        other.tt.new_directory('d', other_a, b'd')
248
249
        base.tt.new_directory('e', base_a, b'e')
250
        this.tt.new_directory('e', this_a, b'e')
251
        other.tt.new_directory('e1', other_b, b'e')
252
253
        base.tt.new_directory('f', base_a, b'f')
254
        this.tt.new_directory('f1', this_b, b'f')
255
        other.tt.new_directory('f1', other_b, b'f')
1534.7.105 by Aaron Bentley
Got merge with rename working
256
257
        for tg in [this, base, other]:
258
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
259
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
6855.4.1 by Jelmer Vernooij
Yet more bees.
260
        self.assertEqual(this.wt.id2path(b'c'), pathjoin('b/c1'))
261
        self.assertEqual(this.wt.id2path(b'd'), pathjoin('b/d1'))
262
        self.assertEqual(this.wt.id2path(b'e'), pathjoin('b/e1'))
263
        self.assertEqual(this.wt.id2path(b'f'), pathjoin('b/f1'))
1534.7.105 by Aaron Bentley
Got merge with rename working
264
265
    def test_filename_merge_conflicts(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
266
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
267
        base = TransformGroup("BASE", root_id)
268
        this = TransformGroup("THIS", root_id)
269
        other = TransformGroup("OTHER", root_id)
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
270
        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
271
                                   for t in [base, this, other]]
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
272
        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
273
                                   for t in [base, this, other]]
274
6973.10.1 by Jelmer Vernooij
Fix some tests.
275
        base.tt.new_file('g', base_a, [b'g'], b'g')
276
        other.tt.new_file('g1', other_b, [b'g1'], b'g')
277
278
        base.tt.new_file('h', base_a, [b'h'], b'h')
279
        this.tt.new_file('h1', this_b, [b'h1'], b'h')
280
281
        base.tt.new_file('i', base.root, [b'i'], b'i')
282
        other.tt.new_directory('i1', this_b, b'i')
1534.7.105 by Aaron Bentley
Got merge with rename working
283
284
        for tg in [this, base, other]:
285
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
286
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.105 by Aaron Bentley
Got merge with rename working
287
6855.4.1 by Jelmer Vernooij
Yet more bees.
288
        self.assertEqual(this.wt.id2path(b'g'), pathjoin('b/g1.OTHER'))
1534.7.105 by Aaron Bentley
Got merge with rename working
289
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.BASE')), True)
290
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.THIS')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
291
        self.assertEqual(this.wt.id2path(b'h'), pathjoin('b/h1.THIS'))
1534.7.105 by Aaron Bentley
Got merge with rename working
292
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.BASE')), True)
293
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.OTHER')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
294
        self.assertEqual(this.wt.id2path(b'i'), pathjoin('b/i1.OTHER'))
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
295
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
296
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
297
class TestBuildTree(tests.TestCaseWithTransport):
298
3006.2.2 by Alexander Belchenko
tests added.
299
    def test_build_tree_with_symlinks(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
300
        self.requireFeature(SymlinkFeature)
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
301
        os.mkdir('a')
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
302
        a = ControlDir.create_standalone_workingtree('a')
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
303
        os.mkdir('a/foo')
7143.15.2 by Jelmer Vernooij
Run autopep8.
304
        with open('a/foo/bar', 'wb') as f:
305
            f.write(b'contents')
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
306
        os.symlink('a/foo/bar', 'a/foo/baz')
307
        a.add(['foo', 'foo/bar', 'foo/baz'])
308
        a.commit('initial commit')
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
309
        b = ControlDir.create_standalone_workingtree('b')
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
310
        basis = a.basis_tree()
311
        basis.lock_read()
312
        self.addCleanup(basis.unlock)
313
        build_tree(basis, b)
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
314
        self.assertIs(os.path.isdir('b/foo'), True)
6973.7.5 by Jelmer Vernooij
s/file/open.
315
        with open('b/foo/bar', 'rb') as f:
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
316
            self.assertEqual(f.read(), b"contents")
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
317
        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
318
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
319
    def test_build_with_references(self):
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
320
        tree = self.make_branch_and_tree('source',
7143.15.2 by Jelmer Vernooij
Run autopep8.
321
                                         format='development-subtree')
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
322
        subtree = self.make_branch_and_tree('source/subtree',
7143.15.2 by Jelmer Vernooij
Run autopep8.
323
                                            format='development-subtree')
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
324
        tree.add_reference(subtree)
325
        tree.commit('a revision')
326
        tree.branch.create_checkout('target')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
327
        self.assertPathExists('target')
328
        self.assertPathExists('target/subtree')
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
329
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
330
    def test_file_conflict_handling(self):
331
        """Ensure that when building trees, conflict handling is done"""
332
        source = self.make_branch_and_tree('source')
333
        target = self.make_branch_and_tree('target')
334
        self.build_tree(['source/file', 'target/file'])
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
335
        source.add('file', b'new-file')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
336
        source.commit('added file')
337
        build_tree(source.basis_tree(), target)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
338
        self.assertEqual(
339
            [DuplicateEntry('Moved existing file to', 'file.moved',
340
                            'file', None, 'new-file')],
341
            target.conflicts())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
342
        target2 = self.make_branch_and_tree('target2')
6973.7.5 by Jelmer Vernooij
s/file/open.
343
        with open('target2/file', 'wb') as target_file, \
344
                open('source/file', 'rb') as source_file:
345
            target_file.write(source_file.read())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
346
        build_tree(source.basis_tree(), target2)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
347
        self.assertEqual([], target2.conflicts())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
348
349
    def test_symlink_conflict_handling(self):
350
        """Ensure that when building trees, conflict handling is done"""
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
351
        self.requireFeature(SymlinkFeature)
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
352
        source = self.make_branch_and_tree('source')
353
        os.symlink('foo', 'source/symlink')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
354
        source.add('symlink', b'new-symlink')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
355
        source.commit('added file')
356
        target = self.make_branch_and_tree('target')
357
        os.symlink('bar', 'target/symlink')
358
        build_tree(source.basis_tree(), target)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
359
        self.assertEqual(
360
            [DuplicateEntry('Moved existing file to', 'symlink.moved',
361
                            'symlink', None, 'new-symlink')],
362
            target.conflicts())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
363
        target = self.make_branch_and_tree('target2')
364
        os.symlink('foo', 'target2/symlink')
365
        build_tree(source.basis_tree(), target)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
366
        self.assertEqual([], target.conflicts())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
367
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
368
    def test_directory_conflict_handling(self):
369
        """Ensure that when building trees, conflict handling is done"""
370
        source = self.make_branch_and_tree('source')
371
        target = self.make_branch_and_tree('target')
372
        self.build_tree(['source/dir1/', 'source/dir1/file', 'target/dir1/'])
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
373
        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
374
        source.commit('added file')
375
        build_tree(source.basis_tree(), target)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
376
        self.assertEqual([], target.conflicts())
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
377
        self.assertPathExists('target/dir1/file')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
378
379
        # Ensure contents are merged
380
        target = self.make_branch_and_tree('target2')
381
        self.build_tree(['target2/dir1/', 'target2/dir1/file2'])
382
        build_tree(source.basis_tree(), target)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
383
        self.assertEqual([], target.conflicts())
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
384
        self.assertPathExists('target2/dir1/file2')
385
        self.assertPathExists('target2/dir1/file')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
386
387
        # 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
388
        target = self.make_branch_and_tree('target3')
389
        self.make_branch('target3/dir1')
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
390
        self.build_tree(['target3/dir1/file2'])
391
        build_tree(source.basis_tree(), target)
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
392
        self.assertPathDoesNotExist('target3/dir1/file')
393
        self.assertPathExists('target3/dir1/file2')
394
        self.assertPathExists('target3/dir1.diverted/file')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
395
        self.assertEqual(
396
            [DuplicateEntry('Diverted to', 'dir1.diverted',
397
                            'dir1', 'new-dir1', None)],
398
            target.conflicts())
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
399
400
        target = self.make_branch_and_tree('target4')
401
        self.build_tree(['target4/dir1/'])
402
        self.make_branch('target4/dir1/file')
403
        build_tree(source.basis_tree(), target)
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
404
        self.assertPathExists('target4/dir1/file')
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
405
        self.assertEqual('directory', file_kind('target4/dir1/file'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
406
        self.assertPathExists('target4/dir1/file.diverted')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
407
        self.assertEqual(
408
            [DuplicateEntry('Diverted to', 'dir1/file.diverted',
409
                            'dir1/file', 'new-file', None)],
410
            target.conflicts())
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
411
412
    def test_mixed_conflict_handling(self):
413
        """Ensure that when building trees, conflict handling is done"""
414
        source = self.make_branch_and_tree('source')
415
        target = self.make_branch_and_tree('target')
416
        self.build_tree(['source/name', 'target/name/'])
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
417
        source.add('name', b'new-name')
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
418
        source.commit('added file')
419
        build_tree(source.basis_tree(), target)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
420
        self.assertEqual(
421
            [DuplicateEntry('Moved existing file to',
422
                            'name.moved', 'name', None, 'new-name')],
423
            target.conflicts())
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
424
425
    def test_raises_in_populated(self):
426
        source = self.make_branch_and_tree('source')
427
        self.build_tree(['source/name'])
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
428
        source.add('name')
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
429
        source.commit('added name')
430
        target = self.make_branch_and_tree('target')
431
        self.build_tree(['target/name'])
432
        target.add('name')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
433
        self.assertRaises(errors.WorkingTreeAlreadyPopulated,
7143.15.2 by Jelmer Vernooij
Run autopep8.
434
                          build_tree, source.basis_tree(), target)
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
435
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
436
    def test_build_tree_rename_count(self):
437
        source = self.make_branch_and_tree('source')
438
        self.build_tree(['source/file1', 'source/dir1/'])
439
        source.add(['file1', 'dir1'])
440
        source.commit('add1')
441
        target1 = self.make_branch_and_tree('target1')
2502.1.6 by Aaron Bentley
Update from review comments
442
        transform_result = build_tree(source.basis_tree(), target1)
443
        self.assertEqual(2, transform_result.rename_count)
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
444
445
        self.build_tree(['source/dir1/file2'])
446
        source.add(['dir1/file2'])
447
        source.commit('add3')
448
        target2 = self.make_branch_and_tree('target2')
2502.1.6 by Aaron Bentley
Update from review comments
449
        transform_result = build_tree(source.basis_tree(), target2)
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
450
        # children of non-root directories should not be renamed
2502.1.6 by Aaron Bentley
Update from review comments
451
        self.assertEqual(2, transform_result.rename_count)
2502.1.1 by Aaron Bentley
Ensure renames only root children are renamed when building trees
452
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
453
    def create_ab_tree(self):
454
        """Create a committed test tree with two files"""
455
        source = self.make_branch_and_tree('source')
6855.4.1 by Jelmer Vernooij
Yet more bees.
456
        self.build_tree_contents([('source/file1', b'A')])
457
        self.build_tree_contents([('source/file2', b'B')])
458
        source.add(['file1', 'file2'], [b'file1-id', b'file2-id'])
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
459
        source.commit('commit files')
460
        source.lock_write()
461
        self.addCleanup(source.unlock)
462
        return source
463
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
464
    def test_build_tree_accelerator_tree(self):
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
465
        source = self.create_ab_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
466
        self.build_tree_contents([('source/file2', b'C')])
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
467
        calls = []
468
        real_source_get_file = source.get_file
7143.15.2 by Jelmer Vernooij
Run autopep8.
469
7192.5.1 by Jelmer Vernooij
Remove more file ids.
470
        def get_file(path):
471
            calls.append(path)
472
            return real_source_get_file(path)
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
473
        source.get_file = get_file
474
        target = self.make_branch_and_tree('target')
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
475
        revision_tree = source.basis_tree()
476
        revision_tree.lock_read()
477
        self.addCleanup(revision_tree.unlock)
478
        build_tree(revision_tree, target, source)
7192.5.1 by Jelmer Vernooij
Remove more file ids.
479
        self.assertEqual(['file1'], calls)
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
480
        target.lock_read()
481
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
482
        self.assertEqual([], list(target.iter_changes(revision_tree)))
3123.5.1 by Aaron Bentley
Make build-tree able to use an additional 'accelerator' tree
483
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
484
    def test_build_tree_accelerator_tree_observes_sha1(self):
485
        source = self.create_ab_tree()
6973.10.1 by Jelmer Vernooij
Fix some tests.
486
        sha1 = osutils.sha_string(b'A')
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
487
        target = self.make_branch_and_tree('target')
488
        target.lock_write()
489
        self.addCleanup(target.unlock)
490
        state = target.current_dirstate()
491
        state._cutoff_time = time.time() + 60
492
        build_tree(source.basis_tree(), target, source)
6973.10.1 by Jelmer Vernooij
Fix some tests.
493
        entry = state._get_entry(0, path_utf8=b'file1')
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
494
        self.assertEqual(sha1, entry[1][0][1])
495
3123.5.4 by Aaron Bentley
Use an accelerator tree when branching, handle no-such-id correctly
496
    def test_build_tree_accelerator_tree_missing_file(self):
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
497
        source = self.create_ab_tree()
3123.5.4 by Aaron Bentley
Use an accelerator tree when branching, handle no-such-id correctly
498
        os.unlink('source/file1')
499
        source.remove(['file2'])
500
        target = self.make_branch_and_tree('target')
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
501
        revision_tree = source.basis_tree()
502
        revision_tree.lock_read()
503
        self.addCleanup(revision_tree.unlock)
504
        build_tree(revision_tree, target, source)
505
        target.lock_read()
506
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
507
        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
508
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
509
    def test_build_tree_accelerator_wrong_kind(self):
3146.4.8 by Aaron Bentley
Add missing symlink requirement
510
        self.requireFeature(SymlinkFeature)
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
511
        source = self.make_branch_and_tree('source')
6855.4.1 by Jelmer Vernooij
Yet more bees.
512
        self.build_tree_contents([('source/file1', b'')])
513
        self.build_tree_contents([('source/file2', b'')])
514
        source.add(['file1', 'file2'], [b'file1-id', b'file2-id'])
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
515
        source.commit('commit files')
516
        os.unlink('source/file2')
6855.4.1 by Jelmer Vernooij
Yet more bees.
517
        self.build_tree_contents([('source/file2/', b'C')])
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
518
        os.unlink('source/file1')
519
        os.symlink('file2', 'source/file1')
520
        calls = []
521
        real_source_get_file = source.get_file
7143.15.2 by Jelmer Vernooij
Run autopep8.
522
7192.5.1 by Jelmer Vernooij
Remove more file ids.
523
        def get_file(path):
524
            calls.append(path)
525
            return real_source_get_file(path)
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
526
        source.get_file = get_file
527
        target = self.make_branch_and_tree('target')
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
528
        revision_tree = source.basis_tree()
529
        revision_tree.lock_read()
530
        self.addCleanup(revision_tree.unlock)
531
        build_tree(revision_tree, target, source)
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
532
        self.assertEqual([], calls)
3123.5.19 by Aaron Bentley
Ensure content is exactly the same, when accelerator used
533
        target.lock_read()
534
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
535
        self.assertEqual([], list(target.iter_changes(revision_tree)))
3123.5.16 by Aaron Bentley
Test handling of conversion to non-file
536
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
537
    def test_build_tree_hardlink(self):
538
        self.requireFeature(HardlinkFeature)
539
        source = self.create_ab_tree()
540
        target = self.make_branch_and_tree('target')
541
        revision_tree = source.basis_tree()
542
        revision_tree.lock_read()
543
        self.addCleanup(revision_tree.unlock)
544
        build_tree(revision_tree, target, source, hardlink=True)
545
        target.lock_read()
546
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
547
        self.assertEqual([], list(target.iter_changes(revision_tree)))
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
548
        source_stat = os.stat('source/file1')
549
        target_stat = os.stat('target/file1')
550
        self.assertEqual(source_stat, target_stat)
551
552
        # Explicitly disallowing hardlinks should prevent them.
553
        target2 = self.make_branch_and_tree('target2')
554
        build_tree(revision_tree, target2, source, hardlink=False)
555
        target2.lock_read()
556
        self.addCleanup(target2.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
557
        self.assertEqual([], list(target2.iter_changes(revision_tree)))
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
558
        source_stat = os.stat('source/file1')
559
        target2_stat = os.stat('target2/file1')
560
        self.assertNotEqual(source_stat, target2_stat)
561
3137.1.1 by Aaron Bentley
Fix build_tree acceleration when file is moved in accelerator_tree
562
    def test_build_tree_accelerator_tree_moved(self):
563
        source = self.make_branch_and_tree('source')
6855.4.1 by Jelmer Vernooij
Yet more bees.
564
        self.build_tree_contents([('source/file1', b'A')])
565
        source.add(['file1'], [b'file1-id'])
3137.1.1 by Aaron Bentley
Fix build_tree acceleration when file is moved in accelerator_tree
566
        source.commit('commit files')
567
        source.rename_one('file1', 'file2')
568
        source.lock_read()
569
        self.addCleanup(source.unlock)
570
        target = self.make_branch_and_tree('target')
571
        revision_tree = source.basis_tree()
572
        revision_tree.lock_read()
573
        self.addCleanup(revision_tree.unlock)
574
        build_tree(revision_tree, target, source)
575
        target.lock_read()
576
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
577
        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
578
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
579
    def test_build_tree_hardlinks_preserve_execute(self):
580
        self.requireFeature(HardlinkFeature)
581
        source = self.create_ab_tree()
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
582
        tt = source.transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
583
        trans_id = tt.trans_id_tree_path('file1')
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
584
        tt.set_executability(True, trans_id)
585
        tt.apply()
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
586
        self.assertTrue(source.is_executable('file1'))
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
587
        target = self.make_branch_and_tree('target')
588
        revision_tree = source.basis_tree()
589
        revision_tree.lock_read()
590
        self.addCleanup(revision_tree.unlock)
591
        build_tree(revision_tree, target, source, hardlink=True)
592
        target.lock_read()
593
        self.addCleanup(target.unlock)
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
594
        self.assertEqual([], list(target.iter_changes(revision_tree)))
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
595
        self.assertTrue(source.is_executable('file1'))
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
596
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
597
    def install_rot13_content_filter(self, pattern):
4985.2.1 by Vincent Ladeuil
Deploy addAttrCleanup on the whole test suite.
598
        # We could use
599
        # self.addCleanup(filters._reset_registry, filters._reset_registry())
600
        # below, but that looks a bit... hard to read even if it's exactly
601
        # the same thing.
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
602
        original_registry = filters._reset_registry()
7143.15.2 by Jelmer Vernooij
Run autopep8.
603
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
604
        def restore_registry():
605
            filters._reset_registry(original_registry)
606
        self.addCleanup(restore_registry)
7143.15.2 by Jelmer Vernooij
Run autopep8.
607
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
608
        def rot13(chunks, context=None):
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
609
            return [
610
                codecs.encode(chunk.decode('ascii'), 'rot13').encode('ascii')
611
                for chunk in chunks]
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
612
        rot13filter = filters.ContentFilter(rot13, rot13)
6498.5.3 by Jelmer Vernooij
Fix tests.
613
        filters.filter_stacks_registry.register(
614
            'rot13', {'yes': [rot13filter]}.get)
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
615
        os.mkdir(self.test_home_dir + '/.bazaar')
616
        rules_filename = self.test_home_dir + '/.bazaar/rules'
6973.7.5 by Jelmer Vernooij
s/file/open.
617
        with open(rules_filename, 'wb') as f:
618
            f.write(b'[name %s]\nrot13=yes\n' % (pattern,))
7143.15.2 by Jelmer Vernooij
Run autopep8.
619
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
620
        def uninstall_rules():
621
            os.remove(rules_filename)
622
            rules.reset_rules()
623
        self.addCleanup(uninstall_rules)
624
        rules.reset_rules()
625
626
    def test_build_tree_content_filtered_files_are_not_hardlinked(self):
627
        """build_tree will not hardlink files that have content filtering rules
628
        applied to them (but will still hardlink other files from the same tree
629
        if it can).
630
        """
631
        self.requireFeature(HardlinkFeature)
6973.10.1 by Jelmer Vernooij
Fix some tests.
632
        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.
633
        source = self.create_ab_tree()
634
        target = self.make_branch_and_tree('target')
635
        revision_tree = source.basis_tree()
636
        revision_tree.lock_read()
637
        self.addCleanup(revision_tree.unlock)
638
        build_tree(revision_tree, target, source, hardlink=True)
639
        target.lock_read()
640
        self.addCleanup(target.unlock)
641
        self.assertEqual([], list(target.iter_changes(revision_tree)))
642
        source_stat = os.stat('source/file1')
643
        target_stat = os.stat('target/file1')
644
        self.assertNotEqual(source_stat, target_stat)
645
        source_stat = os.stat('source/file2')
646
        target_stat = os.stat('target/file2')
4826.1.8 by Andrew Bennetts
Tweaks suggested by John.
647
        self.assertEqualStat(source_stat, target_stat)
4826.1.5 by Andrew Bennetts
Add test that content filtered files are not hardlinked by build_tree.
648
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
649
    def test_case_insensitive_build_tree_inventory(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
650
        if (features.CaseInsensitiveFilesystemFeature.available()
7143.15.2 by Jelmer Vernooij
Run autopep8.
651
                or features.CaseInsCasePresFilenameFeature.available()):
4241.9.4 by Vincent Ladeuil
Fix test_case_insensitive_build_tree_inventory failure on OSX.
652
            raise tests.UnavailableFeature('Fully case sensitive filesystem')
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
653
        source = self.make_branch_and_tree('source')
654
        self.build_tree(['source/file', 'source/FILE'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
655
        source.add(['file', 'FILE'], [b'lower-id', b'upper-id'])
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
656
        source.commit('added files')
657
        # Don't try this at home, kids!
658
        # Force the tree to report that it is case insensitive
659
        target = self.make_branch_and_tree('target')
660
        target.case_sensitive = False
3453.2.6 by Aaron Bentley
Rename mutate_tree to delta_from_tree, add comment
661
        build_tree(source.basis_tree(), target, source, delta_from_tree=True)
6855.4.1 by Jelmer Vernooij
Yet more bees.
662
        self.assertEqual('file.moved', target.id2path(b'lower-id'))
663
        self.assertEqual('FILE', target.id2path(b'upper-id'))
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
664
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
665
    def test_build_tree_observes_sha(self):
666
        source = self.make_branch_and_tree('source')
667
        self.build_tree(['source/file1', 'source/dir/', 'source/dir/file2'])
668
        source.add(['file1', 'dir', 'dir/file2'],
6855.4.1 by Jelmer Vernooij
Yet more bees.
669
                   [b'file1-id', b'dir-id', b'file2-id'])
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
670
        source.commit('new files')
671
        target = self.make_branch_and_tree('target')
672
        target.lock_write()
673
        self.addCleanup(target.unlock)
674
        # We make use of the fact that DirState caches its cutoff time. So we
675
        # set the 'safe' time to one minute in the future.
676
        state = target.current_dirstate()
677
        state._cutoff_time = time.time() + 60
678
        build_tree(source.basis_tree(), target)
679
        entry1_sha = osutils.sha_file_by_name('source/file1')
680
        entry2_sha = osutils.sha_file_by_name('source/dir/file2')
681
        # entry[1] is the state information, entry[1][0] is the state of the
682
        # working tree, entry[1][0][1] is the sha value for the current working
683
        # tree
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
684
        entry1 = state._get_entry(0, path_utf8=b'file1')
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
685
        self.assertEqual(entry1_sha, entry1[1][0][1])
686
        # The 'size' field must also be set.
687
        self.assertEqual(25, entry1[1][0][2])
688
        entry1_state = entry1[1][0]
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
689
        entry2 = state._get_entry(0, path_utf8=b'dir/file2')
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
690
        self.assertEqual(entry2_sha, entry2[1][0][1])
691
        self.assertEqual(29, entry2[1][0][2])
692
        entry2_state = entry2[1][0]
693
        # Now, make sure that we don't have to re-read the content. The
694
        # packed_stat should match exactly.
7141.7.2 by Jelmer Vernooij
Fix more tests.
695
        self.assertEqual(entry1_sha, target.get_file_sha1('file1'))
696
        self.assertEqual(entry2_sha, target.get_file_sha1('dir/file2'))
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
697
        self.assertEqual(entry1_state, entry1[1][0])
698
        self.assertEqual(entry2_state, entry2[1][0])
699
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
700
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
701
class TestCommitTransform(tests.TestCaseWithTransport):
702
703
    def get_branch(self):
704
        tree = self.make_branch_and_tree('tree')
705
        tree.lock_write()
706
        self.addCleanup(tree.unlock)
707
        tree.commit('empty commit')
708
        return tree.branch
709
710
    def get_branch_and_transform(self):
711
        branch = self.get_branch()
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
712
        tt = branch.basis_tree().preview_transform()
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
713
        self.addCleanup(tt.finalize)
714
        return branch, tt
715
716
    def test_commit_wrong_basis(self):
717
        branch = self.get_branch()
718
        basis = branch.repository.revision_tree(
719
            _mod_revision.NULL_REVISION)
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
720
        tt = basis.preview_transform()
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
721
        self.addCleanup(tt.finalize)
4526.8.5 by Aaron Bentley
Updates from review.
722
        e = self.assertRaises(ValueError, tt.commit, branch, '')
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
723
        self.assertEqual('TreeTransform not based on branch basis: null:',
724
                         str(e))
725
726
    def test_empy_commit(self):
727
        branch, tt = self.get_branch_and_transform()
728
        rev = tt.commit(branch, 'my message')
729
        self.assertEqual(2, branch.revno())
730
        repo = branch.repository
731
        self.assertEqual('my message', repo.get_revision(rev).message)
732
733
    def test_merge_parents(self):
734
        branch, tt = self.get_branch_and_transform()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
735
        tt.commit(branch, 'my message', [b'rev1b', b'rev1c'])
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
736
        self.assertEqual([b'rev1b', b'rev1c'],
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
737
                         branch.basis_tree().get_parent_ids()[1:])
738
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
739
    def test_first_commit(self):
740
        branch = self.make_branch('branch')
741
        branch.lock_write()
742
        self.addCleanup(branch.unlock)
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
743
        tt = branch.basis_tree().preview_transform()
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
744
        self.addCleanup(tt.finalize)
6973.13.2 by Jelmer Vernooij
Fix some more tests.
745
        tt.new_directory('', ROOT_PARENT, b'TREE_ROOT')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
746
        tt.commit(branch, 'my message')
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
747
        self.assertEqual([], branch.basis_tree().get_parent_ids())
4526.8.5 by Aaron Bentley
Updates from review.
748
        self.assertNotEqual(_mod_revision.NULL_REVISION,
749
                            branch.last_revision())
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
750
4526.8.5 by Aaron Bentley
Updates from review.
751
    def test_first_commit_with_merge_parents(self):
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
752
        branch = self.make_branch('branch')
753
        branch.lock_write()
754
        self.addCleanup(branch.unlock)
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
755
        tt = branch.basis_tree().preview_transform()
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
756
        self.addCleanup(tt.finalize)
4526.8.5 by Aaron Bentley
Updates from review.
757
        e = self.assertRaises(ValueError, tt.commit, branch,
7143.15.2 by Jelmer Vernooij
Run autopep8.
758
                              'my message', [b'rev1b-id'])
4526.8.5 by Aaron Bentley
Updates from review.
759
        self.assertEqual('Cannot supply merge parents for first commit.',
760
                         str(e))
761
        self.assertEqual(_mod_revision.NULL_REVISION, branch.last_revision())
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
762
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
763
    def test_add_files(self):
764
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
765
        tt.new_file('file', tt.root, [b'contents'], b'file-id')
766
        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
767
        if SymlinkFeature.available():
6973.10.1 by Jelmer Vernooij
Fix some tests.
768
            tt.new_symlink('symlink', trans_id, 'target', b'symlink-id')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
769
        tt.commit(branch, 'message')
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
770
        tree = branch.basis_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
771
        self.assertEqual('file', tree.id2path(b'file-id'))
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
772
        self.assertEqual(b'contents', tree.get_file_text('file'))
6855.4.1 by Jelmer Vernooij
Yet more bees.
773
        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
774
        if SymlinkFeature.available():
6855.4.1 by Jelmer Vernooij
Yet more bees.
775
            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.
776
            self.assertEqual('target', tree.get_symlink_target('dir/symlink'))
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
777
4526.8.2 by Aaron Bentley
Proved strict commit handling.
778
    def test_add_unversioned(self):
779
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
780
        tt.new_file('file', tt.root, [b'contents'])
4526.8.2 by Aaron Bentley
Proved strict commit handling.
781
        self.assertRaises(errors.StrictCommitFailed, tt.commit, branch,
782
                          'message', strict=True)
783
784
    def test_modify_strict(self):
785
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
786
        tt.new_file('file', tt.root, [b'contents'], b'file-id')
4526.8.2 by Aaron Bentley
Proved strict commit handling.
787
        tt.commit(branch, 'message', strict=True)
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
788
        tt = branch.basis_tree().preview_transform()
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
789
        self.addCleanup(tt.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
790
        trans_id = tt.trans_id_file_id(b'file-id')
4526.8.2 by Aaron Bentley
Proved strict commit handling.
791
        tt.delete_contents(trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
792
        tt.create_file([b'contents'], trans_id)
4526.8.2 by Aaron Bentley
Proved strict commit handling.
793
        tt.commit(branch, 'message', strict=True)
794
4526.8.6 by Aaron Bentley
Check for malformed transforms before committing.
795
    def test_commit_malformed(self):
796
        """Committing a malformed transform should raise an exception.
797
798
        In this case, we are adding a file without adding its parent.
799
        """
800
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
801
        parent_id = tt.trans_id_file_id(b'parent-id')
802
        tt.new_file('file', parent_id, [b'contents'], b'file-id')
7490.69.1 by Jelmer Vernooij
Move some more tests to breezy.bzr.
803
        self.assertRaises(MalformedTransform, tt.commit, branch,
4526.8.6 by Aaron Bentley
Check for malformed transforms before committing.
804
                          'message')
805
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
806
    def test_commit_rich_revision_data(self):
807
        branch, tt = self.get_branch_and_transform()
5162.4.3 by Aaron Bentley
Fix failing test.
808
        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.
809
                           committer='me <me@example.com>',
6973.12.5 by Jelmer Vernooij
Add some u's for revision property names.
810
                           revprops={u'foo': 'bar'}, revision_id=b'revid-1',
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
811
                           authors=['Author1 <author1@example.com>',
7143.15.2 by Jelmer Vernooij
Run autopep8.
812
                                    'Author2 <author2@example.com>',
813
                                    ])
6973.10.1 by Jelmer Vernooij
Fix some tests.
814
        self.assertEqual(b'revid-1', rev_id)
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
815
        revision = branch.repository.get_revision(rev_id)
816
        self.assertEqual(1, revision.timestamp)
5162.4.3 by Aaron Bentley
Fix failing test.
817
        self.assertEqual(43201, revision.timezone)
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
818
        self.assertEqual('me <me@example.com>', revision.committer)
819
        self.assertEqual(['Author1 <author1@example.com>',
820
                          'Author2 <author2@example.com>'],
821
                         revision.get_apparent_authors())
822
        del revision.properties['authors']
823
        self.assertEqual({'foo': 'bar',
824
                          'branch-nick': 'tree'},
825
                         revision.properties)
826
827
    def test_no_explicit_revprops(self):
828
        branch, tt = self.get_branch_and_transform()
829
        rev_id = tt.commit(branch, 'message', authors=[
830
            'Author1 <author1@example.com>',
831
            'Author2 <author2@example.com>', ])
832
        revision = branch.repository.get_revision(rev_id)
833
        self.assertEqual(['Author1 <author1@example.com>',
834
                          'Author2 <author2@example.com>'],
835
                         revision.get_apparent_authors())
836
        self.assertEqual('tree', revision.properties['branch-nick'])
837
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
838
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
839
class TestFileMover(tests.TestCaseWithTransport):
840
841
    def test_file_mover(self):
842
        self.build_tree(['a/', 'a/b', 'c/', 'c/d'])
843
        mover = _FileMover()
844
        mover.rename('a', 'q')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
845
        self.assertPathExists('q')
846
        self.assertPathDoesNotExist('a')
847
        self.assertPathExists('q/b')
848
        self.assertPathExists('c')
849
        self.assertPathExists('c/d')
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
850
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
851
    def test_pre_delete_rollback(self):
852
        self.build_tree(['a/'])
853
        mover = _FileMover()
854
        mover.pre_delete('a', 'q')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
855
        self.assertPathExists('q')
856
        self.assertPathDoesNotExist('a')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
857
        mover.rollback()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
858
        self.assertPathDoesNotExist('q')
859
        self.assertPathExists('a')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
860
861
    def test_apply_deletions(self):
2733.2.12 by Aaron Bentley
Updates from review
862
        self.build_tree(['a/', 'b/'])
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
863
        mover = _FileMover()
864
        mover.pre_delete('a', 'q')
2733.2.12 by Aaron Bentley
Updates from review
865
        mover.pre_delete('b', 'r')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
866
        self.assertPathExists('q')
867
        self.assertPathExists('r')
868
        self.assertPathDoesNotExist('a')
869
        self.assertPathDoesNotExist('b')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
870
        mover.apply_deletions()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
871
        self.assertPathDoesNotExist('q')
872
        self.assertPathDoesNotExist('r')
873
        self.assertPathDoesNotExist('a')
874
        self.assertPathDoesNotExist('b')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
875
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
876
    def test_file_mover_rollback(self):
877
        self.build_tree(['a/', 'a/b', 'c/', 'c/d/', 'c/e/'])
878
        mover = _FileMover()
879
        mover.rename('c/d', 'c/f')
880
        mover.rename('c/e', 'c/d')
881
        try:
882
            mover.rename('a', 'c')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
883
        except errors.FileExists:
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
884
            mover.rollback()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
885
        self.assertPathExists('a')
886
        self.assertPathExists('c/d')
2733.2.3 by Aaron Bentley
Test tranform rollback
887
888
889
class Bogus(Exception):
890
    pass
891
892
893
class TestTransformRollback(tests.TestCaseWithTransport):
894
895
    class ExceptionFileMover(_FileMover):
896
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
897
        def __init__(self, bad_source=None, bad_target=None):
898
            _FileMover.__init__(self)
899
            self.bad_source = bad_source
900
            self.bad_target = bad_target
901
2733.2.3 by Aaron Bentley
Test tranform rollback
902
        def rename(self, source, target):
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
903
            if (self.bad_source is not None and
7143.15.2 by Jelmer Vernooij
Run autopep8.
904
                    source.endswith(self.bad_source)):
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
905
                raise Bogus
906
            elif (self.bad_target is not None and
7143.15.2 by Jelmer Vernooij
Run autopep8.
907
                  target.endswith(self.bad_target)):
2733.2.3 by Aaron Bentley
Test tranform rollback
908
                raise Bogus
909
            else:
910
                _FileMover.rename(self, source, target)
911
912
    def test_rollback_rename(self):
913
        tree = self.make_branch_and_tree('.')
914
        self.build_tree(['a/', 'a/b'])
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
915
        tt = tree.transform()
2733.2.3 by Aaron Bentley
Test tranform rollback
916
        self.addCleanup(tt.finalize)
917
        a_id = tt.trans_id_tree_path('a')
918
        tt.adjust_path('c', tt.root, a_id)
919
        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
920
        self.assertRaises(Bogus, tt.apply,
921
                          _mover=self.ExceptionFileMover(bad_source='a'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
922
        self.assertPathExists('a')
923
        self.assertPathExists('a/b')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
924
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
925
        self.assertPathExists('c')
926
        self.assertPathExists('c/d')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
927
928
    def test_rollback_rename_into_place(self):
929
        tree = self.make_branch_and_tree('.')
930
        self.build_tree(['a/', 'a/b'])
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
931
        tt = tree.transform()
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
932
        self.addCleanup(tt.finalize)
933
        a_id = tt.trans_id_tree_path('a')
934
        tt.adjust_path('c', tt.root, a_id)
935
        tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
936
        self.assertRaises(Bogus, tt.apply,
937
                          _mover=self.ExceptionFileMover(bad_target='c/d'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
938
        self.assertPathExists('a')
939
        self.assertPathExists('a/b')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
940
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
941
        self.assertPathExists('c')
942
        self.assertPathExists('c/d')
2733.2.6 by Aaron Bentley
Make TreeTransform commits rollbackable
943
944
    def test_rollback_deletion(self):
945
        tree = self.make_branch_and_tree('.')
946
        self.build_tree(['a/', 'a/b'])
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
947
        tt = tree.transform()
2733.2.6 by Aaron Bentley
Make TreeTransform commits rollbackable
948
        self.addCleanup(tt.finalize)
949
        a_id = tt.trans_id_tree_path('a')
950
        tt.delete_contents(a_id)
951
        tt.adjust_path('d', tt.root, tt.trans_id_tree_path('a/b'))
952
        self.assertRaises(Bogus, tt.apply,
953
                          _mover=self.ExceptionFileMover(bad_target='d'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
954
        self.assertPathExists('a')
955
        self.assertPathExists('a/b')
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
956
957
5876.3.3 by Martin
Use better test class name
958
class TestFinalizeRobustness(tests.TestCaseWithTransport):
959
    """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
960
961
    def _override_globals_in_method(self, instance, method_name, globals):
962
        """Replace method on instance with one with updated globals"""
963
        import types
6619.3.24 by Jelmer Vernooij
Run 2to3 methodattrs fixer.
964
        func = getattr(instance, method_name).__func__
6619.3.16 by Jelmer Vernooij
Run 2to3 funcattrs fixer.
965
        new_globals = dict(func.__globals__)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
966
        new_globals.update(globals)
6619.3.16 by Jelmer Vernooij
Run 2to3 funcattrs fixer.
967
        new_func = types.FunctionType(func.__code__, new_globals,
7143.15.2 by Jelmer Vernooij
Run autopep8.
968
                                      func.__name__, func.__defaults__)
7479.2.1 by Jelmer Vernooij
Drop python2 support.
969
        setattr(instance, method_name,
970
                types.MethodType(new_func, instance))
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
971
        self.addCleanup(delattr, instance, method_name)
972
973
    @staticmethod
974
    def _fake_open_raises_before(name, mode):
975
        """Like open() but raises before doing anything"""
976
        raise RuntimeError
977
978
    @staticmethod
979
    def _fake_open_raises_after(name, mode):
980
        """Like open() but raises after creating file without returning"""
981
        open(name, mode).close()
982
        raise RuntimeError
983
984
    def create_transform_and_root_trans_id(self):
985
        """Setup a transform creating a file in limbo"""
986
        tree = self.make_branch_and_tree('.')
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
987
        tt = tree.transform()
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
988
        return tt, tt.create_path("a", tt.root)
989
990
    def create_transform_and_subdir_trans_id(self):
991
        """Setup a transform creating a directory containing a file in limbo"""
992
        tree = self.make_branch_and_tree('.')
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
993
        tt = tree.transform()
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
994
        d_trans_id = tt.create_path("d", tt.root)
995
        tt.create_directory(d_trans_id)
996
        f_trans_id = tt.create_path("a", d_trans_id)
997
        tt.adjust_path("a", d_trans_id, f_trans_id)
998
        return tt, f_trans_id
999
1000
    def test_root_create_file_open_raises_before_creation(self):
1001
        tt, trans_id = self.create_transform_and_root_trans_id()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1002
        self._override_globals_in_method(
1003
            tt, "create_file", {"open": self._fake_open_raises_before})
7143.15.2 by Jelmer Vernooij
Run autopep8.
1004
        self.assertRaises(RuntimeError, tt.create_file,
1005
                          [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
1006
        path = tt._limbo_name(trans_id)
1007
        self.assertPathDoesNotExist(path)
1008
        tt.finalize()
1009
        self.assertPathDoesNotExist(tt._limbodir)
1010
1011
    def test_root_create_file_open_raises_after_creation(self):
1012
        tt, trans_id = self.create_transform_and_root_trans_id()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1013
        self._override_globals_in_method(
1014
            tt, "create_file", {"open": self._fake_open_raises_after})
7143.15.2 by Jelmer Vernooij
Run autopep8.
1015
        self.assertRaises(RuntimeError, tt.create_file,
1016
                          [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
1017
        path = tt._limbo_name(trans_id)
1018
        self.assertPathExists(path)
5876.3.2 by Martin
Change test that expects ImmortalLimbo to want the sensible thing instead, and fail for now
1019
        tt.finalize()
1020
        self.assertPathDoesNotExist(path)
1021
        self.assertPathDoesNotExist(tt._limbodir)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
1022
1023
    def test_subdir_create_file_open_raises_before_creation(self):
1024
        tt, trans_id = self.create_transform_and_subdir_trans_id()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1025
        self._override_globals_in_method(
1026
            tt, "create_file", {"open": self._fake_open_raises_before})
7143.15.2 by Jelmer Vernooij
Run autopep8.
1027
        self.assertRaises(RuntimeError, tt.create_file,
1028
                          [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
1029
        path = tt._limbo_name(trans_id)
1030
        self.assertPathDoesNotExist(path)
1031
        tt.finalize()
1032
        self.assertPathDoesNotExist(tt._limbodir)
1033
1034
    def test_subdir_create_file_open_raises_after_creation(self):
1035
        tt, trans_id = self.create_transform_and_subdir_trans_id()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1036
        self._override_globals_in_method(
1037
            tt, "create_file", {"open": self._fake_open_raises_after})
7143.15.2 by Jelmer Vernooij
Run autopep8.
1038
        self.assertRaises(RuntimeError, tt.create_file,
1039
                          [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
1040
        path = tt._limbo_name(trans_id)
1041
        self.assertPathExists(path)
1042
        tt.finalize()
1043
        self.assertPathDoesNotExist(path)
1044
        self.assertPathDoesNotExist(tt._limbodir)
1045
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
1046
    def test_rename_in_limbo_rename_raises_after_rename(self):
1047
        tt, trans_id = self.create_transform_and_root_trans_id()
1048
        parent1 = tt.new_directory('parent1', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1049
        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
1050
        parent2 = tt.new_directory('parent2', tt.root)
1051
1052
        class FakeOSModule(object):
1053
            def rename(self, old, new):
1054
                os.rename(old, new)
1055
                raise RuntimeError
1056
        self._override_globals_in_method(tt, "_rename_in_limbo",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1057
                                         {"os": FakeOSModule()})
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
1058
        self.assertRaises(
1059
            RuntimeError, tt.adjust_path, "child1", parent2, child1)
1060
        path = osutils.pathjoin(tt._limbo_name(parent2), "child1")
1061
        self.assertPathExists(path)
1062
        tt.finalize()
1063
        self.assertPathDoesNotExist(path)
1064
        self.assertPathDoesNotExist(tt._limbodir)
1065
1066
    def test_rename_in_limbo_rename_raises_before_rename(self):
1067
        tt, trans_id = self.create_transform_and_root_trans_id()
1068
        parent1 = tt.new_directory('parent1', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
1069
        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
1070
        parent2 = tt.new_directory('parent2', tt.root)
1071
1072
        class FakeOSModule(object):
1073
            def rename(self, old, new):
1074
                raise RuntimeError
1075
        self._override_globals_in_method(tt, "_rename_in_limbo",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1076
                                         {"os": FakeOSModule()})
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
1077
        self.assertRaises(
1078
            RuntimeError, tt.adjust_path, "child1", parent2, child1)
1079
        path = osutils.pathjoin(tt._limbo_name(parent1), "child1")
1080
        self.assertPathExists(path)
1081
        tt.finalize()
1082
        self.assertPathDoesNotExist(path)
1083
        self.assertPathDoesNotExist(tt._limbodir)
1084
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
1085
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
1086
class TestTransformMissingParent(tests.TestCaseWithTransport):
1087
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
1088
    def make_tt_with_versioned_dir(self):
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
1089
        wt = self.make_branch_and_tree('.')
7143.15.2 by Jelmer Vernooij
Run autopep8.
1090
        self.build_tree(['dir/', ])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1091
        wt.add(['dir'], [b'dir-id'])
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
1092
        wt.commit('Create dir')
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
1093
        tt = wt.transform()
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
1094
        self.addCleanup(tt.finalize)
1095
        return wt, tt
1096
1097
    def test_resolve_create_parent_for_versioned_file(self):
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
1098
        wt, tt = self.make_tt_with_versioned_dir()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1099
        dir_tid = tt.trans_id_tree_path('dir')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1100
        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.
1101
        tt.delete_contents(dir_tid)
1102
        tt.unversion_file(dir_tid)
1103
        conflicts = resolve_conflicts(tt)
1104
        # one conflict for the missing directory, one for the unversioned
1105
        # parent
1106
        self.assertLength(2, conflicts)
1107
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
1108
    def test_non_versioned_file_create_conflict(self):
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
1109
        wt, tt = self.make_tt_with_versioned_dir()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1110
        dir_tid = tt.trans_id_tree_path('dir')
6973.10.1 by Jelmer Vernooij
Fix some tests.
1111
        tt.new_file('file', dir_tid, [b'Contents'])
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
1112
        tt.delete_contents(dir_tid)
1113
        tt.unversion_file(dir_tid)
1114
        conflicts = resolve_conflicts(tt)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1115
        # 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.
1116
        self.assertLength(1, conflicts)
1117
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
1118
                         conflicts.pop())
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
1119
1120
0.13.13 by Aaron Bentley
Add direct test of serialization records
1121
class FakeSerializer(object):
1122
    """Serializer implementation that simply returns the input.
1123
1124
    The input is returned in the order used by pack.ContainerPushParser.
1125
    """
1126
    @staticmethod
1127
    def bytes_record(bytes, names):
1128
        return names, bytes
1129
1130
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1131
class TestSerializeTransform(tests.TestCaseWithTransport):
1132
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1133
    _test_needs_features = [features.UnicodeFilenameFeature]
0.13.22 by Aaron Bentley
More unicodeness for Shelf tests
1134
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
1135
    def get_preview(self, tree=None):
1136
        if tree is None:
1137
            tree = self.make_branch_and_tree('tree')
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1138
        tt = tree.preview_transform()
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
1139
        self.addCleanup(tt.finalize)
1140
        return tt
1141
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1142
    def assertSerializesTo(self, expected, tt):
1143
        records = list(tt.serialize(FakeSerializer()))
1144
        self.assertEqual(expected, records)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1145
0.13.13 by Aaron Bentley
Add direct test of serialization records
1146
    @staticmethod
1147
    def default_attribs():
1148
        return {
6973.10.1 by Jelmer Vernooij
Fix some tests.
1149
            b'_id_number': 1,
1150
            b'_new_name': {},
1151
            b'_new_parent': {},
1152
            b'_new_executability': {},
1153
            b'_new_id': {},
1154
            b'_tree_path_ids': {b'': b'new-0'},
1155
            b'_removed_id': [],
1156
            b'_removed_contents': [],
1157
            b'_non_present_ids': {},
0.13.13 by Aaron Bentley
Add direct test of serialization records
1158
            }
1159
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1160
    def make_records(self, attribs, contents):
1161
        records = [
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
1162
            ((((b'attribs'),),), bencode.bencode(attribs))]
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1163
        records.extend([(((n, k),), c) for n, k, c in contents])
1164
        return records
1165
0.13.13 by Aaron Bentley
Add direct test of serialization records
1166
    def creation_records(self):
1167
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1168
        attribs[b'_id_number'] = 3
1169
        attribs[b'_new_name'] = {
1170
            b'new-1': u'foo\u1234'.encode('utf-8'), b'new-2': b'qux'}
1171
        attribs[b'_new_id'] = {b'new-1': b'baz', b'new-2': b'quxx'}
1172
        attribs[b'_new_parent'] = {b'new-1': b'new-0', b'new-2': b'new-0'}
1173
        attribs[b'_new_executability'] = {b'new-1': 1}
0.13.13 by Aaron Bentley
Add direct test of serialization records
1174
        contents = [
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1175
            (b'new-1', b'file', b'i 1\nbar\n'),
1176
            (b'new-2', b'directory', b''),
0.13.13 by Aaron Bentley
Add direct test of serialization records
1177
            ]
1178
        return self.make_records(attribs, contents)
1179
1180
    def test_serialize_creation(self):
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
1181
        tt = self.get_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1182
        tt.new_file(u'foo\u1234', tt.root, [b'bar'], b'baz', True)
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1183
        tt.new_directory('qux', tt.root, b'quxx')
0.13.21 by Aaron Bentley
Use assertSerializesTo in more places
1184
        self.assertSerializesTo(self.creation_records(), tt)
0.13.13 by Aaron Bentley
Add direct test of serialization records
1185
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
1186
    def test_deserialize_creation(self):
1187
        tt = self.get_preview()
1188
        tt.deserialize(iter(self.creation_records()))
1189
        self.assertEqual(3, tt._id_number)
1190
        self.assertEqual({'new-1': u'foo\u1234',
1191
                          'new-2': 'qux'}, tt._new_name)
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1192
        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.
1193
        self.assertEqual({'new-1': tt.root, 'new-2': tt.root}, tt._new_parent)
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1194
        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.
1195
        self.assertEqual({'new-1': True}, tt._new_executability)
1196
        self.assertEqual({'new-1': 'file',
1197
                          'new-2': 'directory'}, tt._new_contents)
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
1198
        with open(tt._limbo_name('new-1'), 'rb') as foo_limbo:
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
1199
            foo_content = foo_limbo.read()
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1200
        self.assertEqual(b'bar', foo_content)
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
1201
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1202
    def symlink_creation_records(self):
1203
        attribs = self.default_attribs()
7045.4.9 by Jelmer Vernooij
Fix some transform tests.
1204
        attribs[b'_id_number'] = 2
1205
        attribs[b'_new_name'] = {b'new-1': u'foo\u1234'.encode('utf-8')}
1206
        attribs[b'_new_parent'] = {b'new-1': b'new-0'}
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
1207
        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
1208
        return self.make_records(attribs, contents)
1209
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
1210
    def test_serialize_symlink_creation(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1211
        self.requireFeature(features.SymlinkFeature)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
1212
        tt = self.get_preview()
0.13.16 by Aaron Bentley
Add unicode symlink targets to tests
1213
        tt.new_symlink(u'foo\u1234', tt.root, u'bar\u1234')
0.13.21 by Aaron Bentley
Use assertSerializesTo in more places
1214
        self.assertSerializesTo(self.symlink_creation_records(), tt)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
1215
1216
    def test_deserialize_symlink_creation(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
1217
        self.requireFeature(features.SymlinkFeature)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
1218
        tt = self.get_preview()
1219
        tt.deserialize(iter(self.symlink_creation_records()))
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
1220
        abspath = tt._limbo_name('new-1')
4241.14.17 by Vincent Ladeuil
Add more tests for unicode symlinks to test_transform.
1221
        foo_content = osutils.readlink(abspath)
0.13.22 by Aaron Bentley
More unicodeness for Shelf tests
1222
        self.assertEqual(u'bar\u1234', foo_content)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1223
0.13.19 by Aaron Bentley
Clean up serialization tests
1224
    def make_destruction_preview(self):
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1225
        tree = self.make_branch_and_tree('.')
1226
        self.build_tree([u'foo\u1234', 'bar'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1227
        tree.add([u'foo\u1234', 'bar'], [b'foo-id', b'bar-id'])
0.13.19 by Aaron Bentley
Clean up serialization tests
1228
        return self.get_preview(tree)
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
1229
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1230
    def destruction_records(self):
1231
        attribs = self.default_attribs()
7045.4.9 by Jelmer Vernooij
Fix some transform tests.
1232
        attribs[b'_id_number'] = 3
1233
        attribs[b'_removed_id'] = [b'new-1']
1234
        attribs[b'_removed_contents'] = [b'new-2']
1235
        attribs[b'_tree_path_ids'] = {
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1236
            b'': b'new-0',
1237
            u'foo\u1234'.encode('utf-8'): b'new-1',
1238
            b'bar': b'new-2',
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1239
            }
1240
        return self.make_records(attribs, [])
1241
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
1242
    def test_serialize_destruction(self):
0.13.19 by Aaron Bentley
Clean up serialization tests
1243
        tt = self.make_destruction_preview()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1244
        foo_trans_id = tt.trans_id_tree_path(u'foo\u1234')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1245
        tt.unversion_file(foo_trans_id)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1246
        bar_trans_id = tt.trans_id_tree_path('bar')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1247
        tt.delete_contents(bar_trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1248
        self.assertSerializesTo(self.destruction_records(), tt)
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
1249
1250
    def test_deserialize_destruction(self):
0.13.19 by Aaron Bentley
Clean up serialization tests
1251
        tt = self.make_destruction_preview()
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
1252
        tt.deserialize(iter(self.destruction_records()))
1253
        self.assertEqual({u'foo\u1234': 'new-1',
1254
                          'bar': 'new-2',
1255
                          '': tt.root}, tt._tree_path_ids)
1256
        self.assertEqual({'new-1': u'foo\u1234',
1257
                          'new-2': 'bar',
1258
                          tt.root: ''}, tt._tree_id_paths)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
1259
        self.assertEqual({'new-1'}, tt._removed_id)
1260
        self.assertEqual({'new-2'}, tt._removed_contents)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1261
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1262
    def missing_records(self):
1263
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1264
        attribs[b'_id_number'] = 2
1265
        attribs[b'_non_present_ids'] = {
7143.15.2 by Jelmer Vernooij
Run autopep8.
1266
            b'boo': b'new-1', }
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1267
        return self.make_records(attribs, [])
1268
1269
    def test_serialize_missing(self):
1270
        tt = self.get_preview()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1271
        tt.trans_id_file_id(b'boo')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1272
        self.assertSerializesTo(self.missing_records(), tt)
1273
1274
    def test_deserialize_missing(self):
1275
        tt = self.get_preview()
1276
        tt.deserialize(iter(self.missing_records()))
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
1277
        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
1278
1279
    def make_modification_preview(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
1280
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
1281
        LINES_TWO = b'z\nbb\nx\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1282
        tree = self.make_branch_and_tree('tree')
1283
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1284
        tree.add('file', b'file-id')
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
1285
        return self.get_preview(tree), [LINES_TWO]
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1286
1287
    def modification_records(self):
1288
        attribs = self.default_attribs()
7045.4.9 by Jelmer Vernooij
Fix some transform tests.
1289
        attribs[b'_id_number'] = 2
1290
        attribs[b'_tree_path_ids'] = {
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1291
            b'file': b'new-1',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1292
            b'': b'new-0', }
7045.4.9 by Jelmer Vernooij
Fix some transform tests.
1293
        attribs[b'_removed_contents'] = [b'new-1']
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1294
        contents = [(b'new-1', b'file',
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
1295
                     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
1296
        return self.make_records(attribs, contents)
1297
1298
    def test_serialize_modification(self):
1299
        tt, LINES = self.make_modification_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1300
        trans_id = tt.trans_id_file_id(b'file-id')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1301
        tt.delete_contents(trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1302
        tt.create_file(LINES, trans_id)
1303
        self.assertSerializesTo(self.modification_records(), tt)
1304
1305
    def test_deserialize_modification(self):
1306
        tt, LINES = self.make_modification_preview()
1307
        tt.deserialize(iter(self.modification_records()))
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1308
        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
1309
1310
    def make_kind_change_preview(self):
6973.10.1 by Jelmer Vernooij
Fix some tests.
1311
        LINES = b'a\nb\nc\nd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1312
        tree = self.make_branch_and_tree('tree')
1313
        self.build_tree(['tree/foo/'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1314
        tree.add('foo', b'foo-id')
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1315
        return self.get_preview(tree), [LINES]
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1316
1317
    def kind_change_records(self):
1318
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1319
        attribs[b'_id_number'] = 2
1320
        attribs[b'_tree_path_ids'] = {
1321
            b'foo': b'new-1',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1322
            b'': b'new-0', }
6973.10.1 by Jelmer Vernooij
Fix some tests.
1323
        attribs[b'_removed_contents'] = [b'new-1']
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
1324
        contents = [(b'new-1', b'file',
6973.10.1 by Jelmer Vernooij
Fix some tests.
1325
                     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
1326
        return self.make_records(attribs, contents)
1327
1328
    def test_serialize_kind_change(self):
1329
        tt, LINES = self.make_kind_change_preview()
6855.4.1 by Jelmer Vernooij
Yet more bees.
1330
        trans_id = tt.trans_id_file_id(b'foo-id')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1331
        tt.delete_contents(trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1332
        tt.create_file(LINES, trans_id)
1333
        self.assertSerializesTo(self.kind_change_records(), tt)
1334
1335
    def test_deserialize_kind_change(self):
1336
        tt, LINES = self.make_kind_change_preview()
1337
        tt.deserialize(iter(self.kind_change_records()))
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
1338
        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
1339
1340
    def make_add_contents_preview(self):
6973.10.1 by Jelmer Vernooij
Fix some tests.
1341
        LINES = b'a\nb\nc\nd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1342
        tree = self.make_branch_and_tree('tree')
1343
        self.build_tree(['tree/foo'])
1344
        tree.add('foo')
1345
        os.unlink('tree/foo')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1346
        return self.get_preview(tree), LINES
1347
1348
    def add_contents_records(self):
1349
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
1350
        attribs[b'_id_number'] = 2
1351
        attribs[b'_tree_path_ids'] = {
1352
            b'foo': b'new-1',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1353
            b'': b'new-0', }
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
1354
        contents = [(b'new-1', b'file',
6973.10.1 by Jelmer Vernooij
Fix some tests.
1355
                     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
1356
        return self.make_records(attribs, contents)
1357
1358
    def test_serialize_add_contents(self):
1359
        tt, LINES = self.make_add_contents_preview()
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1360
        trans_id = tt.trans_id_tree_path('foo')
6973.10.1 by Jelmer Vernooij
Fix some tests.
1361
        tt.create_file([LINES], trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1362
        self.assertSerializesTo(self.add_contents_records(), tt)
1363
1364
    def test_deserialize_add_contents(self):
1365
        tt, LINES = self.make_add_contents_preview()
1366
        tt.deserialize(iter(self.add_contents_records()))
1367
        self.assertFileEqual(LINES, tt._limbo_name('new-1'))
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1368
1369
    def test_get_parents_lines(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
1370
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1371
        tree = self.make_branch_and_tree('tree')
1372
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1373
        tree.add('file', b'file-id')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1374
        tt = self.get_preview(tree)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1375
        trans_id = tt.trans_id_tree_path('file')
6973.10.1 by Jelmer Vernooij
Fix some tests.
1376
        self.assertEqual(([b'aa\n', b'bb\n', b'cc\n', b'dd\n'],),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1377
                         tt._get_parents_lines(trans_id))
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1378
1379
    def test_get_parents_texts(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
1380
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1381
        tree = self.make_branch_and_tree('tree')
1382
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1383
        tree.add('file', b'file-id')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
1384
        tt = self.get_preview(tree)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
1385
        trans_id = tt.trans_id_tree_path('file')
1386
        self.assertEqual((LINES_ONE,),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1387
                         tt._get_parents_texts(trans_id))
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
1388
1389
1390
class TestOrphan(tests.TestCaseWithTransport):
1391
1392
    def test_no_orphan_for_transform_preview(self):
1393
        tree = self.make_branch_and_tree('tree')
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1394
        tt = tree.preview_transform()
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
1395
        self.addCleanup(tt.finalize)
1396
        self.assertRaises(NotImplementedError, tt.new_orphan, 'foo', 'bar')
1397
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
1398
    def _set_orphan_policy(self, wt, policy):
6883.13.1 by Jelmer Vernooij
Rename bzr.transform.orphan_policy -> transform.orphan_policy.
1399
        wt.branch.get_config_stack().set('transform.orphan_policy',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1400
                                         policy)
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
1401
1402
    def _prepare_orphan(self, wt):
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1403
        self.build_tree(['dir/', 'dir/file', 'dir/foo'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
1404
        wt.add(['dir', 'dir/file'], [b'dir-id', b'file-id'])
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1405
        wt.commit('add dir and file ignoring foo')
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
1406
        tt = wt.transform()
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1407
        self.addCleanup(tt.finalize)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1408
        # dir and bar are deleted
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1409
        dir_tid = tt.trans_id_tree_path('dir')
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1410
        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.
1411
        orphan_tid = tt.trans_id_tree_path('dir/foo')
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1412
        tt.delete_contents(file_tid)
1413
        tt.unversion_file(file_tid)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1414
        tt.delete_contents(dir_tid)
1415
        tt.unversion_file(dir_tid)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1416
        # 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.
1417
        raw_conflicts = tt.find_conflicts()
1418
        self.assertLength(1, raw_conflicts)
1419
        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.
1420
        return tt, orphan_tid
1421
1422
    def test_new_orphan_created(self):
1423
        wt = self.make_branch_and_tree('.')
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
1424
        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.
1425
        tt, orphan_tid = self._prepare_orphan(wt)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1426
        warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1427
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1428
        def warning(*args):
1429
            warnings.append(args[0] % args[1:])
1430
        self.overrideAttr(trace, 'warning', warning)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1431
        remaining_conflicts = resolve_conflicts(tt)
6681.2.10 by Jelmer Vernooij
Fix failures.
1432
        self.assertEqual(['dir/foo has been orphaned in brz-orphans'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1433
                         warnings)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1434
        # Yeah for resolved conflicts !
1435
        self.assertLength(0, remaining_conflicts)
1436
        # We have a new orphan
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1437
        self.assertEqual('foo.~1~', tt.final_name(orphan_tid))
6681.2.10 by Jelmer Vernooij
Fix failures.
1438
        self.assertEqual('brz-orphans',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1439
                         tt.final_name(tt.final_parent(orphan_tid)))
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
1440
1441
    def test_never_orphan(self):
1442
        wt = self.make_branch_and_tree('.')
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
1443
        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.
1444
        tt, orphan_tid = self._prepare_orphan(wt)
1445
        remaining_conflicts = resolve_conflicts(tt)
1446
        self.assertLength(1, remaining_conflicts)
1447
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
1448
                         remaining_conflicts.pop())
1449
1450
    def test_orphan_error(self):
1451
        def bogus_orphan(tt, orphan_id, parent_id):
1452
            raise transform.OrphaningError(tt.final_name(orphan_id),
1453
                                           tt.final_name(parent_id))
1454
        transform.orphaning_registry.register('bogus', bogus_orphan,
1455
                                              'Raise an error when orphaning')
1456
        wt = self.make_branch_and_tree('.')
1457
        self._set_orphan_policy(wt, 'bogus')
1458
        tt, orphan_tid = self._prepare_orphan(wt)
1459
        remaining_conflicts = resolve_conflicts(tt)
1460
        self.assertLength(1, remaining_conflicts)
1461
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
1462
                         remaining_conflicts.pop())
5409.1.17 by Vincent Ladeuil
Ensures we fallback to the default policy if a bogus one is specified.
1463
1464
    def test_unknown_orphan_policy(self):
1465
        wt = self.make_branch_and_tree('.')
1466
        # Set a fictional policy nobody ever implemented
1467
        self._set_orphan_policy(wt, 'donttouchmypreciouuus')
1468
        tt, orphan_tid = self._prepare_orphan(wt)
1469
        warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1470
5409.1.17 by Vincent Ladeuil
Ensures we fallback to the default policy if a bogus one is specified.
1471
        def warning(*args):
1472
            warnings.append(args[0] % args[1:])
1473
        self.overrideAttr(trace, 'warning', warning)
1474
        remaining_conflicts = resolve_conflicts(tt)
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
1475
        # We fallback to the default policy which create a conflict
1476
        self.assertLength(1, remaining_conflicts)
1477
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
1478
                         remaining_conflicts.pop())
1479
        self.assertLength(1, warnings)
6449.6.7 by Jelmer Vernooij
Fix tests.
1480
        self.assertStartsWith(warnings[0], 'Value "donttouchmypreciouuus" ')
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1481
1482
1483
class TestTransformHooks(tests.TestCaseWithTransport):
1484
1485
    def setUp(self):
1486
        super(TestTransformHooks, self).setUp()
1487
        self.wt = self.make_branch_and_tree('.')
1488
        os.chdir('..')
1489
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1490
    def transform(self):
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
1491
        transform = self.wt.transform()
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1492
        self.addCleanup(transform.finalize)
1493
        return transform, transform.root
1494
1495
    def test_pre_commit_hooks(self):
1496
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1497
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1498
        def record_pre_transform(tree, tt):
1499
            calls.append((tree, tt))
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1500
        MutableTree.hooks.install_named_hook(
1501
            'pre_transform', record_pre_transform, "Pre transform")
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1502
        transform, root = self.transform()
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1503
        old_root_id = transform.tree_file_id(root)
1504
        transform.apply()
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
1505
        self.assertEqual(old_root_id, self.wt.path2id(''))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1506
        self.assertEqual([(self.wt, transform)], calls)
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1507
1508
    def test_post_commit_hooks(self):
1509
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1510
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1511
        def record_post_transform(tree, tt):
1512
            calls.append((tree, tt))
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1513
        MutableTree.hooks.install_named_hook(
1514
            'post_transform', record_post_transform, "Post transform")
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1515
        transform, root = self.transform()
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1516
        old_root_id = transform.tree_file_id(root)
1517
        transform.apply()
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
1518
        self.assertEqual(old_root_id, self.wt.path2id(''))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1519
        self.assertEqual([(self.wt, transform)], calls)
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1520
1521
1522
class TestLinkTree(tests.TestCaseWithTransport):
1523
1524
    _test_needs_features = [HardlinkFeature]
1525
1526
    def setUp(self):
1527
        tests.TestCaseWithTransport.setUp(self)
1528
        self.parent_tree = self.make_branch_and_tree('parent')
1529
        self.parent_tree.lock_write()
1530
        self.addCleanup(self.parent_tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1531
        self.build_tree_contents([('parent/foo', b'bar')])
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1532
        self.parent_tree.add('foo')
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1533
        self.parent_tree.commit('added foo')
6652.1.4 by Jelmer Vernooij
Fix test.
1534
        child_controldir = self.parent_tree.controldir.sprout('child')
1535
        self.child_tree = child_controldir.open_workingtree()
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1536
1537
    def hardlinked(self):
1538
        parent_stat = os.lstat(self.parent_tree.abspath('foo'))
1539
        child_stat = os.lstat(self.child_tree.abspath('foo'))
1540
        return parent_stat.st_ino == child_stat.st_ino
1541
1542
    def test_link_fails_if_modified(self):
1543
        """If the file to be linked has modified text, don't link."""
6855.4.1 by Jelmer Vernooij
Yet more bees.
1544
        self.build_tree_contents([('child/foo', b'baz')])
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1545
        transform.link_tree(self.child_tree, self.parent_tree)
1546
        self.assertFalse(self.hardlinked())
1547
1548
    def test_link_fails_if_execute_bit_changed(self):
1549
        """If the file to be linked has modified execute bit, don't link."""
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
1550
        tt = self.child_tree.transform()
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1551
        try:
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1552
            trans_id = tt.trans_id_tree_path('foo')
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1553
            tt.set_executability(True, trans_id)
1554
            tt.apply()
1555
        finally:
1556
            tt.finalize()
1557
        transform.link_tree(self.child_tree, self.parent_tree)
1558
        self.assertFalse(self.hardlinked())
1559
1560
    def test_link_succeeds_if_unmodified(self):
1561
        """If the file to be linked is unmodified, link"""
1562
        transform.link_tree(self.child_tree, self.parent_tree)
1563
        self.assertTrue(self.hardlinked())
7490.77.4 by Jelmer Vernooij
Move some errors around.
1564
1565
1566
class ErrorTests(tests.TestCase):
1567
1568
    def test_transform_rename_failed(self):
1569
        e = TransformRenameFailed(u"from", u"to", "readonly file", 2)
1570
        self.assertEqual(
1571
            u"Failed to rename from to to: readonly file",
1572
            str(e))