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