/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
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
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
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
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
16
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
17
from cStringIO import StringIO
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
18
import os
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
19
import sys
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
20
1910.2.64 by Aaron Bentley
Changes from review
21
from bzrlib import (
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
22
    bzrdir,
23
    errors,
24
    inventory,
3638.3.2 by Vincent Ladeuil
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.
25
    osutils,
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
26
    repository,
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
27
    revision as _mod_revision,
1910.2.64 by Aaron Bentley
Changes from review
28
    treebuilder,
29
    )
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
30
from bzrlib.bzrdir import BzrDir
3251.4.11 by Aaron Bentley
Fix wrong local lookups
31
from bzrlib.bundle import read_mergeable_from_url
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
32
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
1793.2.3 by Aaron Bentley
Rename read_bundle.py to bundle_data.py
33
from bzrlib.bundle.bundle_data import BundleTree
3251.4.11 by Aaron Bentley
Fix wrong local lookups
34
from bzrlib.directory_service import directories
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
35
from bzrlib.bundle.serializer import write_bundle, read_bundle, v09, v4
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
36
from bzrlib.bundle.serializer.v08 import BundleSerializerV08
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
37
from bzrlib.bundle.serializer.v09 import BundleSerializerV09
2520.4.72 by Aaron Bentley
Rename format to 4alpha
38
from bzrlib.bundle.serializer.v4 import BundleSerializerV4
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
39
from bzrlib.branch import Branch
1185.82.90 by Aaron Bentley
Reorganized test suite
40
from bzrlib.diff import internal_diff
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
41
from bzrlib.merge import Merge3Merger
2241.1.5 by Martin Pool
Move KnitFormat2 into repofmt
42
from bzrlib.repofmt import knitrepo
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
43
from bzrlib.osutils import sha_file, sha_string
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
44
from bzrlib.tests import (
45
    SymlinkFeature,
46
    TestCase,
47
    TestCaseInTempDir,
48
    TestCaseWithTransport,
49
    TestSkipped,
3251.4.11 by Aaron Bentley
Fix wrong local lookups
50
    test_read_bundle,
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
51
    test_commit,
52
    )
1185.82.66 by Aaron Bentley
Handle new executable files
53
from bzrlib.transform import TreeTransform
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
54
1185.82.90 by Aaron Bentley
Reorganized test suite
55
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
56
class MockTree(object):
57
    def __init__(self):
1731.1.4 by Aaron Bentley
merge from bzr.dev
58
        from bzrlib.inventory import InventoryDirectory, ROOT_ID
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
59
        object.__init__(self)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
60
        self.paths = {ROOT_ID: ""}
61
        self.ids = {"": ROOT_ID}
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
62
        self.contents = {}
1731.1.4 by Aaron Bentley
merge from bzr.dev
63
        self.root = InventoryDirectory(ROOT_ID, '', None)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
64
65
    inventory = property(lambda x:x)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
66
67
    def __iter__(self):
68
        return self.paths.iterkeys()
69
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
70
    def __getitem__(self, file_id):
71
        if file_id == self.root.file_id:
72
            return self.root
73
        else:
74
            return self.make_entry(file_id, self.paths[file_id])
75
76
    def parent_id(self, file_id):
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
77
        parent_dir = os.path.dirname(self.paths[file_id])
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
78
        if parent_dir == "":
79
            return None
80
        return self.ids[parent_dir]
81
82
    def iter_entries(self):
83
        for path, file_id in self.ids.iteritems():
84
            yield path, self[file_id]
85
86
    def get_file_kind(self, file_id):
87
        if file_id in self.contents:
88
            kind = 'file'
89
        else:
90
            kind = 'directory'
91
        return kind
92
93
    def make_entry(self, file_id, path):
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
94
        from bzrlib.inventory import (InventoryEntry, InventoryFile
95
                                    , InventoryDirectory, InventoryLink)
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
96
        name = os.path.basename(path)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
97
        kind = self.get_file_kind(file_id)
98
        parent_id = self.parent_id(file_id)
99
        text_sha_1, text_size = self.contents_stats(file_id)
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
100
        if kind == 'directory':
101
            ie = InventoryDirectory(file_id, name, parent_id)
102
        elif kind == 'file':
103
            ie = InventoryFile(file_id, name, parent_id)
104
        elif kind == 'symlink':
105
            ie = InventoryLink(file_id, name, parent_id)
106
        else:
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
107
            raise errors.BzrError('unknown kind %r' % kind)
0.5.91 by Aaron Bentley
Updated to match API change
108
        ie.text_sha1 = text_sha_1
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
109
        ie.text_size = text_size
110
        return ie
111
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
112
    def add_dir(self, file_id, path):
113
        self.paths[file_id] = path
114
        self.ids[path] = file_id
115
    
116
    def add_file(self, file_id, path, contents):
117
        self.add_dir(file_id, path)
118
        self.contents[file_id] = contents
119
120
    def path2id(self, path):
121
        return self.ids.get(path)
122
123
    def id2path(self, file_id):
124
        return self.paths.get(file_id)
125
126
    def has_id(self, file_id):
127
        return self.id2path(file_id) is not None
128
129
    def get_file(self, file_id):
130
        result = StringIO()
131
        result.write(self.contents[file_id])
132
        result.seek(0,0)
133
        return result
134
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
135
    def contents_stats(self, file_id):
136
        if file_id not in self.contents:
137
            return None, None
138
        text_sha1 = sha_file(self.get_file(file_id))
139
        return text_sha1, len(self.contents[file_id])
140
141
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
142
class BTreeTester(TestCase):
143
    """A simple unittest tester for the BundleTree class."""
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
144
145
    def make_tree_1(self):
146
        mtree = MockTree()
147
        mtree.add_dir("a", "grandparent")
148
        mtree.add_dir("b", "grandparent/parent")
149
        mtree.add_file("c", "grandparent/parent/file", "Hello\n")
150
        mtree.add_dir("d", "grandparent/alt_parent")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
151
        return BundleTree(mtree, ''), mtree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
152
        
153
    def test_renames(self):
154
        """Ensure that file renames have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
155
        btree = self.make_tree_1()[0]
156
        self.assertEqual(btree.old_path("grandparent"), "grandparent")
157
        self.assertEqual(btree.old_path("grandparent/parent"), 
158
                         "grandparent/parent")
159
        self.assertEqual(btree.old_path("grandparent/parent/file"),
160
                         "grandparent/parent/file")
161
162
        self.assertEqual(btree.id2path("a"), "grandparent")
163
        self.assertEqual(btree.id2path("b"), "grandparent/parent")
164
        self.assertEqual(btree.id2path("c"), "grandparent/parent/file")
165
166
        self.assertEqual(btree.path2id("grandparent"), "a")
167
        self.assertEqual(btree.path2id("grandparent/parent"), "b")
168
        self.assertEqual(btree.path2id("grandparent/parent/file"), "c")
169
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
170
        self.assertTrue(btree.path2id("grandparent2") is None)
171
        self.assertTrue(btree.path2id("grandparent2/parent") is None)
172
        self.assertTrue(btree.path2id("grandparent2/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
173
174
        btree.note_rename("grandparent", "grandparent2")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
175
        self.assertTrue(btree.old_path("grandparent") is None)
176
        self.assertTrue(btree.old_path("grandparent/parent") is None)
177
        self.assertTrue(btree.old_path("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
178
179
        self.assertEqual(btree.id2path("a"), "grandparent2")
180
        self.assertEqual(btree.id2path("b"), "grandparent2/parent")
181
        self.assertEqual(btree.id2path("c"), "grandparent2/parent/file")
182
183
        self.assertEqual(btree.path2id("grandparent2"), "a")
184
        self.assertEqual(btree.path2id("grandparent2/parent"), "b")
185
        self.assertEqual(btree.path2id("grandparent2/parent/file"), "c")
186
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
187
        self.assertTrue(btree.path2id("grandparent") is None)
188
        self.assertTrue(btree.path2id("grandparent/parent") is None)
189
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
190
191
        btree.note_rename("grandparent/parent", "grandparent2/parent2")
192
        self.assertEqual(btree.id2path("a"), "grandparent2")
193
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
194
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file")
195
196
        self.assertEqual(btree.path2id("grandparent2"), "a")
197
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
198
        self.assertEqual(btree.path2id("grandparent2/parent2/file"), "c")
199
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
200
        self.assertTrue(btree.path2id("grandparent2/parent") is None)
201
        self.assertTrue(btree.path2id("grandparent2/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
202
203
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
204
                          "grandparent2/parent2/file2")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
205
        self.assertEqual(btree.id2path("a"), "grandparent2")
206
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
207
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file2")
208
209
        self.assertEqual(btree.path2id("grandparent2"), "a")
210
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
211
        self.assertEqual(btree.path2id("grandparent2/parent2/file2"), "c")
212
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
213
        self.assertTrue(btree.path2id("grandparent2/parent2/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
214
215
    def test_moves(self):
216
        """Ensure that file moves have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
217
        btree = self.make_tree_1()[0]
218
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
219
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
220
        self.assertEqual(btree.id2path("c"), "grandparent/alt_parent/file")
221
        self.assertEqual(btree.path2id("grandparent/alt_parent/file"), "c")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
222
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
223
224
    def unified_diff(self, old, new):
225
        out = StringIO()
226
        internal_diff("old", old, "new", new, out)
227
        out.seek(0,0)
228
        return out.read()
229
230
    def make_tree_2(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
231
        btree = self.make_tree_1()[0]
232
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
233
                          "grandparent/alt_parent/file")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
234
        self.assertTrue(btree.id2path("e") is None)
235
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
236
        btree.note_id("e", "grandparent/parent/file")
237
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
238
239
    def test_adds(self):
240
        """File/inventory adds"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
241
        btree = self.make_tree_2()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
242
        add_patch = self.unified_diff([], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
243
        btree.note_patch("grandparent/parent/file", add_patch)
244
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
245
        btree.note_target('grandparent/parent/symlink', 'venus')
246
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
247
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
248
    def adds_test(self, btree):
249
        self.assertEqual(btree.id2path("e"), "grandparent/parent/file")
250
        self.assertEqual(btree.path2id("grandparent/parent/file"), "e")
251
        self.assertEqual(btree.get_file("e").read(), "Extra cheese\n")
252
        self.assertEqual(btree.get_symlink_target('f'), 'venus')
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
253
254
    def test_adds2(self):
255
        """File/inventory adds, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
256
        btree = self.make_tree_2()
257
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
258
        add_patch = self.unified_diff(["Hello\n"], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
259
        btree.note_patch("grandparent/parent/file", add_patch)
260
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
261
        btree.note_target('grandparent/parent/symlink', 'venus')
262
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
263
264
    def make_tree_3(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
265
        btree, mtree = self.make_tree_1()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
266
        mtree.add_file("e", "grandparent/parent/topping", "Anchovies\n")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
267
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
268
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
269
        btree.note_rename("grandparent/parent/topping", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
270
                          "grandparent/alt_parent/stopping")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
271
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
272
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
273
    def get_file_test(self, btree):
274
        self.assertEqual(btree.get_file("e").read(), "Lemon\n")
275
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
276
277
    def test_get_file(self):
278
        """Get file contents"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
279
        btree = self.make_tree_3()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
280
        mod_patch = self.unified_diff(["Anchovies\n"], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
281
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
282
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
283
284
    def test_get_file2(self):
285
        """Get file contents, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
286
        btree = self.make_tree_3()
287
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
288
        mod_patch = self.unified_diff([], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
289
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
290
        mod_patch = self.unified_diff([], ["Hello\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
291
        btree.note_patch("grandparent/alt_parent/file", mod_patch)
292
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
293
294
    def test_delete(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
295
        "Deletion by bundle"
296
        btree = self.make_tree_1()[0]
297
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
298
        btree.note_deletion("grandparent/parent/file")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
299
        self.assertTrue(btree.id2path("c") is None)
300
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
301
302
    def sorted_ids(self, tree):
303
        ids = list(tree)
304
        ids.sort()
305
        return ids
306
307
    def test_iteration(self):
308
        """Ensure that iteration through ids works properly"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
309
        btree = self.make_tree_1()[0]
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
310
        self.assertEqual(self.sorted_ids(btree),
311
            [inventory.ROOT_ID, 'a', 'b', 'c', 'd'])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
312
        btree.note_deletion("grandparent/parent/file")
313
        btree.note_id("e", "grandparent/alt_parent/fool", kind="directory")
314
        btree.note_last_changed("grandparent/alt_parent/fool", 
1185.82.95 by Aaron Bentley
Restore path-orientation of ChangesetTree
315
                                "revisionidiguess")
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
316
        self.assertEqual(self.sorted_ids(btree),
317
            [inventory.ROOT_ID, 'a', 'b', 'd', 'e'])
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
318
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
319
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
320
class BundleTester1(TestCaseWithTransport):
321
322
    def test_mismatched_bundle(self):
323
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
324
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
325
        serializer = BundleSerializerV08('0.8')
326
        b = self.make_branch('.', format=format)
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
327
        self.assertRaises(errors.IncompatibleBundleFormat, serializer.write, 
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
328
                          b.repository, [], {}, StringIO())
329
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
330
    def test_matched_bundle(self):
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
331
        """Don't raise IncompatibleBundleFormat for knit2 and bundle0.9"""
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
332
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
333
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
334
        serializer = BundleSerializerV09('0.9')
335
        b = self.make_branch('.', format=format)
336
        serializer.write(b.repository, [], {}, StringIO())
337
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
338
    def test_mismatched_model(self):
339
        """Try copying a bundle from knit2 to knit1"""
340
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
341
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
342
        source = self.make_branch_and_tree('source', format=format)
343
        source.commit('one', rev_id='one-id')
344
        source.commit('two', rev_id='two-id')
345
        text = StringIO()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
346
        write_bundle(source.branch.repository, 'two-id', 'null:', text,
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
347
                     format='0.9')
348
        text.seek(0)
349
350
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
351
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
352
        target = self.make_branch('target', format=format)
353
        self.assertRaises(errors.IncompatibleRevision, install_bundle, 
354
                          target.repository, read_bundle(text))
355
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
356
2520.4.43 by Aaron Bentley
Fix test suite
357
class BundleTester(object):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
358
359
    def bzrdir_format(self):
360
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
361
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
362
        return format
363
364
    def make_branch_and_tree(self, path, format=None):
365
        if format is None:
366
            format = self.bzrdir_format()
367
        return TestCaseWithTransport.make_branch_and_tree(self, path, format)
368
369
    def make_branch(self, path, format=None):
370
        if format is None:
371
            format = self.bzrdir_format()
372
        return TestCaseWithTransport.make_branch(self, path, format)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
373
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
374
    def create_bundle_text(self, base_rev_id, rev_id):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
375
        bundle_txt = StringIO()
376
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id, 
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
377
                               bundle_txt, format=self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
378
        bundle_txt.seek(0)
379
        self.assertEqual(bundle_txt.readline(), 
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
380
                         '# Bazaar revision bundle v%s\n' % self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
381
        self.assertEqual(bundle_txt.readline(), '#\n')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
382
1185.82.14 by Aaron Bentley
API updates
383
        rev = self.b1.repository.get_revision(rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
384
        self.assertEqual(bundle_txt.readline().decode('utf-8'),
385
                         u'# message:\n')
386
        bundle_txt.seek(0)
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
387
        return bundle_txt, rev_ids
388
389
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
390
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
391
        Make sure that the text generated is valid, and that it
392
        can be applied against the base, and generate the same information.
393
        
394
        :return: The in-memory bundle 
395
        """
396
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
397
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
398
        # This should also validate the generated bundle 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
399
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
400
        repository = self.b1.repository
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
401
        for bundle_rev in bundle.real_revisions:
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
402
            # These really should have already been checked when we read the
403
            # bundle, since it computes the sha1 hash for the revision, which
404
            # only will match if everything is okay, but lets be explicit about
405
            # it
406
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1185.82.33 by Aaron Bentley
Strengthen tests
407
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
408
                      'timestamp', 'timezone', 'message', 'committer', 
409
                      'parent_ids', 'properties'):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
410
                self.assertEqual(getattr(branch_rev, a), 
411
                                 getattr(bundle_rev, a))
412
            self.assertEqual(len(branch_rev.parent_ids), 
413
                             len(bundle_rev.parent_ids))
1185.82.47 by Aaron Bentley
Ensure all intended rev_ids end up in the revision
414
        self.assertEqual(rev_ids, 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
415
                         [r.revision_id for r in bundle.real_revisions])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
416
        self.valid_apply_bundle(base_rev_id, bundle,
1185.82.89 by Aaron Bentley
Remove auto_commit stuff
417
                                   checkout_dir=checkout_dir)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
418
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
419
        return bundle
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
420
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
421
    def get_invalid_bundle(self, base_rev_id, rev_id):
422
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
423
        Munge the text so that it's invalid.
424
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
425
        :return: The in-memory bundle
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
426
        """
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
427
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
428
        new_text = bundle_txt.getvalue().replace('executable:no', 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
429
                                               'executable:yes')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
430
        bundle_txt = StringIO(new_text)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
431
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
432
        self.valid_apply_bundle(base_rev_id, bundle)
433
        return bundle 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
434
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
435
    def test_non_bundle(self):
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
436
        self.assertRaises(errors.NotABundle,
437
                          read_bundle, StringIO('#!/bin/sh\n'))
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
438
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
439
    def test_malformed(self):
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
440
        self.assertRaises(errors.BadBundle, read_bundle,
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
441
                          StringIO('# Bazaar revision bundle v'))
442
443
    def test_crlf_bundle(self):
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
444
        try:
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
445
            read_bundle(StringIO('# Bazaar revision bundle v0.8\r\n'))
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
446
        except errors.BadBundle:
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
447
            # It is currently permitted for bundles with crlf line endings to
448
            # make read_bundle raise a BadBundle, but this should be fixed.
1793.2.10 by Aaron Bentley
Whitespace/comment fix
449
            # Anything else, especially NotABundle, is an error.
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
450
            pass
451
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
452
    def get_checkout(self, rev_id, checkout_dir=None):
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
453
        """Get a new tree, with the specified revision in it.
454
        """
455
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
456
        if checkout_dir is None:
3638.3.2 by Vincent Ladeuil
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.
457
            checkout_dir = osutils.mkdtemp(prefix='test-branch-', dir='.')
0.5.89 by John Arbash Meinel
Updating for explicitly defined directories.
458
        else:
459
            if not os.path.exists(checkout_dir):
460
                os.mkdir(checkout_dir)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
461
        tree = self.make_branch_and_tree(checkout_dir)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
462
        s = StringIO()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
463
        ancestors = write_bundle(self.b1.repository, rev_id, 'null:', s,
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
464
                                 format=self.format)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
465
        s.seek(0)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
466
        self.assertIsInstance(s.getvalue(), str)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
467
        install_bundle(tree.branch.repository, read_bundle(s))
1185.82.41 by Aaron Bentley
More work on installing changesets
468
        for ancestor in ancestors:
469
            old = self.b1.repository.revision_tree(ancestor)
470
            new = tree.branch.repository.revision_tree(ancestor)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
471
            old.lock_read()
472
            new.lock_read()
473
            try:
474
                # Check that there aren't any inventory level changes
475
                delta = new.changes_from(old)
476
                self.assertFalse(delta.has_changed(),
477
                                 'Revision %s not copied correctly.'
478
                                 % (ancestor,))
479
480
                # Now check that the file contents are all correct
481
                for inventory_id in old:
482
                    try:
483
                        old_file = old.get_file(inventory_id)
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
484
                    except errors.NoSuchFile:
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
485
                        continue
486
                    if old_file is None:
487
                        continue
488
                    self.assertEqual(old_file.read(),
489
                                     new.get_file(inventory_id).read())
490
            finally:
491
                new.unlock()
492
                old.unlock()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
493
        if not _mod_revision.is_null(rev_id):
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
494
            rh = self.b1.revision_history()
495
            tree.branch.set_revision_history(rh[:rh.index(rev_id)+1])
496
            tree.update()
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
497
            delta = tree.changes_from(self.b1.repository.revision_tree(rev_id))
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
498
            self.assertFalse(delta.has_changed(),
2255.10.5 by John Arbash Meinel
Fix a small bug when we have a symlink that does not need to be re-read.
499
                             'Working tree has modifications: %s' % delta)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
500
        return tree
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
501
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
502
    def valid_apply_bundle(self, base_rev_id, info, checkout_dir=None):
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
503
        """Get the base revision, apply the changes, and make
504
        sure everything matches the builtin branch.
505
        """
1185.82.17 by Aaron Bentley
More API updates
506
        to_tree = self.get_checkout(base_rev_id, checkout_dir=checkout_dir)
3146.4.11 by Aaron Bentley
Fix lock errors in bundle tests
507
        to_tree.lock_write()
508
        try:
509
            self._valid_apply_bundle(base_rev_id, info, to_tree)
510
        finally:
511
            to_tree.unlock()
512
513
    def _valid_apply_bundle(self, base_rev_id, info, to_tree):
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
514
        original_parents = to_tree.get_parent_ids()
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
515
        repository = to_tree.branch.repository
1927.2.1 by Robert Collins
Alter set_pending_merges to shove the left most merge into the trees last-revision if that is not set. Related bugfixes include basis_tree handling ghosts, de-duping the merges with the last-revision and update changing where and how it adds its pending merge.
516
        original_parents = to_tree.get_parent_ids()
1185.82.41 by Aaron Bentley
More work on installing changesets
517
        self.assertIs(repository.has_revision(base_rev_id), True)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
518
        for rev in info.real_revisions:
519
            self.assert_(not repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
520
                'Revision {%s} present before applying bundle' 
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
521
                % rev.revision_id)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
522
        merge_bundle(info, to_tree, True, Merge3Merger, False, False)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
523
524
        for rev in info.real_revisions:
1185.82.17 by Aaron Bentley
More API updates
525
            self.assert_(repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
526
                'Missing revision {%s} after applying bundle' 
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
527
                % rev.revision_id)
528
1185.82.17 by Aaron Bentley
More API updates
529
        self.assert_(to_tree.branch.repository.has_revision(info.target))
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
530
        # Do we also want to verify that all the texts have been added?
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
531
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
532
        self.assertEqual(original_parents + [info.target],
533
            to_tree.get_parent_ids())
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
534
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
535
        rev = info.real_revisions[-1]
1185.82.17 by Aaron Bentley
More API updates
536
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
537
        to_tree = to_tree.branch.repository.revision_tree(rev.revision_id)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
538
        
539
        # TODO: make sure the target tree is identical to base tree
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
540
        #       we might also check the working tree.
541
542
        base_files = list(base_tree.list_files())
543
        to_files = list(to_tree.list_files())
544
        self.assertEqual(len(base_files), len(to_files))
1185.82.66 by Aaron Bentley
Handle new executable files
545
        for base_file, to_file in zip(base_files, to_files):
546
            self.assertEqual(base_file, to_file)
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
547
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
548
        for path, status, kind, fileid, entry in base_files:
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
549
            # Check that the meta information is the same
550
            self.assertEqual(base_tree.get_file_size(fileid),
551
                    to_tree.get_file_size(fileid))
552
            self.assertEqual(base_tree.get_file_sha1(fileid),
553
                    to_tree.get_file_sha1(fileid))
554
            # Check that the contents are the same
555
            # This is pretty expensive
556
            # self.assertEqual(base_tree.get_file(fileid).read(),
557
            #         to_tree.get_file(fileid).read())
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
558
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
559
    def test_bundle(self):
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
560
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.14 by Aaron Bentley
API updates
561
        self.b1 = self.tree1.branch
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
562
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
563
        open('b1/one', 'wb').write('one\n')
1185.82.14 by Aaron Bentley
API updates
564
        self.tree1.add('one')
565
        self.tree1.commit('add one', rev_id='a@cset-0-1')
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
566
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
567
        bundle = self.get_valid_bundle('null:', 'a@cset-0-1')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
568
569
        # Make sure we can handle files with spaces, tabs, other
570
        # bogus characters
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
571
        self.build_tree([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
572
                'b1/with space.txt'
573
                , 'b1/dir/'
574
                , 'b1/dir/filein subdir.c'
575
                , 'b1/dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
576
                , 'b1/dir/ pre space'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
577
                , 'b1/sub/'
578
                , 'b1/sub/sub/'
579
                , 'b1/sub/sub/nonempty.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
580
                ])
0.5.84 by John Arbash Meinel
(broken) problem with removes.
581
        open('b1/sub/sub/emptyfile.txt', 'wb').close()
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
582
        open('b1/dir/nolastnewline.txt', 'wb').write('bloop')
1185.82.66 by Aaron Bentley
Handle new executable files
583
        tt = TreeTransform(self.tree1)
584
        tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
585
        tt.apply()
2520.4.84 by Aaron Bentley
Fix heisenbug record-rewriting test
586
        # have to fix length of file-id so that we can predictably rewrite
587
        # a (length-prefixed) record containing it later.
588
        self.tree1.add('with space.txt', 'withspace-id')
1185.82.14 by Aaron Bentley
API updates
589
        self.tree1.add([
2520.4.84 by Aaron Bentley
Fix heisenbug record-rewriting test
590
                  'dir'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
591
                , 'dir/filein subdir.c'
592
                , 'dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
593
                , 'dir/ pre space'
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
594
                , 'dir/nolastnewline.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
595
                , 'sub'
596
                , 'sub/sub'
597
                , 'sub/sub/nonempty.txt'
598
                , 'sub/sub/emptyfile.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
599
                ])
1185.82.14 by Aaron Bentley
API updates
600
        self.tree1.commit('add whitespace', rev_id='a@cset-0-2')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
601
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
602
        bundle = self.get_valid_bundle('a@cset-0-1', 'a@cset-0-2')
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
603
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
604
        # Check a rollup bundle 
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
605
        bundle = self.get_valid_bundle('null:', 'a@cset-0-2')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
606
607
        # Now delete entries
1185.82.21 by Aaron Bentley
Stop using deprecated function
608
        self.tree1.remove(
0.5.118 by John Arbash Meinel
Got most of test_changeset to work. Still needs work for Aaron's test code.
609
                ['sub/sub/nonempty.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
610
                , 'sub/sub/emptyfile.txt'
0.5.118 by John Arbash Meinel
Got most of test_changeset to work. Still needs work for Aaron's test code.
611
                , 'sub/sub'
612
                ])
1185.82.68 by Aaron Bentley
Handle execute bit on modified files
613
        tt = TreeTransform(self.tree1)
614
        trans_id = tt.trans_id_tree_file_id('exe-1')
615
        tt.set_executability(False, trans_id)
616
        tt.apply()
1185.82.19 by Aaron Bentley
More API updates
617
        self.tree1.commit('removed', rev_id='a@cset-0-3')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
618
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
619
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
620
        self.assertRaises((errors.TestamentMismatch,
2520.4.71 by Aaron Bentley
Update test to accept VersionedFileInvalidChecksum instead of TestamentMismatch
621
            errors.VersionedFileInvalidChecksum), self.get_invalid_bundle,
622
            'a@cset-0-2', 'a@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
623
        # Check a rollup bundle 
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
624
        bundle = self.get_valid_bundle('null:', 'a@cset-0-3')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
625
626
        # Now move the directory
1185.82.19 by Aaron Bentley
More API updates
627
        self.tree1.rename_one('dir', 'sub/dir')
628
        self.tree1.commit('rename dir', rev_id='a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
629
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
630
        bundle = self.get_valid_bundle('a@cset-0-3', 'a@cset-0-4')
631
        # Check a rollup bundle 
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
632
        bundle = self.get_valid_bundle('null:', 'a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
633
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
634
        # Modified files
635
        open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
2520.4.83 by Aaron Bentley
Clean up tests
636
        open('b1/sub/dir/ pre space', 'ab').write(
637
             '\r\nAdding some\r\nDOS format lines\r\n')
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
638
        open('b1/sub/dir/nolastnewline.txt', 'ab').write('\n')
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
639
        self.tree1.rename_one('sub/dir/ pre space', 
640
                              'sub/ start space')
1185.82.19 by Aaron Bentley
More API updates
641
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
642
        bundle = self.get_valid_bundle('a@cset-0-4', 'a@cset-0-5')
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
643
1185.82.70 by Aaron Bentley
Handle renamed files better
644
        self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
645
        self.tree1.rename_one('with space.txt', 'WithCaps.txt')
646
        self.tree1.rename_one('temp', 'with space.txt')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
647
        self.tree1.commit(u'swap filenames', rev_id='a@cset-0-6',
648
                          verbose=False)
649
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
650
        other = self.get_checkout('a@cset-0-5')
1910.2.62 by Aaron Bentley
Cleanups
651
        tree1_inv = self.tree1.branch.repository.get_inventory_xml(
652
            'a@cset-0-5')
1910.2.54 by Aaron Bentley
Implement testament format 3 strict
653
        tree2_inv = other.branch.repository.get_inventory_xml('a@cset-0-5')
654
        self.assertEqualDiff(tree1_inv, tree2_inv)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
655
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
656
        other.commit('rename file', rev_id='a@cset-0-6b')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
657
        self.tree1.merge_from_branch(other.branch)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
658
        self.tree1.commit(u'Merge', rev_id='a@cset-0-7',
1185.82.70 by Aaron Bentley
Handle renamed files better
659
                          verbose=False)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
660
        bundle = self.get_valid_bundle('a@cset-0-6', 'a@cset-0-7')
1185.82.72 by Aaron Bentley
Always use leftmost base for changesets
661
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
662
    def test_symlink_bundle(self):
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
663
        self.requireFeature(SymlinkFeature)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
664
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.87 by Aaron Bentley
Got symlink adding working
665
        self.b1 = self.tree1.branch
666
        tt = TreeTransform(self.tree1)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
667
        tt.new_symlink('link', tt.root, 'bar/foo', 'link-1')
1185.82.87 by Aaron Bentley
Got symlink adding working
668
        tt.apply()
669
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
670
        self.get_valid_bundle('null:', 'l@cset-0-1')
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
671
        tt = TreeTransform(self.tree1)
672
        trans_id = tt.trans_id_tree_file_id('link-1')
673
        tt.adjust_path('link2', tt.root, trans_id)
674
        tt.delete_contents(trans_id)
675
        tt.create_symlink('mars', trans_id)
676
        tt.apply()
677
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
678
        self.get_valid_bundle('l@cset-0-1', 'l@cset-0-2')
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
679
        tt = TreeTransform(self.tree1)
680
        trans_id = tt.trans_id_tree_file_id('link-1')
681
        tt.delete_contents(trans_id)
682
        tt.create_symlink('jupiter', trans_id)
683
        tt.apply()
684
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
685
        self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
686
        tt = TreeTransform(self.tree1)
687
        trans_id = tt.trans_id_tree_file_id('link-1')
688
        tt.delete_contents(trans_id)
689
        tt.apply()
690
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
691
        self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
1185.82.96 by Aaron Bentley
Got first binary test passing
692
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
693
    def test_binary_bundle(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
694
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.96 by Aaron Bentley
Got first binary test passing
695
        self.b1 = self.tree1.branch
696
        tt = TreeTransform(self.tree1)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
697
        
698
        # Add
699
        tt.new_file('file', tt.root, '\x00\n\x00\r\x01\n\x02\r\xff', 'binary-1')
2520.4.83 by Aaron Bentley
Clean up tests
700
        tt.new_file('file2', tt.root, '\x01\n\x02\r\x03\n\x04\r\xff',
701
            'binary-2')
1185.82.96 by Aaron Bentley
Got first binary test passing
702
        tt.apply()
703
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
704
        self.get_valid_bundle('null:', 'b@cset-0-1')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
705
706
        # Delete
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
707
        tt = TreeTransform(self.tree1)
708
        trans_id = tt.trans_id_tree_file_id('binary-1')
709
        tt.delete_contents(trans_id)
710
        tt.apply()
711
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
712
        self.get_valid_bundle('b@cset-0-1', 'b@cset-0-2')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
713
714
        # Rename & modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
715
        tt = TreeTransform(self.tree1)
716
        trans_id = tt.trans_id_tree_file_id('binary-2')
717
        tt.adjust_path('file3', tt.root, trans_id)
718
        tt.delete_contents(trans_id)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
719
        tt.create_file('file\rcontents\x00\n\x00', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
720
        tt.apply()
721
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
722
        self.get_valid_bundle('b@cset-0-2', 'b@cset-0-3')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
723
724
        # Modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
725
        tt = TreeTransform(self.tree1)
726
        trans_id = tt.trans_id_tree_file_id('binary-2')
727
        tt.delete_contents(trans_id)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
728
        tt.create_file('\x00file\rcontents', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
729
        tt.apply()
730
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
731
        self.get_valid_bundle('b@cset-0-3', 'b@cset-0-4')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
732
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
733
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
734
        self.get_valid_bundle('null:', 'b@cset-0-4')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
735
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
736
    def test_last_modified(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
737
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
738
        self.b1 = self.tree1.branch
739
        tt = TreeTransform(self.tree1)
740
        tt.new_file('file', tt.root, 'file', 'file')
741
        tt.apply()
742
        self.tree1.commit('create file', rev_id='a@lmod-0-1')
743
744
        tt = TreeTransform(self.tree1)
745
        trans_id = tt.trans_id_tree_file_id('file')
746
        tt.delete_contents(trans_id)
747
        tt.create_file('file2', trans_id)
748
        tt.apply()
749
        self.tree1.commit('modify text', rev_id='a@lmod-0-2a')
750
751
        other = self.get_checkout('a@lmod-0-1')
752
        tt = TreeTransform(other)
753
        trans_id = tt.trans_id_tree_file_id('file')
754
        tt.delete_contents(trans_id)
755
        tt.create_file('file2', trans_id)
756
        tt.apply()
757
        other.commit('modify text in another tree', rev_id='a@lmod-0-2b')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
758
        self.tree1.merge_from_branch(other.branch)
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
759
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
760
                          verbose=False)
761
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
762
        bundle = self.get_valid_bundle('a@lmod-0-2a', 'a@lmod-0-4')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
763
764
    def test_hide_history(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
765
        self.tree1 = self.make_branch_and_tree('b1')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
766
        self.b1 = self.tree1.branch
767
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
768
        open('b1/one', 'wb').write('one\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
769
        self.tree1.add('one')
770
        self.tree1.commit('add file', rev_id='a@cset-0-1')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
771
        open('b1/one', 'wb').write('two\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
772
        self.tree1.commit('modify', rev_id='a@cset-0-2')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
773
        open('b1/one', 'wb').write('three\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
774
        self.tree1.commit('modify', rev_id='a@cset-0-3')
775
        bundle_file = StringIO()
776
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
777
                               'a@cset-0-1', bundle_file, format=self.format)
2382.1.1 by Ian Clatworthy
Fixes #98510 - bundle selftest fails if email has 'two' embedded
778
        self.assertNotContainsRe(bundle_file.getvalue(), '\btwo\b')
2520.4.32 by Aaron Bentley
Fix test case
779
        self.assertContainsRe(self.get_raw(bundle_file), 'one')
780
        self.assertContainsRe(self.get_raw(bundle_file), 'three')
781
2520.4.75 by Aaron Bentley
Fix traceback on empty bundles.
782
    def test_bundle_same_basis(self):
783
        """Ensure using the basis as the target doesn't cause an error"""
784
        self.tree1 = self.make_branch_and_tree('b1')
785
        self.tree1.commit('add file', rev_id='a@cset-0-1')
786
        bundle_file = StringIO()
787
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-1',
788
                               'a@cset-0-1', bundle_file)
789
2520.4.32 by Aaron Bentley
Fix test case
790
    @staticmethod
791
    def get_raw(bundle_file):
792
        return bundle_file.getvalue()
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
793
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
794
    def test_unicode_bundle(self):
795
        # Handle international characters
796
        os.mkdir('b1')
797
        try:
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
798
            f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
799
        except UnicodeEncodeError:
800
            raise TestSkipped("Filesystem doesn't support unicode")
801
802
        self.tree1 = self.make_branch_and_tree('b1')
803
        self.b1 = self.tree1.branch
804
805
        f.write((u'A file\n'
806
            u'With international man of mystery\n'
807
            u'William Dod\xe9\n').encode('utf-8'))
808
        f.close()
809
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
810
        self.tree1.add([u'with Dod\N{Euro Sign}'], ['withdod-id'])
2386.1.1 by John Arbash Meinel
Update test_unicode_bundle, since we know how it fails on Mac OSX
811
        self.tree1.commit(u'i18n commit from William Dod\xe9',
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
812
                          rev_id='i18n-1', committer=u'William Dod\xe9')
813
814
        # Add
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
815
        bundle = self.get_valid_bundle('null:', 'i18n-1')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
816
817
        # Modified
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
818
        f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
819
        f.write(u'Modified \xb5\n'.encode('utf8'))
820
        f.close()
821
        self.tree1.commit(u'modified', rev_id='i18n-2')
822
823
        bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
824
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
825
        # Renamed
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
826
        self.tree1.rename_one(u'with Dod\N{Euro Sign}', u'B\N{Euro Sign}gfors')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
827
        self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
828
                          committer=u'Erik B\xe5gfors')
829
830
        bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
831
832
        # Removed
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
833
        self.tree1.remove([u'B\N{Euro Sign}gfors'])
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
834
        self.tree1.commit(u'removed', rev_id='i18n-4')
835
836
        bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
837
838
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
839
        bundle = self.get_valid_bundle('null:', 'i18n-4')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
840
841
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
842
    def test_whitespace_bundle(self):
843
        if sys.platform in ('win32', 'cygwin'):
844
            raise TestSkipped('Windows doesn\'t support filenames'
845
                              ' with tabs or trailing spaces')
846
        self.tree1 = self.make_branch_and_tree('b1')
847
        self.b1 = self.tree1.branch
848
849
        self.build_tree(['b1/trailing space '])
850
        self.tree1.add(['trailing space '])
851
        # TODO: jam 20060701 Check for handling files with '\t' characters
852
        #       once we actually support them
853
854
        # Added
855
        self.tree1.commit('funky whitespace', rev_id='white-1')
856
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
857
        bundle = self.get_valid_bundle('null:', 'white-1')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
858
859
        # Modified
860
        open('b1/trailing space ', 'ab').write('add some text\n')
861
        self.tree1.commit('add text', rev_id='white-2')
862
863
        bundle = self.get_valid_bundle('white-1', 'white-2')
864
865
        # Renamed
866
        self.tree1.rename_one('trailing space ', ' start and end space ')
867
        self.tree1.commit('rename', rev_id='white-3')
868
869
        bundle = self.get_valid_bundle('white-2', 'white-3')
870
871
        # Removed
872
        self.tree1.remove([' start and end space '])
873
        self.tree1.commit('removed', rev_id='white-4')
874
875
        bundle = self.get_valid_bundle('white-3', 'white-4')
876
        
877
        # Now test a complet roll-up
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
878
        bundle = self.get_valid_bundle('null:', 'white-4')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
879
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
880
    def test_alt_timezone_bundle(self):
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
881
        self.tree1 = self.make_branch_and_memory_tree('b1')
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
882
        self.b1 = self.tree1.branch
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
883
        builder = treebuilder.TreeBuilder()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
884
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
885
        self.tree1.lock_write()
886
        builder.start_tree(self.tree1)
887
        builder.build(['newfile'])
888
        builder.finish_tree()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
889
890
        # Asia/Colombo offset = 5 hours 30 minutes
891
        self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
892
                          timezone=19800, timestamp=1152544886.0)
893
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
894
        bundle = self.get_valid_bundle('null:', 'tz-1')
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
895
        
896
        rev = bundle.revisions[0]
897
        self.assertEqual('Mon 2006-07-10 20:51:26.000000000 +0530', rev.date)
898
        self.assertEqual(19800, rev.timezone)
899
        self.assertEqual(1152544886.0, rev.timestamp)
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
900
        self.tree1.unlock()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
901
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
902
    def test_bundle_root_id(self):
903
        self.tree1 = self.make_branch_and_tree('b1')
904
        self.b1 = self.tree1.branch
905
        self.tree1.commit('message', rev_id='revid1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
906
        bundle = self.get_valid_bundle('null:', 'revid1')
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
907
        tree = self.get_bundle_tree(bundle, 'revid1')
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
908
        self.assertEqual('revid1', tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
909
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
910
    def test_install_revisions(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
911
        self.tree1 = self.make_branch_and_tree('b1')
912
        self.b1 = self.tree1.branch
913
        self.tree1.commit('message', rev_id='rev2a')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
914
        bundle = self.get_valid_bundle('null:', 'rev2a')
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
915
        branch2 = self.make_branch('b2')
916
        self.assertFalse(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
917
        target_revision = bundle.install_revisions(branch2.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
918
        self.assertTrue(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
919
        self.assertEqual('rev2a', target_revision)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
920
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
921
    def test_bundle_empty_property(self):
922
        """Test serializing revision properties with an empty value."""
923
        tree = self.make_branch_and_memory_tree('tree')
924
        tree.lock_write()
925
        self.addCleanup(tree.unlock)
926
        tree.add([''], ['TREE_ROOT'])
927
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
928
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
929
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
930
        bundle = read_bundle(bundle_sio)
931
        revision_info = bundle.revisions[0]
932
        self.assertEqual('rev1', revision_info.revision_id)
933
        rev = revision_info.as_revision()
934
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
935
                         rev.properties)
936
937
    def test_bundle_sorted_properties(self):
938
        """For stability the writer should write properties in sorted order."""
939
        tree = self.make_branch_and_memory_tree('tree')
940
        tree.lock_write()
941
        self.addCleanup(tree.unlock)
942
943
        tree.add([''], ['TREE_ROOT'])
944
        tree.commit('One', rev_id='rev1',
945
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
946
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
947
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
948
        bundle = read_bundle(bundle_sio)
949
        revision_info = bundle.revisions[0]
950
        self.assertEqual('rev1', revision_info.revision_id)
951
        rev = revision_info.as_revision()
952
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
953
                          'd':'1'}, rev.properties)
954
955
    def test_bundle_unicode_properties(self):
956
        """We should be able to round trip a non-ascii property."""
957
        tree = self.make_branch_and_memory_tree('tree')
958
        tree.lock_write()
959
        self.addCleanup(tree.unlock)
960
961
        tree.add([''], ['TREE_ROOT'])
962
        # Revisions themselves do not require anything about revision property
963
        # keys, other than that they are a basestring, and do not contain
964
        # whitespace.
965
        # However, Testaments assert than they are str(), and thus should not
966
        # be Unicode.
967
        tree.commit('One', rev_id='rev1',
968
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
969
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
970
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
971
        bundle = read_bundle(bundle_sio)
972
        revision_info = bundle.revisions[0]
973
        self.assertEqual('rev1', revision_info.revision_id)
974
        rev = revision_info.as_revision()
975
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
976
                          'alpha':u'\u03b1'}, rev.properties)
977
2520.4.43 by Aaron Bentley
Fix test suite
978
    def test_bundle_with_ghosts(self):
979
        tree = self.make_branch_and_tree('tree')
980
        self.b1 = tree.branch
981
        self.build_tree_contents([('tree/file', 'content1')])
982
        tree.add(['file'])
983
        tree.commit('rev1')
984
        self.build_tree_contents([('tree/file', 'content2')])
985
        tree.add_parent_tree_id('ghost')
986
        tree.commit('rev2', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
987
        bundle = self.get_valid_bundle('null:', 'rev2')
2520.4.43 by Aaron Bentley
Fix test suite
988
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
989
    def make_simple_tree(self, format=None):
990
        tree = self.make_branch_and_tree('b1', format=format)
991
        self.b1 = tree.branch
992
        self.build_tree(['b1/file'])
993
        tree.add('file')
994
        return tree
995
996
    def test_across_serializers(self):
997
        tree = self.make_simple_tree('knit')
998
        tree.commit('hello', rev_id='rev1')
2520.4.98 by Aaron Bentley
Support inventory conversion with parents
999
        tree.commit('hello', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1000
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1001
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1002
        bundle.install_revisions(repo)
2520.4.98 by Aaron Bentley
Support inventory conversion with parents
1003
        inv_text = repo.get_inventory_xml('rev2')
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1004
        self.assertNotContainsRe(inv_text, 'format="5"')
2520.4.99 by Aaron Bentley
Test conversion across models
1005
        self.assertContainsRe(inv_text, 'format="7"')
1006
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1007
    def make_repo_with_installed_revisions(self):
1008
        tree = self.make_simple_tree('knit')
1009
        tree.commit('hello', rev_id='rev1')
1010
        tree.commit('hello', rev_id='rev2')
1011
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
1012
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1013
        bundle.install_revisions(repo)
1014
        return repo
1015
2520.4.99 by Aaron Bentley
Test conversion across models
1016
    def test_across_models(self):
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1017
        repo = self.make_repo_with_installed_revisions()
3380.1.12 by Aaron Bentley
fix test
1018
        inv = repo.get_inventory('rev2')
2520.4.99 by Aaron Bentley
Test conversion across models
1019
        self.assertEqual('rev2', inv.root.revision)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1020
        root_id = inv.root.file_id
1021
        repo.lock_read()
1022
        self.addCleanup(repo.unlock)
1023
        self.assertEqual({(root_id, 'rev1'):(),
1024
            (root_id, 'rev2'):((root_id, 'rev1'),)},
1025
            repo.texts.get_parent_map([(root_id, 'rev1'), (root_id, 'rev2')]))
2520.4.99 by Aaron Bentley
Test conversion across models
1026
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1027
    def test_inv_hash_across_serializers(self):
1028
        repo = self.make_repo_with_installed_revisions()
1029
        recorded_inv_sha1 = repo.get_inventory_sha1('rev2')
1030
        xml = repo.get_inventory_xml('rev2')
1031
        self.assertEqual(sha_string(xml), recorded_inv_sha1)
1032
2520.4.99 by Aaron Bentley
Test conversion across models
1033
    def test_across_models_incompatible(self):
1034
        tree = self.make_simple_tree('dirstate-with-subtree')
1035
        tree.commit('hello', rev_id='rev1')
1036
        tree.commit('hello', rev_id='rev2')
1037
        try:
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1038
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.4.99 by Aaron Bentley
Test conversion across models
1039
        except errors.IncompatibleBundleFormat:
1040
            raise TestSkipped("Format 0.8 doesn't work with knit3")
1041
        repo = self.make_repository('repo', format='knit')
1042
        bundle.install_revisions(repo)
1043
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1044
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
2520.4.99 by Aaron Bentley
Test conversion across models
1045
        self.assertRaises(errors.IncompatibleRevision,
1046
                          bundle.install_revisions, repo)
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1047
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
1048
    def test_get_merge_request(self):
1049
        tree = self.make_simple_tree()
1050
        tree.commit('hello', rev_id='rev1')
1051
        tree.commit('hello', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1052
        bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
1053
        result = bundle.get_merge_request(tree.branch.repository)
1054
        self.assertEqual((None, 'rev1', 'inapplicable'), result)
1055
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1056
    def test_with_subtree(self):
1057
        tree = self.make_branch_and_tree('tree',
1058
                                         format='dirstate-with-subtree')
1059
        self.b1 = tree.branch
1060
        subtree = self.make_branch_and_tree('tree/subtree',
1061
                                            format='dirstate-with-subtree')
1062
        tree.add('subtree')
1063
        tree.commit('hello', rev_id='rev1')
1064
        try:
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1065
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1066
        except errors.IncompatibleBundleFormat:
1067
            raise TestSkipped("Format 0.8 doesn't work with knit3")
1068
        if isinstance(bundle, v09.BundleInfo09):
1069
            raise TestSkipped("Format 0.9 doesn't work with subtrees")
1070
        repo = self.make_repository('repo', format='knit')
1071
        self.assertRaises(errors.IncompatibleRevision,
1072
                          bundle.install_revisions, repo)
1073
        repo2 = self.make_repository('repo2', format='dirstate-with-subtree')
1074
        bundle.install_revisions(repo2)
1075
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1076
    def test_revision_id_with_slash(self):
1077
        self.tree1 = self.make_branch_and_tree('tree')
1078
        self.b1 = self.tree1.branch
1079
        try:
1080
            self.tree1.commit('Revision/id/with/slashes', rev_id='rev/id')
1081
        except ValueError:
1082
            raise TestSkipped("Repository doesn't support revision ids with"
1083
                              " slashes")
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1084
        bundle = self.get_valid_bundle('null:', 'rev/id')
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1085
2520.6.2 by Aaron Bentley
Fix bundle installation wrong-versionedfile bug
1086
    def test_skip_file(self):
1087
        """Make sure we don't accidentally write to the wrong versionedfile"""
1088
        self.tree1 = self.make_branch_and_tree('tree')
1089
        self.b1 = self.tree1.branch
1090
        # rev1 is not present in bundle, done by fetch
1091
        self.build_tree_contents([('tree/file2', 'contents1')])
1092
        self.tree1.add('file2', 'file2-id')
1093
        self.tree1.commit('rev1', rev_id='reva')
1094
        self.build_tree_contents([('tree/file3', 'contents2')])
1095
        # rev2 is present in bundle, and done by fetch
1096
        # having file1 in the bunle causes file1's versionedfile to be opened.
1097
        self.tree1.add('file3', 'file3-id')
1098
        self.tree1.commit('rev2')
1099
        # Updating file2 should not cause an attempt to add to file1's vf
1100
        target = self.tree1.bzrdir.sprout('target').open_workingtree()
1101
        self.build_tree_contents([('tree/file2', 'contents3')])
1102
        self.tree1.commit('rev3', rev_id='rev3')
1103
        bundle = self.get_valid_bundle('reva', 'rev3')
2520.6.5 by Aaron Bentley
Skip for bundle formats that don't provide get_bundle_reader
1104
        if getattr(bundle, 'get_bundle_reader', None) is None:
1105
            raise TestSkipped('Bundle format cannot provide reader')
2520.6.2 by Aaron Bentley
Fix bundle installation wrong-versionedfile bug
1106
        # be sure that file1 comes before file2
1107
        for b, m, k, r, f in bundle.get_bundle_reader().iter_records():
1108
            if f == 'file3-id':
1109
                break
1110
            self.assertNotEqual(f, 'file2-id')
1111
        bundle.install_revisions(target.branch.repository)
1112
2520.4.43 by Aaron Bentley
Fix test suite
1113
1114
class V08BundleTester(BundleTester, TestCaseWithTransport):
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
1115
1116
    format = '0.8'
1117
1118
    def test_bundle_empty_property(self):
1119
        """Test serializing revision properties with an empty value."""
1120
        tree = self.make_branch_and_memory_tree('tree')
1121
        tree.lock_write()
1122
        self.addCleanup(tree.unlock)
1123
        tree.add([''], ['TREE_ROOT'])
1124
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1125
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1126
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1127
        self.assertContainsRe(bundle_sio.getvalue(),
1128
                              '# properties:\n'
1129
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1130
                              '#   empty: \n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1131
                              '#   one: two\n'
1132
                             )
1133
        bundle = read_bundle(bundle_sio)
1134
        revision_info = bundle.revisions[0]
1135
        self.assertEqual('rev1', revision_info.revision_id)
1136
        rev = revision_info.as_revision()
1137
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
1138
                         rev.properties)
1139
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1140
    def get_bundle_tree(self, bundle, revision_id):
1141
        repository = self.make_repository('repo')
1142
        return bundle.revision_tree(repository, 'revid1')
1143
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1144
    def test_bundle_empty_property_alt(self):
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1145
        """Test serializing revision properties with an empty value.
1146
1147
        Older readers had a bug when reading an empty property.
1148
        They assumed that all keys ended in ': \n'. However they would write an
1149
        empty value as ':\n'. This tests make sure that all newer bzr versions
1150
        can handle th second form.
1151
        """
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1152
        tree = self.make_branch_and_memory_tree('tree')
1153
        tree.lock_write()
1154
        self.addCleanup(tree.unlock)
1155
        tree.add([''], ['TREE_ROOT'])
1156
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1157
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1158
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1159
        txt = bundle_sio.getvalue()
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1160
        loc = txt.find('#   empty: ') + len('#   empty:')
1161
        # Create a new bundle, which strips the trailing space after empty
1162
        bundle_sio = StringIO(txt[:loc] + txt[loc+1:])
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1163
1164
        self.assertContainsRe(bundle_sio.getvalue(),
1165
                              '# properties:\n'
1166
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1167
                              '#   empty:\n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1168
                              '#   one: two\n'
1169
                             )
1170
        bundle = read_bundle(bundle_sio)
1171
        revision_info = bundle.revisions[0]
1172
        self.assertEqual('rev1', revision_info.revision_id)
1173
        rev = revision_info.as_revision()
1174
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
1175
                         rev.properties)
1176
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1177
    def test_bundle_sorted_properties(self):
1178
        """For stability the writer should write properties in sorted order."""
1179
        tree = self.make_branch_and_memory_tree('tree')
1180
        tree.lock_write()
1181
        self.addCleanup(tree.unlock)
1182
1183
        tree.add([''], ['TREE_ROOT'])
1184
        tree.commit('One', rev_id='rev1',
1185
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
1186
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1187
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1188
        self.assertContainsRe(bundle_sio.getvalue(),
1189
                              '# properties:\n'
1190
                              '#   a: 4\n'
1191
                              '#   b: 3\n'
1192
                              '#   branch-nick: tree\n'
1193
                              '#   c: 2\n'
1194
                              '#   d: 1\n'
1195
                             )
2447.1.4 by John Arbash Meinel
Add a test that we properly round-trip unicode properties.
1196
        bundle = read_bundle(bundle_sio)
1197
        revision_info = bundle.revisions[0]
1198
        self.assertEqual('rev1', revision_info.revision_id)
1199
        rev = revision_info.as_revision()
1200
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
1201
                          'd':'1'}, rev.properties)
1202
1203
    def test_bundle_unicode_properties(self):
1204
        """We should be able to round trip a non-ascii property."""
1205
        tree = self.make_branch_and_memory_tree('tree')
1206
        tree.lock_write()
1207
        self.addCleanup(tree.unlock)
1208
1209
        tree.add([''], ['TREE_ROOT'])
1210
        # Revisions themselves do not require anything about revision property
1211
        # keys, other than that they are a basestring, and do not contain
1212
        # whitespace.
1213
        # However, Testaments assert than they are str(), and thus should not
1214
        # be Unicode.
1215
        tree.commit('One', rev_id='rev1',
1216
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
1217
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1218
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.4 by John Arbash Meinel
Add a test that we properly round-trip unicode properties.
1219
        self.assertContainsRe(bundle_sio.getvalue(),
1220
                              '# properties:\n'
1221
                              '#   alpha: \xce\xb1\n'
1222
                              '#   branch-nick: tree\n'
1223
                              '#   omega: \xce\xa9\n'
1224
                             )
1225
        bundle = read_bundle(bundle_sio)
1226
        revision_info = bundle.revisions[0]
1227
        self.assertEqual('rev1', revision_info.revision_id)
1228
        rev = revision_info.as_revision()
1229
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
1230
                          'alpha':u'\u03b1'}, rev.properties)
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1231
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1232
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1233
class V09BundleKnit2Tester(V08BundleTester):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1234
1235
    format = '0.9'
1236
1237
    def bzrdir_format(self):
1238
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
1239
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1240
        return format
1241
1242
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1243
class V09BundleKnit1Tester(V08BundleTester):
1244
1245
    format = '0.9'
1246
1247
    def bzrdir_format(self):
1248
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1249
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1250
        return format
1251
1252
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1253
class V4BundleTester(BundleTester, TestCaseWithTransport):
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1254
2520.4.136 by Aaron Bentley
Fix format strings
1255
    format = '4'
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1256
1257
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
1258
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1259
        Make sure that the text generated is valid, and that it
1260
        can be applied against the base, and generate the same information.
1261
        
1262
        :return: The in-memory bundle 
1263
        """
1264
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1265
1266
        # This should also validate the generated bundle 
1267
        bundle = read_bundle(bundle_txt)
1268
        repository = self.b1.repository
1269
        for bundle_rev in bundle.real_revisions:
1270
            # These really should have already been checked when we read the
1271
            # bundle, since it computes the sha1 hash for the revision, which
1272
            # only will match if everything is okay, but lets be explicit about
1273
            # it
1274
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1275
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
1276
                      'timestamp', 'timezone', 'message', 'committer', 
1277
                      'parent_ids', 'properties'):
1278
                self.assertEqual(getattr(branch_rev, a), 
1279
                                 getattr(bundle_rev, a))
1280
            self.assertEqual(len(branch_rev.parent_ids), 
1281
                             len(bundle_rev.parent_ids))
2520.4.29 by Aaron Bentley
Reactivate some testing, fix topo_iter
1282
        self.assertEqual(set(rev_ids),
1283
                         set([r.revision_id for r in bundle.real_revisions]))
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1284
        self.valid_apply_bundle(base_rev_id, bundle,
1285
                                   checkout_dir=checkout_dir)
1286
1287
        return bundle
1288
2520.4.34 by Aaron Bentley
Add signature support
1289
    def get_invalid_bundle(self, base_rev_id, rev_id):
1290
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1291
        Munge the text so that it's invalid.
1292
1293
        :return: The in-memory bundle
1294
        """
1295
        from bzrlib.bundle import serializer
1296
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1297
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
1298
        new_text = new_text.replace('<file file_id="exe-1"',
1299
                                    '<file executable="y" file_id="exe-1"')
2520.4.143 by Aaron Bentley
Fix invalid bundle test
1300
        new_text = new_text.replace('B222', 'B237')
2520.4.34 by Aaron Bentley
Add signature support
1301
        bundle_txt = StringIO()
2520.4.136 by Aaron Bentley
Fix format strings
1302
        bundle_txt.write(serializer._get_bundle_header('4'))
2520.4.34 by Aaron Bentley
Add signature support
1303
        bundle_txt.write('\n')
2520.4.76 by Aaron Bentley
Move base64-encoding into merge directives
1304
        bundle_txt.write(new_text.encode('bz2'))
2520.4.34 by Aaron Bentley
Add signature support
1305
        bundle_txt.seek(0)
1306
        bundle = read_bundle(bundle_txt)
1307
        self.valid_apply_bundle(base_rev_id, bundle)
1308
        return bundle
1309
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1310
    def create_bundle_text(self, base_rev_id, rev_id):
1311
        bundle_txt = StringIO()
1312
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id, 
1313
                               bundle_txt, format=self.format)
1314
        bundle_txt.seek(0)
1315
        self.assertEqual(bundle_txt.readline(), 
1316
                         '# Bazaar revision bundle v%s\n' % self.format)
1317
        self.assertEqual(bundle_txt.readline(), '#\n')
1318
        rev = self.b1.repository.get_revision(rev_id)
1319
        bundle_txt.seek(0)
1320
        return bundle_txt, rev_ids
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1321
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1322
    def get_bundle_tree(self, bundle, revision_id):
1323
        repository = self.make_repository('repo')
1324
        bundle.install_revisions(repository)
1325
        return repository.revision_tree(revision_id)
1326
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1327
    def test_creation(self):
1328
        tree = self.make_branch_and_tree('tree')
2520.4.8 by Aaron Bentley
Serialize inventory
1329
        self.build_tree_contents([('tree/file', 'contents1\nstatic\n')])
2520.4.6 by Aaron Bentley
Get installation started
1330
        tree.add('file', 'fileid-2')
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1331
        tree.commit('added file', rev_id='rev1')
2520.4.8 by Aaron Bentley
Serialize inventory
1332
        self.build_tree_contents([('tree/file', 'contents2\nstatic\n')])
2520.4.10 by Aaron Bentley
Enable installation of revisions
1333
        tree.commit('changed file', rev_id='rev2')
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1334
        s = StringIO()
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1335
        serializer = BundleSerializerV4('1.0')
2520.4.8 by Aaron Bentley
Serialize inventory
1336
        serializer.write(tree.branch.repository, ['rev1', 'rev2'], {}, s)
2520.4.5 by Aaron Bentley
Start work on reading mpbundles
1337
        s.seek(0)
2520.4.6 by Aaron Bentley
Get installation started
1338
        tree2 = self.make_branch_and_tree('target')
1339
        target_repo = tree2.branch.repository
1340
        install_bundle(target_repo, serializer.read(s))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1341
        target_repo.lock_read()
1342
        self.addCleanup(target_repo.unlock)
1343
        self.assertEqual({'1':'contents1\nstatic\n',
1344
            '2':'contents2\nstatic\n'},
1345
            dict(target_repo.iter_files_bytes(
1346
                [('fileid-2', 'rev1', '1'), ('fileid-2', 'rev2', '2')])))
2520.4.8 by Aaron Bentley
Serialize inventory
1347
        rtree = target_repo.revision_tree('rev2')
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1348
        inventory_vf = target_repo.inventories
1349
        # If the inventory store has a graph, it must match the revision graph.
1350
        self.assertSubset(
1351
            [inventory_vf.get_parent_map([('rev2',)])[('rev2',)]],
1352
            [None, (('rev1',),)])
2520.4.10 by Aaron Bentley
Enable installation of revisions
1353
        self.assertEqual('changed file',
1354
                         target_repo.get_revision('rev2').message)
2520.4.6 by Aaron Bentley
Get installation started
1355
2520.4.32 by Aaron Bentley
Fix test case
1356
    @staticmethod
1357
    def get_raw(bundle_file):
1358
        bundle_file.seek(0)
2520.4.70 by Aaron Bentley
Yank patch-handling functionality
1359
        line = bundle_file.readline()
1360
        line = bundle_file.readline()
2520.4.32 by Aaron Bentley
Fix test case
1361
        lines = bundle_file.readlines()
2520.4.76 by Aaron Bentley
Move base64-encoding into merge directives
1362
        return ''.join(lines).decode('bz2')
2520.4.32 by Aaron Bentley
Fix test case
1363
2520.4.34 by Aaron Bentley
Add signature support
1364
    def test_copy_signatures(self):
1365
        tree_a = self.make_branch_and_tree('tree_a')
1366
        import bzrlib.gpg
1367
        import bzrlib.commit as commit
1368
        oldstrategy = bzrlib.gpg.GPGStrategy
1369
        branch = tree_a.branch
1370
        repo_a = branch.repository
1371
        tree_a.commit("base", allow_pointless=True, rev_id='A')
1372
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
1373
        try:
1374
            from bzrlib.testament import Testament
1375
            # monkey patch gpg signing mechanism
1376
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
1377
            new_config = test_commit.MustSignConfig(branch)
1378
            commit.Commit(config=new_config).commit(message="base",
1379
                                                    allow_pointless=True,
1380
                                                    rev_id='B',
1381
                                                    working_tree=tree_a)
1382
            def sign(text):
1383
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
1384
            self.assertTrue(repo_a.has_signature_for_revision_id('B'))
1385
        finally:
1386
            bzrlib.gpg.GPGStrategy = oldstrategy
1387
        tree_b = self.make_branch_and_tree('tree_b')
1388
        repo_b = tree_b.branch.repository
1389
        s = StringIO()
2520.4.136 by Aaron Bentley
Fix format strings
1390
        serializer = BundleSerializerV4('4')
2520.4.34 by Aaron Bentley
Add signature support
1391
        serializer.write(tree_a.branch.repository, ['A', 'B'], {}, s)
1392
        s.seek(0)
1393
        install_bundle(repo_b, serializer.read(s))
1394
        self.assertTrue(repo_b.has_signature_for_revision_id('B'))
1395
        self.assertEqual(repo_b.get_signature_text('B'),
1396
                         repo_a.get_signature_text('B'))
2520.4.100 by Aaron Bentley
Fix repeat signature installs
1397
        s.seek(0)
1398
        # ensure repeat installs are harmless
1399
        install_bundle(repo_b, serializer.read(s))
2520.4.34 by Aaron Bentley
Add signature support
1400
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1401
2520.4.90 by Aaron Bentley
Handle \r terminated lines in Weaves properly
1402
class V4WeaveBundleTester(V4BundleTester):
1403
1404
    def bzrdir_format(self):
2520.4.91 by Aaron Bentley
Okay, so I meant metaweave. I think.
1405
        return 'metaweave'
2520.4.90 by Aaron Bentley
Handle \r terminated lines in Weaves properly
1406
1407
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1408
class MungedBundleTester(object):
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1409
1410
    def build_test_bundle(self):
1411
        wt = self.make_branch_and_tree('b1')
1412
1413
        self.build_tree(['b1/one'])
1414
        wt.add('one')
1415
        wt.commit('add one', rev_id='a@cset-0-1')
1416
        self.build_tree(['b1/two'])
1417
        wt.add('two')
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1418
        wt.commit('add two', rev_id='a@cset-0-2',
1419
                  revprops={'branch-nick':'test'})
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1420
1421
        bundle_txt = StringIO()
1422
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1423
                               'a@cset-0-1', bundle_txt, self.format)
1424
        self.assertEqual(set(['a@cset-0-2']), set(rev_ids))
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1425
        bundle_txt.seek(0, 0)
1426
        return bundle_txt
1427
1428
    def check_valid(self, bundle):
1429
        """Check that after whatever munging, the final object is valid."""
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1430
        self.assertEqual(['a@cset-0-2'],
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1431
            [r.revision_id for r in bundle.real_revisions])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1432
1433
    def test_extra_whitespace(self):
1434
        bundle_txt = self.build_test_bundle()
1435
1436
        # Seek to the end of the file
1437
        # Adding one extra newline used to give us
1438
        # TypeError: float() argument must be a string or a number
1439
        bundle_txt.seek(0, 2)
1440
        bundle_txt.write('\n')
1441
        bundle_txt.seek(0)
1442
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1443
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1444
        self.check_valid(bundle)
1445
1446
    def test_extra_whitespace_2(self):
1447
        bundle_txt = self.build_test_bundle()
1448
1449
        # Seek to the end of the file
1450
        # Adding two extra newlines used to give us
1451
        # MalformedPatches: The first line of all patches should be ...
1452
        bundle_txt.seek(0, 2)
1453
        bundle_txt.write('\n\n')
1454
        bundle_txt.seek(0)
1455
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1456
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1457
        self.check_valid(bundle)
1458
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1459
1460
class MungedBundleTesterV09(TestCaseWithTransport, MungedBundleTester):
1461
1462
    format = '0.9'
1463
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1464
    def test_missing_trailing_whitespace(self):
1465
        bundle_txt = self.build_test_bundle()
1466
1467
        # Remove a trailing newline, it shouldn't kill the parser
1468
        raw = bundle_txt.getvalue()
1469
        # The contents of the bundle don't have to be this, but this
1470
        # test is concerned with the exact case where the serializer
1471
        # creates a blank line at the end, and fails if that
1472
        # line is stripped
1473
        self.assertEqual('\n\n', raw[-2:])
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1474
        bundle_txt = StringIO(raw[:-1])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1475
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1476
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1477
        self.check_valid(bundle)
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1478
1793.3.16 by John Arbash Meinel
Add tests to ensure that we gracefully handle opening and trailing non-bundle text.
1479
    def test_opening_text(self):
1480
        bundle_txt = self.build_test_bundle()
1481
1482
        bundle_txt = StringIO("Some random\nemail comments\n"
1483
                              + bundle_txt.getvalue())
1484
1485
        bundle = read_bundle(bundle_txt)
1486
        self.check_valid(bundle)
1487
1488
    def test_trailing_text(self):
1489
        bundle_txt = self.build_test_bundle()
1490
1491
        bundle_txt = StringIO(bundle_txt.getvalue() +
1492
                              "Some trailing\nrandom\ntext\n")
1493
1494
        bundle = read_bundle(bundle_txt)
1495
        self.check_valid(bundle)
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1496
1497
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1498
class MungedBundleTesterV4(TestCaseWithTransport, MungedBundleTester):
1499
2520.4.136 by Aaron Bentley
Fix format strings
1500
    format = '4'
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1501
1502
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1503
class TestBundleWriterReader(TestCase):
1504
1505
    def test_roundtrip_record(self):
1506
        fileobj = StringIO()
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1507
        writer = v4.BundleWriter(fileobj)
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1508
        writer.begin()
2520.4.95 by Aaron Bentley
Add support for header/info records
1509
        writer.add_info_record(foo='bar')
1510
        writer._add_record("Record body", {'parents': ['1', '3'],
1511
            'storage_kind':'fulltext'}, 'file', 'revid', 'fileid')
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1512
        writer.end()
1513
        fileobj.seek(0)
2520.4.148 by Aaron Bentley
Updates from review
1514
        reader = v4.BundleReader(fileobj, stream_input=True)
2520.4.145 by Aaron Bentley
Add memory_friendly toggle, be memory-unfriendly for merge directives
1515
        record_iter = reader.iter_records()
1516
        record = record_iter.next()
1517
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1518
            'info', None, None), record)
1519
        record = record_iter.next()
1520
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1521
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1522
                          record)
1523
1524
    def test_roundtrip_record_memory_hungry(self):
1525
        fileobj = StringIO()
1526
        writer = v4.BundleWriter(fileobj)
1527
        writer.begin()
1528
        writer.add_info_record(foo='bar')
1529
        writer._add_record("Record body", {'parents': ['1', '3'],
1530
            'storage_kind':'fulltext'}, 'file', 'revid', 'fileid')
1531
        writer.end()
1532
        fileobj.seek(0)
2520.4.148 by Aaron Bentley
Updates from review
1533
        reader = v4.BundleReader(fileobj, stream_input=False)
2520.4.145 by Aaron Bentley
Add memory_friendly toggle, be memory-unfriendly for merge directives
1534
        record_iter = reader.iter_records()
2520.4.95 by Aaron Bentley
Add support for header/info records
1535
        record = record_iter.next()
1536
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1537
            'info', None, None), record)
1538
        record = record_iter.next()
1539
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1540
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1541
                          record)
1542
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1543
    def test_encode_name(self):
2520.4.95 by Aaron Bentley
Add support for header/info records
1544
        self.assertEqual('revision/rev1',
1545
            v4.BundleWriter.encode_name('revision', 'rev1'))
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1546
        self.assertEqual('file/rev//1/file-id-1',
1547
            v4.BundleWriter.encode_name('file', 'rev/1', 'file-id-1'))
2520.4.95 by Aaron Bentley
Add support for header/info records
1548
        self.assertEqual('info',
1549
            v4.BundleWriter.encode_name('info', None, None))
1550
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1551
    def test_decode_name(self):
2520.4.95 by Aaron Bentley
Add support for header/info records
1552
        self.assertEqual(('revision', 'rev1', None),
1553
            v4.BundleReader.decode_name('revision/rev1'))
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1554
        self.assertEqual(('file', 'rev/1', 'file-id-1'),
1555
            v4.BundleReader.decode_name('file/rev//1/file-id-1'))
2520.4.95 by Aaron Bentley
Add support for header/info records
1556
        self.assertEqual(('info', None, None),
1557
                         v4.BundleReader.decode_name('info'))
2520.4.131 by Aaron Bentley
Raise BadBundle for records with wrong number of names
1558
1559
    def test_too_many_names(self):
1560
        fileobj = StringIO()
1561
        writer = v4.BundleWriter(fileobj)
1562
        writer.begin()
1563
        writer.add_info_record(foo='bar')
1564
        writer._container.add_bytes_record('blah', ['two', 'names'])
1565
        writer.end()
1566
        fileobj.seek(0)
1567
        record_iter = v4.BundleReader(fileobj).iter_records()
1568
        record = record_iter.next()
1569
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1570
            'info', None, None), record)
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
1571
        self.assertRaises(errors.BadBundle, record_iter.next)
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1572
1573
1574
class TestReadMergeableFromUrl(TestCaseWithTransport):
1575
1576
    def test_read_mergeable_skips_local(self):
1577
        """A local bundle named like the URL should not be read.
1578
        """
1579
        out, wt = test_read_bundle.create_bundle_file(self)
1580
        class FooService(object):
1581
            """A directory service that always returns source"""
1582
1583
            def look_up(self, name, url):
1584
                return 'source'
3251.4.12 by Aaron Bentley
Updates from review
1585
        directories.register('foo:', FooService, 'Testing directory service')
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1586
        self.addCleanup(lambda: directories.remove('foo:'))
1587
        self.build_tree_contents([('./foo:bar', out.getvalue())])
1588
        self.assertRaises(errors.NotABundle, read_mergeable_from_url,
1589
                          'foo:bar')