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