/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
    create_from_tree,
74
    _FileMover,
75
    FinalPaths,
76
    resolve_conflicts,
77
    ROOT_PARENT,
7490.69.1 by Jelmer Vernooij
Move some more tests to breezy.bzr.
78
    ImmortalLimbo,
79
    MalformedTransform,
80
    NoFinalPath,
81
    ReusingTransform,
7490.77.4 by Jelmer Vernooij
Move some errors around.
82
    TransformRenameFailed,
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
83
)
0.13.13 by Aaron Bentley
Add direct test of serialization records
84
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
85
1534.7.93 by Aaron Bentley
Added text merge test
86
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).
87
1731.1.33 by Aaron Bentley
Revert no-special-root changes
88
    def __init__(self, dirname, root_id):
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
89
        self.name = dirname
1534.7.93 by Aaron Bentley
Added text merge test
90
        os.mkdir(dirname)
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
91
        self.wt = ControlDir.create_standalone_workingtree(dirname)
1731.1.33 by Aaron Bentley
Revert no-special-root changes
92
        self.wt.set_root_id(root_id)
1558.1.3 by Aaron Bentley
Fixed deprecated op use in test suite
93
        self.b = self.wt.branch
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
94
        self.tt = self.wt.transform()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
95
        self.root = self.tt.trans_id_tree_path('')
1534.7.93 by Aaron Bentley
Added text merge test
96
1551.11.1 by Aaron Bentley
Initial work on converting TreeTransform to iter_changes format
97
1534.7.95 by Aaron Bentley
Added more text merge tests
98
def conflict_text(tree, merge):
6973.10.1 by Jelmer Vernooij
Fix some tests.
99
    template = b'%s TREE\n%s%s\n%s%s MERGE-SOURCE\n'
100
    return template % (b'<' * 7, tree, b'=' * 7, merge, b'>' * 7)
1534.7.95 by Aaron Bentley
Added more text merge tests
101
1534.7.93 by Aaron Bentley
Added text merge test
102
103
class TestTransformMerge(TestCaseInTempDir):
3199.1.5 by Vincent Ladeuil
Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.
104
1534.7.93 by Aaron Bentley
Added text merge test
105
    def test_text_merge(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
106
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
107
        base = TransformGroup("base", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
108
        base.tt.new_file('a', base.root, [b'a\nb\nc\nd\be\n'], b'a')
109
        base.tt.new_file('b', base.root, [b'b1'], b'b')
110
        base.tt.new_file('c', base.root, [b'c'], b'c')
111
        base.tt.new_file('d', base.root, [b'd'], b'd')
112
        base.tt.new_file('e', base.root, [b'e'], b'e')
113
        base.tt.new_file('f', base.root, [b'f'], b'f')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
114
        base.tt.new_directory('g', base.root, b'g')
115
        base.tt.new_directory('h', base.root, b'h')
1534.7.93 by Aaron Bentley
Added text merge test
116
        base.tt.apply()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
117
        other = TransformGroup("other", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
118
        other.tt.new_file('a', other.root, [b'y\nb\nc\nd\be\n'], b'a')
119
        other.tt.new_file('b', other.root, [b'b2'], b'b')
120
        other.tt.new_file('c', other.root, [b'c2'], b'c')
121
        other.tt.new_file('d', other.root, [b'd'], b'd')
122
        other.tt.new_file('e', other.root, [b'e2'], b'e')
123
        other.tt.new_file('f', other.root, [b'f'], b'f')
124
        other.tt.new_file('g', other.root, [b'g'], b'g')
125
        other.tt.new_file('h', other.root, [b'h\ni\nj\nk\n'], b'h')
126
        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
127
        other.tt.apply()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
128
        this = TransformGroup("this", root_id)
6973.10.1 by Jelmer Vernooij
Fix some tests.
129
        this.tt.new_file('a', this.root, [b'a\nb\nc\nd\bz\n'], b'a')
130
        this.tt.new_file('b', this.root, [b'b'], b'b')
131
        this.tt.new_file('c', this.root, [b'c'], b'c')
132
        this.tt.new_file('d', this.root, [b'd2'], b'd')
133
        this.tt.new_file('e', this.root, [b'e2'], b'e')
134
        this.tt.new_file('f', this.root, [b'f'], b'f')
135
        this.tt.new_file('g', this.root, [b'g'], b'g')
136
        this.tt.new_file('h', this.root, [b'1\n2\n3\n4\n'], b'h')
137
        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
138
        this.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
139
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
3008.1.6 by Michael Hudson
chop up Merge3Merger.__init__ into pieces
140
1534.7.95 by Aaron Bentley
Added more text merge tests
141
        # textual merge
6973.10.1 by Jelmer Vernooij
Fix some tests.
142
        with this.wt.get_file(this.wt.id2path(b'a')) as f:
143
            self.assertEqual(f.read(), b'y\nb\nc\nd\bz\n')
1534.7.95 by Aaron Bentley
Added more text merge tests
144
        # three-way text conflict
6973.10.1 by Jelmer Vernooij
Fix some tests.
145
        with this.wt.get_file(this.wt.id2path(b'b')) as f:
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
146
            self.assertEqual(f.read(), conflict_text(b'b', b'b2'))
1534.7.95 by Aaron Bentley
Added more text merge tests
147
        # OTHER wins
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
148
        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
149
        # THIS wins
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
150
        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
151
        # Ambigious clean merge
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
152
        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
153
        # No change
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
154
        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
155
        # Correct correct results when THIS == OTHER
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
156
        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
157
        # Text conflict when THIS & OTHER are text and BASE is dir
6855.4.1 by Jelmer Vernooij
Yet more bees.
158
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'h')).read(),
6973.10.1 by Jelmer Vernooij
Fix some tests.
159
                         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_*.
160
        self.assertEqual(this.wt.get_file('h.THIS').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
161
                         b'1\n2\n3\n4\n')
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
162
        self.assertEqual(this.wt.get_file('h.OTHER').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
163
                         b'h\ni\nj\nk\n')
1534.7.97 by Aaron Bentley
Ensured foo.BASE is a directory if there's a conflict
164
        self.assertEqual(file_kind(this.wt.abspath('h.BASE')), 'directory')
6855.4.1 by Jelmer Vernooij
Yet more bees.
165
        self.assertEqual(this.wt.get_file(this.wt.id2path(b'i')).read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
166
                         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_*.
167
        self.assertEqual(this.wt.get_file('i.THIS').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
168
                         b'1\n2\n3\n4\n')
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
169
        self.assertEqual(this.wt.get_file('i.OTHER').read(),
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
170
                         b'h\ni\nj\nk\n')
1534.7.99 by Aaron Bentley
Handle non-existent BASE properly
171
        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.
172
        modified = ['a', 'b', 'c', 'h', 'i']
1534.7.192 by Aaron Bentley
Record hashes produced by merges
173
        merge_modified = this.wt.merge_modified()
174
        self.assertSubset(merge_modified, modified)
175
        self.assertEqual(len(merge_modified), len(modified))
7143.15.2 by Jelmer Vernooij
Run autopep8.
176
        with open(this.wt.abspath(this.wt.id2path(b'a')), 'wb') as f:
177
            f.write(b'booga')
1534.7.192 by Aaron Bentley
Record hashes produced by merges
178
        modified.pop(0)
179
        merge_modified = this.wt.merge_modified()
180
        self.assertSubset(merge_modified, modified)
181
        self.assertEqual(len(merge_modified), len(modified))
1558.12.10 by Aaron Bentley
Be robust when merge_hash file_id not in inventory
182
        this.wt.remove('b')
2796.1.4 by Aaron Bentley
Fix up various test cases
183
        this.wt.revert()
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
184
185
    def test_file_merge(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
186
        self.requireFeature(SymlinkFeature)
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
187
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
188
        base = TransformGroup("BASE", root_id)
189
        this = TransformGroup("THIS", root_id)
190
        other = TransformGroup("OTHER", root_id)
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
191
        for tg in this, base, other:
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
192
            tg.tt.new_directory('a', tg.root, b'a')
6973.10.1 by Jelmer Vernooij
Fix some tests.
193
            tg.tt.new_symlink('b', tg.root, 'b', b'b')
194
            tg.tt.new_file('c', tg.root, [b'c'], b'c')
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
195
            tg.tt.new_symlink('d', tg.root, tg.name, b'd')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
196
        targets = ((base, 'base-e', 'base-f', None, None),
197
                   (this, 'other-e', 'this-f', 'other-g', 'this-h'),
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
198
                   (other, 'other-e', None, 'other-g', 'other-h'))
199
        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
200
            for link, target in (('e', e_target), ('f', f_target),
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
201
                                 ('g', g_target), ('h', h_target)):
202
                if target is not None:
7143.15.2 by Jelmer Vernooij
Run autopep8.
203
                    tg.tt.new_symlink(link, tg.root, target,
204
                                      link.encode('ascii'))
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
205
206
        for tg in this, base, other:
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
207
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
208
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.101 by Aaron Bentley
Got conflicts on symlinks working properly
209
        self.assertIs(os.path.isdir(this.wt.abspath('a')), True)
210
        self.assertIs(os.path.islink(this.wt.abspath('b')), True)
211
        self.assertIs(os.path.isfile(this.wt.abspath('c')), True)
212
        for suffix in ('THIS', 'BASE', 'OTHER'):
7143.15.2 by Jelmer Vernooij
Run autopep8.
213
            self.assertEqual(os.readlink(
214
                this.wt.abspath('d.' + suffix)), suffix)
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
215
        self.assertIs(os.path.lexists(this.wt.abspath('d')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
216
        self.assertEqual(this.wt.id2path(b'd'), 'd.OTHER')
217
        self.assertEqual(this.wt.id2path(b'f'), 'f.THIS')
1534.7.102 by Aaron Bentley
Deleted old pre-conflict contents
218
        self.assertEqual(os.readlink(this.wt.abspath('e')), 'other-e')
219
        self.assertIs(os.path.lexists(this.wt.abspath('e.THIS')), False)
220
        self.assertIs(os.path.lexists(this.wt.abspath('e.OTHER')), False)
221
        self.assertIs(os.path.lexists(this.wt.abspath('e.BASE')), False)
1534.7.104 by Aaron Bentley
Fixed set_versioned, enhanced conflict testing
222
        self.assertIs(os.path.lexists(this.wt.abspath('g')), True)
223
        self.assertIs(os.path.lexists(this.wt.abspath('g.BASE')), False)
224
        self.assertIs(os.path.lexists(this.wt.abspath('h')), False)
225
        self.assertIs(os.path.lexists(this.wt.abspath('h.BASE')), False)
226
        self.assertIs(os.path.lexists(this.wt.abspath('h.THIS')), True)
227
        self.assertIs(os.path.lexists(this.wt.abspath('h.OTHER')), True)
1534.7.105 by Aaron Bentley
Got merge with rename working
228
229
    def test_filename_merge(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
230
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
231
        base = TransformGroup("BASE", root_id)
232
        this = TransformGroup("THIS", root_id)
233
        other = TransformGroup("OTHER", root_id)
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
234
        base_a, this_a, other_a = [t.tt.new_directory('a', t.root, b'a')
235
                                   for t in [base, this, other]]
236
        base_b, this_b, other_b = [t.tt.new_directory('b', t.root, b'b')
237
                                   for t in [base, this, other]]
238
        base.tt.new_directory('c', base_a, b'c')
239
        this.tt.new_directory('c1', this_a, b'c')
240
        other.tt.new_directory('c', other_b, b'c')
241
242
        base.tt.new_directory('d', base_a, b'd')
243
        this.tt.new_directory('d1', this_b, b'd')
244
        other.tt.new_directory('d', other_a, b'd')
245
246
        base.tt.new_directory('e', base_a, b'e')
247
        this.tt.new_directory('e', this_a, b'e')
248
        other.tt.new_directory('e1', other_b, b'e')
249
250
        base.tt.new_directory('f', base_a, b'f')
251
        this.tt.new_directory('f1', this_b, b'f')
252
        other.tt.new_directory('f1', other_b, b'f')
1534.7.105 by Aaron Bentley
Got merge with rename working
253
254
        for tg in [this, base, other]:
255
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
256
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
6855.4.1 by Jelmer Vernooij
Yet more bees.
257
        self.assertEqual(this.wt.id2path(b'c'), pathjoin('b/c1'))
258
        self.assertEqual(this.wt.id2path(b'd'), pathjoin('b/d1'))
259
        self.assertEqual(this.wt.id2path(b'e'), pathjoin('b/e1'))
260
        self.assertEqual(this.wt.id2path(b'f'), pathjoin('b/f1'))
1534.7.105 by Aaron Bentley
Got merge with rename working
261
262
    def test_filename_merge_conflicts(self):
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
263
        root_id = generate_ids.gen_root_id()
1731.1.33 by Aaron Bentley
Revert no-special-root changes
264
        base = TransformGroup("BASE", root_id)
265
        this = TransformGroup("THIS", root_id)
266
        other = TransformGroup("OTHER", root_id)
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
267
        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
268
                                   for t in [base, this, other]]
7029.4.2 by Jelmer Vernooij
Fix more merge tests.
269
        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
270
                                   for t in [base, this, other]]
271
6973.10.1 by Jelmer Vernooij
Fix some tests.
272
        base.tt.new_file('g', base_a, [b'g'], b'g')
273
        other.tt.new_file('g1', other_b, [b'g1'], b'g')
274
275
        base.tt.new_file('h', base_a, [b'h'], b'h')
276
        this.tt.new_file('h1', this_b, [b'h1'], b'h')
277
278
        base.tt.new_file('i', base.root, [b'i'], b'i')
279
        other.tt.new_directory('i1', this_b, b'i')
1534.7.105 by Aaron Bentley
Got merge with rename working
280
281
        for tg in [this, base, other]:
282
            tg.tt.apply()
3008.1.11 by Michael Hudson
restore the default behaviour of Merge3Merger.__init__().
283
        Merge3Merger(this.wt, this.wt, base.wt, other.wt)
1534.7.105 by Aaron Bentley
Got merge with rename working
284
6855.4.1 by Jelmer Vernooij
Yet more bees.
285
        self.assertEqual(this.wt.id2path(b'g'), pathjoin('b/g1.OTHER'))
1534.7.105 by Aaron Bentley
Got merge with rename working
286
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.BASE')), True)
287
        self.assertIs(os.path.lexists(this.wt.abspath('b/g1.THIS')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
288
        self.assertEqual(this.wt.id2path(b'h'), pathjoin('b/h1.THIS'))
1534.7.105 by Aaron Bentley
Got merge with rename working
289
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.BASE')), True)
290
        self.assertIs(os.path.lexists(this.wt.abspath('b/h1.OTHER')), False)
6855.4.1 by Jelmer Vernooij
Yet more bees.
291
        self.assertEqual(this.wt.id2path(b'i'), pathjoin('b/i1.OTHER'))
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
292
2027.1.1 by John Arbash Meinel
Fix bug #56549, and write a direct test that the right path is being statted
293
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
294
class TestCommitTransform(tests.TestCaseWithTransport):
295
296
    def get_branch(self):
297
        tree = self.make_branch_and_tree('tree')
298
        tree.lock_write()
299
        self.addCleanup(tree.unlock)
300
        tree.commit('empty commit')
301
        return tree.branch
302
303
    def get_branch_and_transform(self):
304
        branch = self.get_branch()
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
305
        tt = branch.basis_tree().preview_transform()
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
306
        self.addCleanup(tt.finalize)
307
        return branch, tt
308
309
    def test_commit_wrong_basis(self):
310
        branch = self.get_branch()
311
        basis = branch.repository.revision_tree(
312
            _mod_revision.NULL_REVISION)
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
313
        tt = basis.preview_transform()
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
314
        self.addCleanup(tt.finalize)
4526.8.5 by Aaron Bentley
Updates from review.
315
        e = self.assertRaises(ValueError, tt.commit, branch, '')
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
316
        self.assertEqual('TreeTransform not based on branch basis: null:',
317
                         str(e))
318
319
    def test_empy_commit(self):
320
        branch, tt = self.get_branch_and_transform()
321
        rev = tt.commit(branch, 'my message')
322
        self.assertEqual(2, branch.revno())
323
        repo = branch.repository
324
        self.assertEqual('my message', repo.get_revision(rev).message)
325
326
    def test_merge_parents(self):
327
        branch, tt = self.get_branch_and_transform()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
328
        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.
329
        self.assertEqual([b'rev1b', b'rev1c'],
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
330
                         branch.basis_tree().get_parent_ids()[1:])
331
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
332
    def test_first_commit(self):
333
        branch = self.make_branch('branch')
334
        branch.lock_write()
335
        self.addCleanup(branch.unlock)
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
336
        tt = branch.basis_tree().preview_transform()
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
337
        self.addCleanup(tt.finalize)
6973.13.2 by Jelmer Vernooij
Fix some more tests.
338
        tt.new_directory('', ROOT_PARENT, b'TREE_ROOT')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
339
        tt.commit(branch, 'my message')
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
340
        self.assertEqual([], branch.basis_tree().get_parent_ids())
4526.8.5 by Aaron Bentley
Updates from review.
341
        self.assertNotEqual(_mod_revision.NULL_REVISION,
342
                            branch.last_revision())
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
343
4526.8.5 by Aaron Bentley
Updates from review.
344
    def test_first_commit_with_merge_parents(self):
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
345
        branch = self.make_branch('branch')
346
        branch.lock_write()
347
        self.addCleanup(branch.unlock)
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
348
        tt = branch.basis_tree().preview_transform()
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
349
        self.addCleanup(tt.finalize)
4526.8.5 by Aaron Bentley
Updates from review.
350
        e = self.assertRaises(ValueError, tt.commit, branch,
7143.15.2 by Jelmer Vernooij
Run autopep8.
351
                              'my message', [b'rev1b-id'])
4526.8.5 by Aaron Bentley
Updates from review.
352
        self.assertEqual('Cannot supply merge parents for first commit.',
353
                         str(e))
354
        self.assertEqual(_mod_revision.NULL_REVISION, branch.last_revision())
4526.8.3 by Aaron Bentley
Clean up merge parent handling.
355
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
356
    def test_add_files(self):
357
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
358
        tt.new_file('file', tt.root, [b'contents'], b'file-id')
359
        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
360
        if SymlinkFeature.available():
6973.10.1 by Jelmer Vernooij
Fix some tests.
361
            tt.new_symlink('symlink', trans_id, 'target', b'symlink-id')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
362
        tt.commit(branch, 'message')
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
363
        tree = branch.basis_tree()
6855.4.1 by Jelmer Vernooij
Yet more bees.
364
        self.assertEqual('file', tree.id2path(b'file-id'))
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
365
        self.assertEqual(b'contents', tree.get_file_text('file'))
6855.4.1 by Jelmer Vernooij
Yet more bees.
366
        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
367
        if SymlinkFeature.available():
6855.4.1 by Jelmer Vernooij
Yet more bees.
368
            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.
369
            self.assertEqual('target', tree.get_symlink_target('dir/symlink'))
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
370
4526.8.2 by Aaron Bentley
Proved strict commit handling.
371
    def test_add_unversioned(self):
372
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
373
        tt.new_file('file', tt.root, [b'contents'])
4526.8.2 by Aaron Bentley
Proved strict commit handling.
374
        self.assertRaises(errors.StrictCommitFailed, tt.commit, branch,
375
                          'message', strict=True)
376
377
    def test_modify_strict(self):
378
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
379
        tt.new_file('file', tt.root, [b'contents'], b'file-id')
4526.8.2 by Aaron Bentley
Proved strict commit handling.
380
        tt.commit(branch, 'message', strict=True)
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
381
        tt = branch.basis_tree().preview_transform()
4659.2.4 by Vincent Ladeuil
Cleanup remaining bzr-limbo-XXXXXX leaks in /tmp during selftest.
382
        self.addCleanup(tt.finalize)
6973.10.1 by Jelmer Vernooij
Fix some tests.
383
        trans_id = tt.trans_id_file_id(b'file-id')
4526.8.2 by Aaron Bentley
Proved strict commit handling.
384
        tt.delete_contents(trans_id)
6973.5.10 by Jelmer Vernooij
Random bunch of python3 bee-improvements.
385
        tt.create_file([b'contents'], trans_id)
4526.8.2 by Aaron Bentley
Proved strict commit handling.
386
        tt.commit(branch, 'message', strict=True)
387
4526.8.6 by Aaron Bentley
Check for malformed transforms before committing.
388
    def test_commit_malformed(self):
389
        """Committing a malformed transform should raise an exception.
390
391
        In this case, we are adding a file without adding its parent.
392
        """
393
        branch, tt = self.get_branch_and_transform()
6973.10.1 by Jelmer Vernooij
Fix some tests.
394
        parent_id = tt.trans_id_file_id(b'parent-id')
395
        tt.new_file('file', parent_id, [b'contents'], b'file-id')
7490.69.1 by Jelmer Vernooij
Move some more tests to breezy.bzr.
396
        self.assertRaises(MalformedTransform, tt.commit, branch,
4526.8.6 by Aaron Bentley
Check for malformed transforms before committing.
397
                          'message')
398
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
399
    def test_commit_rich_revision_data(self):
400
        branch, tt = self.get_branch_and_transform()
5162.4.3 by Aaron Bentley
Fix failing test.
401
        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.
402
                           committer='me <me@example.com>',
6973.12.5 by Jelmer Vernooij
Add some u's for revision property names.
403
                           revprops={u'foo': 'bar'}, revision_id=b'revid-1',
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
404
                           authors=['Author1 <author1@example.com>',
7143.15.2 by Jelmer Vernooij
Run autopep8.
405
                                    'Author2 <author2@example.com>',
406
                                    ])
6973.10.1 by Jelmer Vernooij
Fix some tests.
407
        self.assertEqual(b'revid-1', rev_id)
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
408
        revision = branch.repository.get_revision(rev_id)
409
        self.assertEqual(1, revision.timestamp)
5162.4.3 by Aaron Bentley
Fix failing test.
410
        self.assertEqual(43201, revision.timezone)
5162.4.1 by Aaron Bentley
TreeTransform supports normal commit parameters and includes branch nick.
411
        self.assertEqual('me <me@example.com>', revision.committer)
412
        self.assertEqual(['Author1 <author1@example.com>',
413
                          'Author2 <author2@example.com>'],
414
                         revision.get_apparent_authors())
415
        del revision.properties['authors']
416
        self.assertEqual({'foo': 'bar',
417
                          'branch-nick': 'tree'},
418
                         revision.properties)
419
420
    def test_no_explicit_revprops(self):
421
        branch, tt = self.get_branch_and_transform()
422
        rev_id = tt.commit(branch, 'message', authors=[
423
            'Author1 <author1@example.com>',
424
            'Author2 <author2@example.com>', ])
425
        revision = branch.repository.get_revision(rev_id)
426
        self.assertEqual(['Author1 <author1@example.com>',
427
                          'Author2 <author2@example.com>'],
428
                         revision.get_apparent_authors())
429
        self.assertEqual('tree', revision.properties['branch-nick'])
430
4526.8.1 by Aaron Bentley
Support committing a TreeTransform to a branch.
431
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
432
class TestFileMover(tests.TestCaseWithTransport):
433
434
    def test_file_mover(self):
435
        self.build_tree(['a/', 'a/b', 'c/', 'c/d'])
436
        mover = _FileMover()
437
        mover.rename('a', 'q')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
438
        self.assertPathExists('q')
439
        self.assertPathDoesNotExist('a')
440
        self.assertPathExists('q/b')
441
        self.assertPathExists('c')
442
        self.assertPathExists('c/d')
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
443
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
444
    def test_pre_delete_rollback(self):
445
        self.build_tree(['a/'])
446
        mover = _FileMover()
447
        mover.pre_delete('a', 'q')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
448
        self.assertPathExists('q')
449
        self.assertPathDoesNotExist('a')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
450
        mover.rollback()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
451
        self.assertPathDoesNotExist('q')
452
        self.assertPathExists('a')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
453
454
    def test_apply_deletions(self):
2733.2.12 by Aaron Bentley
Updates from review
455
        self.build_tree(['a/', 'b/'])
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
456
        mover = _FileMover()
457
        mover.pre_delete('a', 'q')
2733.2.12 by Aaron Bentley
Updates from review
458
        mover.pre_delete('b', 'r')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
459
        self.assertPathExists('q')
460
        self.assertPathExists('r')
461
        self.assertPathDoesNotExist('a')
462
        self.assertPathDoesNotExist('b')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
463
        mover.apply_deletions()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
464
        self.assertPathDoesNotExist('q')
465
        self.assertPathDoesNotExist('r')
466
        self.assertPathDoesNotExist('a')
467
        self.assertPathDoesNotExist('b')
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
468
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
469
    def test_file_mover_rollback(self):
470
        self.build_tree(['a/', 'a/b', 'c/', 'c/d/', 'c/e/'])
471
        mover = _FileMover()
472
        mover.rename('c/d', 'c/f')
473
        mover.rename('c/e', 'c/d')
474
        try:
475
            mover.rename('a', 'c')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
476
        except errors.FileExists:
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
477
            mover.rollback()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
478
        self.assertPathExists('a')
479
        self.assertPathExists('c/d')
2733.2.3 by Aaron Bentley
Test tranform rollback
480
481
482
class Bogus(Exception):
483
    pass
484
485
486
class TestTransformRollback(tests.TestCaseWithTransport):
487
488
    class ExceptionFileMover(_FileMover):
489
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
490
        def __init__(self, bad_source=None, bad_target=None):
491
            _FileMover.__init__(self)
492
            self.bad_source = bad_source
493
            self.bad_target = bad_target
494
2733.2.3 by Aaron Bentley
Test tranform rollback
495
        def rename(self, source, target):
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
496
            if (self.bad_source is not None and
7143.15.2 by Jelmer Vernooij
Run autopep8.
497
                    source.endswith(self.bad_source)):
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
498
                raise Bogus
499
            elif (self.bad_target is not None and
7143.15.2 by Jelmer Vernooij
Run autopep8.
500
                  target.endswith(self.bad_target)):
2733.2.3 by Aaron Bentley
Test tranform rollback
501
                raise Bogus
502
            else:
503
                _FileMover.rename(self, source, target)
504
505
    def test_rollback_rename(self):
506
        tree = self.make_branch_and_tree('.')
507
        self.build_tree(['a/', 'a/b'])
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
508
        tt = tree.transform()
2733.2.3 by Aaron Bentley
Test tranform rollback
509
        self.addCleanup(tt.finalize)
510
        a_id = tt.trans_id_tree_path('a')
511
        tt.adjust_path('c', tt.root, a_id)
512
        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
513
        self.assertRaises(Bogus, tt.apply,
514
                          _mover=self.ExceptionFileMover(bad_source='a'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
515
        self.assertPathExists('a')
516
        self.assertPathExists('a/b')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
517
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
518
        self.assertPathExists('c')
519
        self.assertPathExists('c/d')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
520
521
    def test_rollback_rename_into_place(self):
522
        tree = self.make_branch_and_tree('.')
523
        self.build_tree(['a/', 'a/b'])
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
524
        tt = tree.transform()
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
525
        self.addCleanup(tt.finalize)
526
        a_id = tt.trans_id_tree_path('a')
527
        tt.adjust_path('c', tt.root, a_id)
528
        tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
529
        self.assertRaises(Bogus, tt.apply,
530
                          _mover=self.ExceptionFileMover(bad_target='c/d'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
531
        self.assertPathExists('a')
532
        self.assertPathExists('a/b')
2733.2.4 by Aaron Bentley
Test transform rollback when renaming into place
533
        tt.apply()
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
534
        self.assertPathExists('c')
535
        self.assertPathExists('c/d')
2733.2.6 by Aaron Bentley
Make TreeTransform commits rollbackable
536
537
    def test_rollback_deletion(self):
538
        tree = self.make_branch_and_tree('.')
539
        self.build_tree(['a/', 'a/b'])
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
540
        tt = tree.transform()
2733.2.6 by Aaron Bentley
Make TreeTransform commits rollbackable
541
        self.addCleanup(tt.finalize)
542
        a_id = tt.trans_id_tree_path('a')
543
        tt.delete_contents(a_id)
544
        tt.adjust_path('d', tt.root, tt.trans_id_tree_path('a/b'))
545
        self.assertRaises(Bogus, tt.apply,
546
                          _mover=self.ExceptionFileMover(bad_target='d'))
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
547
        self.assertPathExists('a')
548
        self.assertPathExists('a/b')
3008.1.1 by Aaron Bentley
Start work allowing previews of transforms
549
550
5876.3.3 by Martin
Use better test class name
551
class TestFinalizeRobustness(tests.TestCaseWithTransport):
552
    """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
553
554
    def _override_globals_in_method(self, instance, method_name, globals):
555
        """Replace method on instance with one with updated globals"""
556
        import types
6619.3.24 by Jelmer Vernooij
Run 2to3 methodattrs fixer.
557
        func = getattr(instance, method_name).__func__
6619.3.16 by Jelmer Vernooij
Run 2to3 funcattrs fixer.
558
        new_globals = dict(func.__globals__)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
559
        new_globals.update(globals)
6619.3.16 by Jelmer Vernooij
Run 2to3 funcattrs fixer.
560
        new_func = types.FunctionType(func.__code__, new_globals,
7143.15.2 by Jelmer Vernooij
Run autopep8.
561
                                      func.__name__, func.__defaults__)
7479.2.1 by Jelmer Vernooij
Drop python2 support.
562
        setattr(instance, method_name,
563
                types.MethodType(new_func, instance))
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
564
        self.addCleanup(delattr, instance, method_name)
565
566
    @staticmethod
567
    def _fake_open_raises_before(name, mode):
568
        """Like open() but raises before doing anything"""
569
        raise RuntimeError
570
571
    @staticmethod
572
    def _fake_open_raises_after(name, mode):
573
        """Like open() but raises after creating file without returning"""
574
        open(name, mode).close()
575
        raise RuntimeError
576
577
    def create_transform_and_root_trans_id(self):
578
        """Setup a transform creating a file in limbo"""
579
        tree = self.make_branch_and_tree('.')
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
580
        tt = tree.transform()
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
581
        return tt, tt.create_path("a", tt.root)
582
583
    def create_transform_and_subdir_trans_id(self):
584
        """Setup a transform creating a directory containing a file in limbo"""
585
        tree = self.make_branch_and_tree('.')
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
586
        tt = tree.transform()
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
587
        d_trans_id = tt.create_path("d", tt.root)
588
        tt.create_directory(d_trans_id)
589
        f_trans_id = tt.create_path("a", d_trans_id)
590
        tt.adjust_path("a", d_trans_id, f_trans_id)
591
        return tt, f_trans_id
592
593
    def test_root_create_file_open_raises_before_creation(self):
594
        tt, trans_id = self.create_transform_and_root_trans_id()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
595
        self._override_globals_in_method(
596
            tt, "create_file", {"open": self._fake_open_raises_before})
7143.15.2 by Jelmer Vernooij
Run autopep8.
597
        self.assertRaises(RuntimeError, tt.create_file,
598
                          [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
599
        path = tt._limbo_name(trans_id)
600
        self.assertPathDoesNotExist(path)
601
        tt.finalize()
602
        self.assertPathDoesNotExist(tt._limbodir)
603
604
    def test_root_create_file_open_raises_after_creation(self):
605
        tt, trans_id = self.create_transform_and_root_trans_id()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
606
        self._override_globals_in_method(
607
            tt, "create_file", {"open": self._fake_open_raises_after})
7143.15.2 by Jelmer Vernooij
Run autopep8.
608
        self.assertRaises(RuntimeError, tt.create_file,
609
                          [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
610
        path = tt._limbo_name(trans_id)
611
        self.assertPathExists(path)
5876.3.2 by Martin
Change test that expects ImmortalLimbo to want the sensible thing instead, and fail for now
612
        tt.finalize()
613
        self.assertPathDoesNotExist(path)
614
        self.assertPathDoesNotExist(tt._limbodir)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
615
616
    def test_subdir_create_file_open_raises_before_creation(self):
617
        tt, trans_id = self.create_transform_and_subdir_trans_id()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
618
        self._override_globals_in_method(
619
            tt, "create_file", {"open": self._fake_open_raises_before})
7143.15.2 by Jelmer Vernooij
Run autopep8.
620
        self.assertRaises(RuntimeError, tt.create_file,
621
                          [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
622
        path = tt._limbo_name(trans_id)
623
        self.assertPathDoesNotExist(path)
624
        tt.finalize()
625
        self.assertPathDoesNotExist(tt._limbodir)
626
627
    def test_subdir_create_file_open_raises_after_creation(self):
628
        tt, trans_id = self.create_transform_and_subdir_trans_id()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
629
        self._override_globals_in_method(
630
            tt, "create_file", {"open": self._fake_open_raises_after})
7143.15.2 by Jelmer Vernooij
Run autopep8.
631
        self.assertRaises(RuntimeError, tt.create_file,
632
                          [b"contents"], trans_id)
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
633
        path = tt._limbo_name(trans_id)
634
        self.assertPathExists(path)
635
        tt.finalize()
636
        self.assertPathDoesNotExist(path)
637
        self.assertPathDoesNotExist(tt._limbodir)
638
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
639
    def test_rename_in_limbo_rename_raises_after_rename(self):
640
        tt, trans_id = self.create_transform_and_root_trans_id()
641
        parent1 = tt.new_directory('parent1', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
642
        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
643
        parent2 = tt.new_directory('parent2', tt.root)
644
645
        class FakeOSModule(object):
646
            def rename(self, old, new):
647
                os.rename(old, new)
648
                raise RuntimeError
649
        self._override_globals_in_method(tt, "_rename_in_limbo",
7143.15.2 by Jelmer Vernooij
Run autopep8.
650
                                         {"os": FakeOSModule()})
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
651
        self.assertRaises(
652
            RuntimeError, tt.adjust_path, "child1", parent2, child1)
653
        path = osutils.pathjoin(tt._limbo_name(parent2), "child1")
654
        self.assertPathExists(path)
655
        tt.finalize()
656
        self.assertPathDoesNotExist(path)
657
        self.assertPathDoesNotExist(tt._limbodir)
658
659
    def test_rename_in_limbo_rename_raises_before_rename(self):
660
        tt, trans_id = self.create_transform_and_root_trans_id()
661
        parent1 = tt.new_directory('parent1', tt.root)
6973.10.1 by Jelmer Vernooij
Fix some tests.
662
        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
663
        parent2 = tt.new_directory('parent2', tt.root)
664
665
        class FakeOSModule(object):
666
            def rename(self, old, new):
667
                raise RuntimeError
668
        self._override_globals_in_method(tt, "_rename_in_limbo",
7143.15.2 by Jelmer Vernooij
Run autopep8.
669
                                         {"os": FakeOSModule()})
5876.4.4 by Andrew Bennetts
Fix edge cases in handling interrupts during _rename_in_limbo, with messy tests
670
        self.assertRaises(
671
            RuntimeError, tt.adjust_path, "child1", parent2, child1)
672
        path = osutils.pathjoin(tt._limbo_name(parent1), "child1")
673
        self.assertPathExists(path)
674
        tt.finalize()
675
        self.assertPathDoesNotExist(path)
676
        self.assertPathDoesNotExist(tt._limbodir)
677
5876.3.1 by Martin
Tests for DiskTreeTransform.finalize issues when create_file is interrupted
678
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
679
class TestTransformMissingParent(tests.TestCaseWithTransport):
680
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
681
    def make_tt_with_versioned_dir(self):
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
682
        wt = self.make_branch_and_tree('.')
7143.15.2 by Jelmer Vernooij
Run autopep8.
683
        self.build_tree(['dir/', ])
6855.4.1 by Jelmer Vernooij
Yet more bees.
684
        wt.add(['dir'], [b'dir-id'])
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
685
        wt.commit('Create dir')
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
686
        tt = wt.transform()
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
687
        self.addCleanup(tt.finalize)
688
        return wt, tt
689
690
    def test_resolve_create_parent_for_versioned_file(self):
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
691
        wt, tt = self.make_tt_with_versioned_dir()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
692
        dir_tid = tt.trans_id_tree_path('dir')
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
693
        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.
694
        tt.delete_contents(dir_tid)
695
        tt.unversion_file(dir_tid)
696
        conflicts = resolve_conflicts(tt)
697
        # one conflict for the missing directory, one for the unversioned
698
        # parent
699
        self.assertLength(2, conflicts)
700
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
701
    def test_non_versioned_file_create_conflict(self):
5409.7.4 by Vincent Ladeuil
Take jam's review comments into account.
702
        wt, tt = self.make_tt_with_versioned_dir()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
703
        dir_tid = tt.trans_id_tree_path('dir')
6973.10.1 by Jelmer Vernooij
Fix some tests.
704
        tt.new_file('file', dir_tid, [b'Contents'])
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
705
        tt.delete_contents(dir_tid)
706
        tt.unversion_file(dir_tid)
707
        conflicts = resolve_conflicts(tt)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
708
        # 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.
709
        self.assertLength(1, conflicts)
710
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
711
                         conflicts.pop())
5409.1.6 by Vincent Ladeuil
Add failing tests for bug #323111.
712
713
0.13.13 by Aaron Bentley
Add direct test of serialization records
714
class FakeSerializer(object):
715
    """Serializer implementation that simply returns the input.
716
717
    The input is returned in the order used by pack.ContainerPushParser.
718
    """
719
    @staticmethod
720
    def bytes_record(bytes, names):
721
        return names, bytes
722
723
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
724
class TestSerializeTransform(tests.TestCaseWithTransport):
725
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
726
    _test_needs_features = [features.UnicodeFilenameFeature]
0.13.22 by Aaron Bentley
More unicodeness for Shelf tests
727
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
728
    def get_preview(self, tree=None):
729
        if tree is None:
730
            tree = self.make_branch_and_tree('tree')
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
731
        tt = tree.preview_transform()
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
732
        self.addCleanup(tt.finalize)
733
        return tt
734
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
735
    def assertSerializesTo(self, expected, tt):
736
        records = list(tt.serialize(FakeSerializer()))
737
        self.assertEqual(expected, records)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
738
0.13.13 by Aaron Bentley
Add direct test of serialization records
739
    @staticmethod
740
    def default_attribs():
741
        return {
6973.10.1 by Jelmer Vernooij
Fix some tests.
742
            b'_id_number': 1,
743
            b'_new_name': {},
744
            b'_new_parent': {},
745
            b'_new_executability': {},
746
            b'_new_id': {},
747
            b'_tree_path_ids': {b'': b'new-0'},
748
            b'_removed_id': [],
749
            b'_removed_contents': [],
750
            b'_non_present_ids': {},
0.13.13 by Aaron Bentley
Add direct test of serialization records
751
            }
752
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
753
    def make_records(self, attribs, contents):
754
        records = [
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
755
            ((((b'attribs'),),), bencode.bencode(attribs))]
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
756
        records.extend([(((n, k),), c) for n, k, c in contents])
757
        return records
758
0.13.13 by Aaron Bentley
Add direct test of serialization records
759
    def creation_records(self):
760
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
761
        attribs[b'_id_number'] = 3
762
        attribs[b'_new_name'] = {
763
            b'new-1': u'foo\u1234'.encode('utf-8'), b'new-2': b'qux'}
764
        attribs[b'_new_id'] = {b'new-1': b'baz', b'new-2': b'quxx'}
765
        attribs[b'_new_parent'] = {b'new-1': b'new-0', b'new-2': b'new-0'}
766
        attribs[b'_new_executability'] = {b'new-1': 1}
0.13.13 by Aaron Bentley
Add direct test of serialization records
767
        contents = [
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
768
            (b'new-1', b'file', b'i 1\nbar\n'),
769
            (b'new-2', b'directory', b''),
0.13.13 by Aaron Bentley
Add direct test of serialization records
770
            ]
771
        return self.make_records(attribs, contents)
772
773
    def test_serialize_creation(self):
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
774
        tt = self.get_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
775
        tt.new_file(u'foo\u1234', tt.root, [b'bar'], b'baz', True)
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
776
        tt.new_directory('qux', tt.root, b'quxx')
0.13.21 by Aaron Bentley
Use assertSerializesTo in more places
777
        self.assertSerializesTo(self.creation_records(), tt)
0.13.13 by Aaron Bentley
Add direct test of serialization records
778
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
779
    def test_deserialize_creation(self):
780
        tt = self.get_preview()
781
        tt.deserialize(iter(self.creation_records()))
782
        self.assertEqual(3, tt._id_number)
783
        self.assertEqual({'new-1': u'foo\u1234',
784
                          'new-2': 'qux'}, tt._new_name)
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
785
        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.
786
        self.assertEqual({'new-1': tt.root, 'new-2': tt.root}, tt._new_parent)
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
787
        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.
788
        self.assertEqual({'new-1': True}, tt._new_executability)
789
        self.assertEqual({'new-1': 'file',
790
                          'new-2': 'directory'}, tt._new_contents)
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
791
        with open(tt._limbo_name('new-1'), 'rb') as foo_limbo:
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
792
            foo_content = foo_limbo.read()
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
793
        self.assertEqual(b'bar', foo_content)
0.13.14 by Aaron Bentley
Add deserialization test, remove roundtrip test.
794
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
795
    def symlink_creation_records(self):
796
        attribs = self.default_attribs()
7045.4.9 by Jelmer Vernooij
Fix some transform tests.
797
        attribs[b'_id_number'] = 2
798
        attribs[b'_new_name'] = {b'new-1': u'foo\u1234'.encode('utf-8')}
799
        attribs[b'_new_parent'] = {b'new-1': b'new-0'}
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
800
        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
801
        return self.make_records(attribs, contents)
802
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
803
    def test_serialize_symlink_creation(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
804
        self.requireFeature(features.SymlinkFeature)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
805
        tt = self.get_preview()
0.13.16 by Aaron Bentley
Add unicode symlink targets to tests
806
        tt.new_symlink(u'foo\u1234', tt.root, u'bar\u1234')
0.13.21 by Aaron Bentley
Use assertSerializesTo in more places
807
        self.assertSerializesTo(self.symlink_creation_records(), tt)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
808
809
    def test_deserialize_symlink_creation(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
810
        self.requireFeature(features.SymlinkFeature)
0.13.15 by Aaron Bentley
Convert symlink tests to avoid roundtripping
811
        tt = self.get_preview()
812
        tt.deserialize(iter(self.symlink_creation_records()))
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
813
        abspath = tt._limbo_name('new-1')
4241.14.17 by Vincent Ladeuil
Add more tests for unicode symlinks to test_transform.
814
        foo_content = osutils.readlink(abspath)
0.13.22 by Aaron Bentley
More unicodeness for Shelf tests
815
        self.assertEqual(u'bar\u1234', foo_content)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
816
0.13.19 by Aaron Bentley
Clean up serialization tests
817
    def make_destruction_preview(self):
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
818
        tree = self.make_branch_and_tree('.')
819
        self.build_tree([u'foo\u1234', 'bar'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
820
        tree.add([u'foo\u1234', 'bar'], [b'foo-id', b'bar-id'])
0.13.19 by Aaron Bentley
Clean up serialization tests
821
        return self.get_preview(tree)
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
822
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
823
    def destruction_records(self):
824
        attribs = self.default_attribs()
7045.4.9 by Jelmer Vernooij
Fix some transform tests.
825
        attribs[b'_id_number'] = 3
826
        attribs[b'_removed_id'] = [b'new-1']
827
        attribs[b'_removed_contents'] = [b'new-2']
828
        attribs[b'_tree_path_ids'] = {
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
829
            b'': b'new-0',
830
            u'foo\u1234'.encode('utf-8'): b'new-1',
831
            b'bar': b'new-2',
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
832
            }
833
        return self.make_records(attribs, [])
834
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
835
    def test_serialize_destruction(self):
0.13.19 by Aaron Bentley
Clean up serialization tests
836
        tt = self.make_destruction_preview()
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
837
        foo_trans_id = tt.trans_id_tree_path(u'foo\u1234')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
838
        tt.unversion_file(foo_trans_id)
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
839
        bar_trans_id = tt.trans_id_tree_path('bar')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
840
        tt.delete_contents(bar_trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
841
        self.assertSerializesTo(self.destruction_records(), tt)
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
842
843
    def test_deserialize_destruction(self):
0.13.19 by Aaron Bentley
Clean up serialization tests
844
        tt = self.make_destruction_preview()
0.13.17 by Aaron Bentley
Convert roundtrip destruction test to serialization/deserialization pair
845
        tt.deserialize(iter(self.destruction_records()))
846
        self.assertEqual({u'foo\u1234': 'new-1',
847
                          'bar': 'new-2',
848
                          '': tt.root}, tt._tree_path_ids)
849
        self.assertEqual({'new-1': u'foo\u1234',
850
                          'new-2': 'bar',
851
                          tt.root: ''}, tt._tree_id_paths)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
852
        self.assertEqual({'new-1'}, tt._removed_id)
853
        self.assertEqual({'new-2'}, tt._removed_contents)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
854
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
855
    def missing_records(self):
856
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
857
        attribs[b'_id_number'] = 2
858
        attribs[b'_non_present_ids'] = {
7143.15.2 by Jelmer Vernooij
Run autopep8.
859
            b'boo': b'new-1', }
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
860
        return self.make_records(attribs, [])
861
862
    def test_serialize_missing(self):
863
        tt = self.get_preview()
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
864
        tt.trans_id_file_id(b'boo')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
865
        self.assertSerializesTo(self.missing_records(), tt)
866
867
    def test_deserialize_missing(self):
868
        tt = self.get_preview()
869
        tt.deserialize(iter(self.missing_records()))
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
870
        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
871
872
    def make_modification_preview(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
873
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
874
        LINES_TWO = b'z\nbb\nx\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
875
        tree = self.make_branch_and_tree('tree')
876
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
877
        tree.add('file', b'file-id')
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
878
        return self.get_preview(tree), [LINES_TWO]
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
879
880
    def modification_records(self):
881
        attribs = self.default_attribs()
7045.4.9 by Jelmer Vernooij
Fix some transform tests.
882
        attribs[b'_id_number'] = 2
883
        attribs[b'_tree_path_ids'] = {
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
884
            b'file': b'new-1',
7143.15.2 by Jelmer Vernooij
Run autopep8.
885
            b'': b'new-0', }
7045.4.9 by Jelmer Vernooij
Fix some transform tests.
886
        attribs[b'_removed_contents'] = [b'new-1']
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
887
        contents = [(b'new-1', b'file',
7045.4.1 by Jelmer Vernooij
Some brz-git fixes.
888
                     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
889
        return self.make_records(attribs, contents)
890
891
    def test_serialize_modification(self):
892
        tt, LINES = self.make_modification_preview()
6973.10.1 by Jelmer Vernooij
Fix some tests.
893
        trans_id = tt.trans_id_file_id(b'file-id')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
894
        tt.delete_contents(trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
895
        tt.create_file(LINES, trans_id)
896
        self.assertSerializesTo(self.modification_records(), tt)
897
898
    def test_deserialize_modification(self):
899
        tt, LINES = self.make_modification_preview()
900
        tt.deserialize(iter(self.modification_records()))
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
901
        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
902
903
    def make_kind_change_preview(self):
6973.10.1 by Jelmer Vernooij
Fix some tests.
904
        LINES = b'a\nb\nc\nd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
905
        tree = self.make_branch_and_tree('tree')
906
        self.build_tree(['tree/foo/'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
907
        tree.add('foo', b'foo-id')
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
908
        return self.get_preview(tree), [LINES]
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
909
910
    def kind_change_records(self):
911
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
912
        attribs[b'_id_number'] = 2
913
        attribs[b'_tree_path_ids'] = {
914
            b'foo': b'new-1',
7143.15.2 by Jelmer Vernooij
Run autopep8.
915
            b'': b'new-0', }
6973.10.1 by Jelmer Vernooij
Fix some tests.
916
        attribs[b'_removed_contents'] = [b'new-1']
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
917
        contents = [(b'new-1', b'file',
6973.10.1 by Jelmer Vernooij
Fix some tests.
918
                     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
919
        return self.make_records(attribs, contents)
920
921
    def test_serialize_kind_change(self):
922
        tt, LINES = self.make_kind_change_preview()
6855.4.1 by Jelmer Vernooij
Yet more bees.
923
        trans_id = tt.trans_id_file_id(b'foo-id')
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
924
        tt.delete_contents(trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
925
        tt.create_file(LINES, trans_id)
926
        self.assertSerializesTo(self.kind_change_records(), tt)
927
928
    def test_deserialize_kind_change(self):
929
        tt, LINES = self.make_kind_change_preview()
930
        tt.deserialize(iter(self.kind_change_records()))
7045.4.7 by Jelmer Vernooij
Fix remaining tests.
931
        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
932
933
    def make_add_contents_preview(self):
6973.10.1 by Jelmer Vernooij
Fix some tests.
934
        LINES = b'a\nb\nc\nd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
935
        tree = self.make_branch_and_tree('tree')
936
        self.build_tree(['tree/foo'])
937
        tree.add('foo')
938
        os.unlink('tree/foo')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
939
        return self.get_preview(tree), LINES
940
941
    def add_contents_records(self):
942
        attribs = self.default_attribs()
6973.10.1 by Jelmer Vernooij
Fix some tests.
943
        attribs[b'_id_number'] = 2
944
        attribs[b'_tree_path_ids'] = {
945
            b'foo': b'new-1',
7143.15.2 by Jelmer Vernooij
Run autopep8.
946
            b'': b'new-0', }
7045.3.1 by Jelmer Vernooij
Fix another ~500 tests.
947
        contents = [(b'new-1', b'file',
6973.10.1 by Jelmer Vernooij
Fix some tests.
948
                     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
949
        return self.make_records(attribs, contents)
950
951
    def test_serialize_add_contents(self):
952
        tt, LINES = self.make_add_contents_preview()
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
953
        trans_id = tt.trans_id_tree_path('foo')
6973.10.1 by Jelmer Vernooij
Fix some tests.
954
        tt.create_file([LINES], trans_id)
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
955
        self.assertSerializesTo(self.add_contents_records(), tt)
956
957
    def test_deserialize_add_contents(self):
958
        tt, LINES = self.make_add_contents_preview()
959
        tt.deserialize(iter(self.add_contents_records()))
960
        self.assertFileEqual(LINES, tt._limbo_name('new-1'))
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
961
962
    def test_get_parents_lines(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
963
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
964
        tree = self.make_branch_and_tree('tree')
965
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
966
        tree.add('file', b'file-id')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
967
        tt = self.get_preview(tree)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
968
        trans_id = tt.trans_id_tree_path('file')
6973.10.1 by Jelmer Vernooij
Fix some tests.
969
        self.assertEqual(([b'aa\n', b'bb\n', b'cc\n', b'dd\n'],),
7143.15.2 by Jelmer Vernooij
Run autopep8.
970
                         tt._get_parents_lines(trans_id))
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
971
972
    def test_get_parents_texts(self):
6855.4.1 by Jelmer Vernooij
Yet more bees.
973
        LINES_ONE = b'aa\nbb\ncc\ndd\n'
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
974
        tree = self.make_branch_and_tree('tree')
975
        self.build_tree_contents([('tree/file', LINES_ONE)])
6855.4.1 by Jelmer Vernooij
Yet more bees.
976
        tree.add('file', b'file-id')
0.13.18 by Aaron Bentley
Finish converting tests to direct serialize/deserialize tests, clean up
977
        tt = self.get_preview(tree)
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
978
        trans_id = tt.trans_id_tree_path('file')
979
        self.assertEqual((LINES_ONE,),
7143.15.2 by Jelmer Vernooij
Run autopep8.
980
                         tt._get_parents_texts(trans_id))
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
981
982
983
class TestOrphan(tests.TestCaseWithTransport):
984
985
    def test_no_orphan_for_transform_preview(self):
986
        tree = self.make_branch_and_tree('tree')
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
987
        tt = tree.preview_transform()
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
988
        self.addCleanup(tt.finalize)
989
        self.assertRaises(NotImplementedError, tt.new_orphan, 'foo', 'bar')
990
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
991
    def _set_orphan_policy(self, wt, policy):
6883.13.1 by Jelmer Vernooij
Rename bzr.transform.orphan_policy -> transform.orphan_policy.
992
        wt.branch.get_config_stack().set('transform.orphan_policy',
7143.15.2 by Jelmer Vernooij
Run autopep8.
993
                                         policy)
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
994
995
    def _prepare_orphan(self, wt):
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
996
        self.build_tree(['dir/', 'dir/file', 'dir/foo'])
6855.4.1 by Jelmer Vernooij
Yet more bees.
997
        wt.add(['dir', 'dir/file'], [b'dir-id', b'file-id'])
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
998
        wt.commit('add dir and file ignoring foo')
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
999
        tt = wt.transform()
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1000
        self.addCleanup(tt.finalize)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1001
        # dir and bar are deleted
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1002
        dir_tid = tt.trans_id_tree_path('dir')
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1003
        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.
1004
        orphan_tid = tt.trans_id_tree_path('dir/foo')
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1005
        tt.delete_contents(file_tid)
1006
        tt.unversion_file(file_tid)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1007
        tt.delete_contents(dir_tid)
1008
        tt.unversion_file(dir_tid)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1009
        # There should be a conflict because dir still contain foo
7490.129.2 by Jelmer Vernooij
Move cook conflict implementation into breezy.bzr.transform.
1010
        raw_conflicts = tt.find_raw_conflicts()
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1011
        self.assertLength(1, raw_conflicts)
1012
        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.
1013
        return tt, orphan_tid
1014
1015
    def test_new_orphan_created(self):
1016
        wt = self.make_branch_and_tree('.')
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
1017
        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.
1018
        tt, orphan_tid = self._prepare_orphan(wt)
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1019
        warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1020
5540.3.1 by Vincent Ladeuil
Fix spurious orphan reports.
1021
        def warning(*args):
1022
            warnings.append(args[0] % args[1:])
1023
        self.overrideAttr(trace, 'warning', warning)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1024
        remaining_conflicts = resolve_conflicts(tt)
6681.2.10 by Jelmer Vernooij
Fix failures.
1025
        self.assertEqual(['dir/foo has been orphaned in brz-orphans'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1026
                         warnings)
5409.7.2 by Vincent Ladeuil
Add NEWS entry, a missing test and some cleanup.
1027
        # Yeah for resolved conflicts !
1028
        self.assertLength(0, remaining_conflicts)
1029
        # We have a new orphan
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1030
        self.assertEqual('foo.~1~', tt.final_name(orphan_tid))
6681.2.10 by Jelmer Vernooij
Fix failures.
1031
        self.assertEqual('brz-orphans',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1032
                         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.
1033
1034
    def test_never_orphan(self):
1035
        wt = self.make_branch_and_tree('.')
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
1036
        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.
1037
        tt, orphan_tid = self._prepare_orphan(wt)
1038
        remaining_conflicts = resolve_conflicts(tt)
1039
        self.assertLength(1, remaining_conflicts)
1040
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
1041
                         remaining_conflicts.pop())
1042
1043
    def test_orphan_error(self):
1044
        def bogus_orphan(tt, orphan_id, parent_id):
1045
            raise transform.OrphaningError(tt.final_name(orphan_id),
1046
                                           tt.final_name(parent_id))
1047
        transform.orphaning_registry.register('bogus', bogus_orphan,
1048
                                              'Raise an error when orphaning')
1049
        wt = self.make_branch_and_tree('.')
1050
        self._set_orphan_policy(wt, 'bogus')
1051
        tt, orphan_tid = self._prepare_orphan(wt)
1052
        remaining_conflicts = resolve_conflicts(tt)
1053
        self.assertLength(1, remaining_conflicts)
1054
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
1055
                         remaining_conflicts.pop())
5409.1.17 by Vincent Ladeuil
Ensures we fallback to the default policy if a bogus one is specified.
1056
1057
    def test_unknown_orphan_policy(self):
1058
        wt = self.make_branch_and_tree('.')
1059
        # Set a fictional policy nobody ever implemented
1060
        self._set_orphan_policy(wt, 'donttouchmypreciouuus')
1061
        tt, orphan_tid = self._prepare_orphan(wt)
1062
        warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1063
5409.1.17 by Vincent Ladeuil
Ensures we fallback to the default policy if a bogus one is specified.
1064
        def warning(*args):
1065
            warnings.append(args[0] % args[1:])
1066
        self.overrideAttr(trace, 'warning', warning)
1067
        remaining_conflicts = resolve_conflicts(tt)
5409.1.20 by Vincent Ladeuil
Revert to 'conflict' being the default orphaning policy and fix fallouts.
1068
        # We fallback to the default policy which create a conflict
1069
        self.assertLength(1, remaining_conflicts)
1070
        self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
1071
                         remaining_conflicts.pop())
1072
        self.assertLength(1, warnings)
6449.6.7 by Jelmer Vernooij
Fix tests.
1073
        self.assertStartsWith(warnings[0], 'Value "donttouchmypreciouuus" ')
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1074
1075
1076
class TestTransformHooks(tests.TestCaseWithTransport):
1077
1078
    def setUp(self):
1079
        super(TestTransformHooks, self).setUp()
1080
        self.wt = self.make_branch_and_tree('.')
1081
        os.chdir('..')
1082
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1083
    def transform(self):
7490.80.2 by Jelmer Vernooij
Call tree.transform() rather than constructor.
1084
        transform = self.wt.transform()
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1085
        self.addCleanup(transform.finalize)
1086
        return transform, transform.root
1087
1088
    def test_pre_commit_hooks(self):
1089
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1090
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1091
        def record_pre_transform(tree, tt):
1092
            calls.append((tree, tt))
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1093
        MutableTree.hooks.install_named_hook(
1094
            'pre_transform', record_pre_transform, "Pre transform")
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1095
        transform, root = self.transform()
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1096
        old_root_id = transform.tree_file_id(root)
1097
        transform.apply()
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
1098
        self.assertEqual(old_root_id, self.wt.path2id(''))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1099
        self.assertEqual([(self.wt, transform)], calls)
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1100
1101
    def test_post_commit_hooks(self):
1102
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1103
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1104
        def record_post_transform(tree, tt):
1105
            calls.append((tree, tt))
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1106
        MutableTree.hooks.install_named_hook(
1107
            'post_transform', record_post_transform, "Post transform")
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1108
        transform, root = self.transform()
6434.2.2 by Jelmer Vernooij
Add hooks for tree transforms.
1109
        old_root_id = transform.tree_file_id(root)
1110
        transform.apply()
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
1111
        self.assertEqual(old_root_id, self.wt.path2id(''))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1112
        self.assertEqual([(self.wt, transform)], calls)
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1113
1114
1115
class TestLinkTree(tests.TestCaseWithTransport):
1116
1117
    _test_needs_features = [HardlinkFeature]
1118
1119
    def setUp(self):
1120
        tests.TestCaseWithTransport.setUp(self)
1121
        self.parent_tree = self.make_branch_and_tree('parent')
1122
        self.parent_tree.lock_write()
1123
        self.addCleanup(self.parent_tree.unlock)
6855.4.1 by Jelmer Vernooij
Yet more bees.
1124
        self.build_tree_contents([('parent/foo', b'bar')])
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1125
        self.parent_tree.add('foo')
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1126
        self.parent_tree.commit('added foo')
6652.1.4 by Jelmer Vernooij
Fix test.
1127
        child_controldir = self.parent_tree.controldir.sprout('child')
1128
        self.child_tree = child_controldir.open_workingtree()
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1129
1130
    def hardlinked(self):
1131
        parent_stat = os.lstat(self.parent_tree.abspath('foo'))
1132
        child_stat = os.lstat(self.child_tree.abspath('foo'))
1133
        return parent_stat.st_ino == child_stat.st_ino
1134
1135
    def test_link_fails_if_modified(self):
1136
        """If the file to be linked has modified text, don't link."""
6855.4.1 by Jelmer Vernooij
Yet more bees.
1137
        self.build_tree_contents([('child/foo', b'baz')])
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1138
        transform.link_tree(self.child_tree, self.parent_tree)
1139
        self.assertFalse(self.hardlinked())
1140
1141
    def test_link_fails_if_execute_bit_changed(self):
1142
        """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.
1143
        tt = self.child_tree.transform()
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1144
        try:
6885.1.1 by Jelmer Vernooij
Get rid of TreeTransform.trans_id_tree_file_id.
1145
            trans_id = tt.trans_id_tree_path('foo')
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1146
            tt.set_executability(True, trans_id)
1147
            tt.apply()
1148
        finally:
1149
            tt.finalize()
1150
        transform.link_tree(self.child_tree, self.parent_tree)
1151
        self.assertFalse(self.hardlinked())
1152
1153
    def test_link_succeeds_if_unmodified(self):
1154
        """If the file to be linked is unmodified, link"""
1155
        transform.link_tree(self.child_tree, self.parent_tree)
1156
        self.assertTrue(self.hardlinked())
7490.77.4 by Jelmer Vernooij
Move some errors around.
1157
1158
1159
class ErrorTests(tests.TestCase):
1160
1161
    def test_transform_rename_failed(self):
1162
        e = TransformRenameFailed(u"from", u"to", "readonly file", 2)
1163
        self.assertEqual(
1164
            u"Failed to rename from to to: readonly file",
1165
            str(e))