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