/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
1
# Copyright (C) 2004-2006 by Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
16
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
17
from cStringIO import StringIO
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
18
import os
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
19
import sys
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
20
import tempfile
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
21
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
22
from bzrlib import inventory
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
23
from bzrlib.builtins import _merge_helper
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
24
from bzrlib.bzrdir import BzrDir
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
25
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
1793.2.3 by Aaron Bentley
Rename read_bundle.py to bundle_data.py
26
from bzrlib.bundle.bundle_data import BundleTree
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
27
from bzrlib.bundle.serializer import write_bundle, read_bundle
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
28
from bzrlib.branch import Branch
1185.82.90 by Aaron Bentley
Reorganized test suite
29
from bzrlib.diff import internal_diff
1910.2.3 by Aaron Bentley
All tests pass
30
from bzrlib.errors import (BzrError, TestamentMismatch, NotABundle, BadBundle, 
31
                           NoSuchFile,)
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
32
from bzrlib.merge import Merge3Merger
1185.82.87 by Aaron Bentley
Got symlink adding working
33
from bzrlib.osutils import has_symlinks, sha_file
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
34
from bzrlib.tests import (TestCaseInTempDir, TestCaseWithTransport,
35
                          TestCase, TestSkipped)
1185.82.66 by Aaron Bentley
Handle new executable files
36
from bzrlib.transform import TreeTransform
1185.82.17 by Aaron Bentley
More API updates
37
from bzrlib.workingtree import WorkingTree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
38
1185.82.90 by Aaron Bentley
Reorganized test suite
39
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
40
class MockTree(object):
41
    def __init__(self):
1731.1.4 by Aaron Bentley
merge from bzr.dev
42
        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)
43
        object.__init__(self)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
44
        self.paths = {ROOT_ID: ""}
45
        self.ids = {"": ROOT_ID}
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
46
        self.contents = {}
1731.1.4 by Aaron Bentley
merge from bzr.dev
47
        self.root = InventoryDirectory(ROOT_ID, '', None)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
48
49
    inventory = property(lambda x:x)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
50
51
    def __iter__(self):
52
        return self.paths.iterkeys()
53
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
54
    def __getitem__(self, file_id):
55
        if file_id == self.root.file_id:
56
            return self.root
57
        else:
58
            return self.make_entry(file_id, self.paths[file_id])
59
60
    def parent_id(self, file_id):
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
61
        parent_dir = os.path.dirname(self.paths[file_id])
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
62
        if parent_dir == "":
63
            return None
64
        return self.ids[parent_dir]
65
66
    def iter_entries(self):
67
        for path, file_id in self.ids.iteritems():
68
            yield path, self[file_id]
69
70
    def get_file_kind(self, file_id):
71
        if file_id in self.contents:
72
            kind = 'file'
73
        else:
74
            kind = 'directory'
75
        return kind
76
77
    def make_entry(self, file_id, path):
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
78
        from bzrlib.inventory import (InventoryEntry, InventoryFile
79
                                    , InventoryDirectory, InventoryLink)
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
80
        name = os.path.basename(path)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
81
        kind = self.get_file_kind(file_id)
82
        parent_id = self.parent_id(file_id)
83
        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()
84
        if kind == 'directory':
85
            ie = InventoryDirectory(file_id, name, parent_id)
86
        elif kind == 'file':
87
            ie = InventoryFile(file_id, name, parent_id)
88
        elif kind == 'symlink':
89
            ie = InventoryLink(file_id, name, parent_id)
90
        else:
91
            raise BzrError('unknown kind %r' % kind)
0.5.91 by Aaron Bentley
Updated to match API change
92
        ie.text_sha1 = text_sha_1
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
93
        ie.text_size = text_size
94
        return ie
95
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
96
    def add_dir(self, file_id, path):
97
        self.paths[file_id] = path
98
        self.ids[path] = file_id
99
    
100
    def add_file(self, file_id, path, contents):
101
        self.add_dir(file_id, path)
102
        self.contents[file_id] = contents
103
104
    def path2id(self, path):
105
        return self.ids.get(path)
106
107
    def id2path(self, file_id):
108
        return self.paths.get(file_id)
109
110
    def has_id(self, file_id):
111
        return self.id2path(file_id) is not None
112
113
    def get_file(self, file_id):
114
        result = StringIO()
115
        result.write(self.contents[file_id])
116
        result.seek(0,0)
117
        return result
118
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
119
    def contents_stats(self, file_id):
120
        if file_id not in self.contents:
121
            return None, None
122
        text_sha1 = sha_file(self.get_file(file_id))
123
        return text_sha1, len(self.contents[file_id])
124
125
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
126
class BTreeTester(TestCase):
127
    """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)
128
129
    def make_tree_1(self):
130
        mtree = MockTree()
131
        mtree.add_dir("a", "grandparent")
132
        mtree.add_dir("b", "grandparent/parent")
133
        mtree.add_file("c", "grandparent/parent/file", "Hello\n")
134
        mtree.add_dir("d", "grandparent/alt_parent")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
135
        return BundleTree(mtree, ''), mtree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
136
        
137
    def test_renames(self):
138
        """Ensure that file renames have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
139
        btree = self.make_tree_1()[0]
140
        self.assertEqual(btree.old_path("grandparent"), "grandparent")
141
        self.assertEqual(btree.old_path("grandparent/parent"), 
142
                         "grandparent/parent")
143
        self.assertEqual(btree.old_path("grandparent/parent/file"),
144
                         "grandparent/parent/file")
145
146
        self.assertEqual(btree.id2path("a"), "grandparent")
147
        self.assertEqual(btree.id2path("b"), "grandparent/parent")
148
        self.assertEqual(btree.id2path("c"), "grandparent/parent/file")
149
150
        self.assertEqual(btree.path2id("grandparent"), "a")
151
        self.assertEqual(btree.path2id("grandparent/parent"), "b")
152
        self.assertEqual(btree.path2id("grandparent/parent/file"), "c")
153
154
        assert btree.path2id("grandparent2") is None
155
        assert btree.path2id("grandparent2/parent") is None
156
        assert btree.path2id("grandparent2/parent/file") is None
157
158
        btree.note_rename("grandparent", "grandparent2")
159
        assert btree.old_path("grandparent") is None
160
        assert btree.old_path("grandparent/parent") is None
161
        assert btree.old_path("grandparent/parent/file") is None
162
163
        self.assertEqual(btree.id2path("a"), "grandparent2")
164
        self.assertEqual(btree.id2path("b"), "grandparent2/parent")
165
        self.assertEqual(btree.id2path("c"), "grandparent2/parent/file")
166
167
        self.assertEqual(btree.path2id("grandparent2"), "a")
168
        self.assertEqual(btree.path2id("grandparent2/parent"), "b")
169
        self.assertEqual(btree.path2id("grandparent2/parent/file"), "c")
170
171
        assert btree.path2id("grandparent") is None
172
        assert btree.path2id("grandparent/parent") is None
173
        assert btree.path2id("grandparent/parent/file") is None
174
175
        btree.note_rename("grandparent/parent", "grandparent2/parent2")
176
        self.assertEqual(btree.id2path("a"), "grandparent2")
177
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
178
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file")
179
180
        self.assertEqual(btree.path2id("grandparent2"), "a")
181
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
182
        self.assertEqual(btree.path2id("grandparent2/parent2/file"), "c")
183
184
        assert btree.path2id("grandparent2/parent") is None
185
        assert btree.path2id("grandparent2/parent/file") is None
186
187
        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)
188
                          "grandparent2/parent2/file2")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
189
        self.assertEqual(btree.id2path("a"), "grandparent2")
190
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
191
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file2")
192
193
        self.assertEqual(btree.path2id("grandparent2"), "a")
194
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
195
        self.assertEqual(btree.path2id("grandparent2/parent2/file2"), "c")
196
197
        assert 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)
198
199
    def test_moves(self):
200
        """Ensure that file moves have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
201
        btree = self.make_tree_1()[0]
202
        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)
203
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
204
        self.assertEqual(btree.id2path("c"), "grandparent/alt_parent/file")
205
        self.assertEqual(btree.path2id("grandparent/alt_parent/file"), "c")
206
        assert 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)
207
208
    def unified_diff(self, old, new):
209
        out = StringIO()
210
        internal_diff("old", old, "new", new, out)
211
        out.seek(0,0)
212
        return out.read()
213
214
    def make_tree_2(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
215
        btree = self.make_tree_1()[0]
216
        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)
217
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
218
        assert btree.id2path("e") is None
219
        assert btree.path2id("grandparent/parent/file") is None
220
        btree.note_id("e", "grandparent/parent/file")
221
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
222
223
    def test_adds(self):
224
        """File/inventory adds"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
225
        btree = self.make_tree_2()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
226
        add_patch = self.unified_diff([], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
227
        btree.note_patch("grandparent/parent/file", add_patch)
228
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
229
        btree.note_target('grandparent/parent/symlink', 'venus')
230
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
231
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
232
    def adds_test(self, btree):
233
        self.assertEqual(btree.id2path("e"), "grandparent/parent/file")
234
        self.assertEqual(btree.path2id("grandparent/parent/file"), "e")
235
        self.assertEqual(btree.get_file("e").read(), "Extra cheese\n")
236
        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)
237
238
    def test_adds2(self):
239
        """File/inventory adds, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
240
        btree = self.make_tree_2()
241
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
242
        add_patch = self.unified_diff(["Hello\n"], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
243
        btree.note_patch("grandparent/parent/file", add_patch)
244
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
245
        btree.note_target('grandparent/parent/symlink', 'venus')
246
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
247
248
    def make_tree_3(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
249
        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)
250
        mtree.add_file("e", "grandparent/parent/topping", "Anchovies\n")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
251
        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)
252
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
253
        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)
254
                          "grandparent/alt_parent/stopping")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
255
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
256
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
257
    def get_file_test(self, btree):
258
        self.assertEqual(btree.get_file("e").read(), "Lemon\n")
259
        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)
260
261
    def test_get_file(self):
262
        """Get file contents"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
263
        btree = self.make_tree_3()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
264
        mod_patch = self.unified_diff(["Anchovies\n"], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
265
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
266
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
267
268
    def test_get_file2(self):
269
        """Get file contents, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
270
        btree = self.make_tree_3()
271
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
272
        mod_patch = self.unified_diff([], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
273
        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)
274
        mod_patch = self.unified_diff([], ["Hello\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
275
        btree.note_patch("grandparent/alt_parent/file", mod_patch)
276
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
277
278
    def test_delete(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
279
        "Deletion by bundle"
280
        btree = self.make_tree_1()[0]
281
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
282
        btree.note_deletion("grandparent/parent/file")
283
        assert btree.id2path("c") is None
284
        assert 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)
285
286
    def sorted_ids(self, tree):
287
        ids = list(tree)
288
        ids.sort()
289
        return ids
290
291
    def test_iteration(self):
292
        """Ensure that iteration through ids works properly"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
293
        btree = self.make_tree_1()[0]
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
294
        self.assertEqual(self.sorted_ids(btree),
295
            [inventory.ROOT_ID, 'a', 'b', 'c', 'd'])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
296
        btree.note_deletion("grandparent/parent/file")
297
        btree.note_id("e", "grandparent/alt_parent/fool", kind="directory")
298
        btree.note_last_changed("grandparent/alt_parent/fool", 
1185.82.95 by Aaron Bentley
Restore path-orientation of ChangesetTree
299
                                "revisionidiguess")
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
300
        self.assertEqual(self.sorted_ids(btree),
301
            [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)
302
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
303
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
304
class BundleTester(TestCaseWithTransport):
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
305
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
306
    def create_bundle_text(self, base_rev_id, rev_id):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
307
        bundle_txt = StringIO()
308
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id, 
309
                               bundle_txt)
310
        bundle_txt.seek(0)
311
        self.assertEqual(bundle_txt.readline(), 
1551.7.3 by Aaron Bentley
Fix strict testaments, as_sha1
312
                         '# Bazaar revision bundle v0.8\n')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
313
        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.
314
1185.82.14 by Aaron Bentley
API updates
315
        rev = self.b1.repository.get_revision(rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
316
        self.assertEqual(bundle_txt.readline().decode('utf-8'),
317
                         u'# message:\n')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
318
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
319
        open(',,bundle', 'wb').write(bundle_txt.getvalue())
320
        bundle_txt.seek(0)
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
321
        return bundle_txt, rev_ids
322
323
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
324
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
325
        Make sure that the text generated is valid, and that it
326
        can be applied against the base, and generate the same information.
327
        
328
        :return: The in-memory bundle 
329
        """
330
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
331
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
332
        # This should also validate the generated bundle 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
333
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
334
        repository = self.b1.repository
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
335
        for bundle_rev in bundle.real_revisions:
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
336
            # These really should have already been checked when we read the
337
            # bundle, since it computes the sha1 hash for the revision, which
338
            # only will match if everything is okay, but lets be explicit about
339
            # it
340
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1185.82.33 by Aaron Bentley
Strengthen tests
341
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
342
                      'timestamp', 'timezone', 'message', 'committer', 
343
                      'parent_ids', 'properties'):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
344
                self.assertEqual(getattr(branch_rev, a), 
345
                                 getattr(bundle_rev, a))
346
            self.assertEqual(len(branch_rev.parent_ids), 
347
                             len(bundle_rev.parent_ids))
1185.82.47 by Aaron Bentley
Ensure all intended rev_ids end up in the revision
348
        self.assertEqual(rev_ids, 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
349
                         [r.revision_id for r in bundle.real_revisions])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
350
        self.valid_apply_bundle(base_rev_id, bundle,
1185.82.89 by Aaron Bentley
Remove auto_commit stuff
351
                                   checkout_dir=checkout_dir)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
352
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
353
        return bundle
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
354
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
355
    def get_invalid_bundle(self, base_rev_id, rev_id):
356
        """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
357
        Munge the text so that it's invalid.
358
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
359
        :return: The in-memory bundle
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
360
        """
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
361
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
362
        new_text = bundle_txt.getvalue().replace('executable:no', 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
363
                                               'executable:yes')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
364
        bundle_txt = StringIO(new_text)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
365
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
366
        self.valid_apply_bundle(base_rev_id, bundle)
367
        return bundle 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
368
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
369
    def test_non_bundle(self):
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
370
        self.assertRaises(NotABundle, read_bundle, StringIO('#!/bin/sh\n'))
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
371
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
372
    def test_malformed(self):
373
        self.assertRaises(BadBundle, read_bundle, 
374
                          StringIO('# Bazaar revision bundle v'))
375
376
    def test_crlf_bundle(self):
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
377
        try:
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
378
            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
379
        except BadBundle:
380
            # It is currently permitted for bundles with crlf line endings to
381
            # make read_bundle raise a BadBundle, but this should be fixed.
1793.2.10 by Aaron Bentley
Whitespace/comment fix
382
            # Anything else, especially NotABundle, is an error.
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
383
            pass
384
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
385
    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.
386
        """Get a new tree, with the specified revision in it.
387
        """
388
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
389
        if checkout_dir is None:
390
            checkout_dir = tempfile.mkdtemp(prefix='test-branch-', dir='.')
0.5.89 by John Arbash Meinel
Updating for explicitly defined directories.
391
        else:
392
            if not os.path.exists(checkout_dir):
393
                os.mkdir(checkout_dir)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
394
        tree = BzrDir.create_standalone_workingtree(checkout_dir)
395
        s = StringIO()
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
396
        ancestors = write_bundle(self.b1.repository, rev_id, None, s)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
397
        s.seek(0)
1185.82.135 by Aaron Bentley
Ensure that bundles are bytestrings
398
        assert isinstance(s.getvalue(), str), (
399
            "Bundle isn't a bytestring:\n %s..." % repr(s.getvalue())[:40])
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
400
        install_bundle(tree.branch.repository, read_bundle(s))
1185.82.41 by Aaron Bentley
More work on installing changesets
401
        for ancestor in ancestors:
402
            old = self.b1.repository.revision_tree(ancestor)
403
            new = tree.branch.repository.revision_tree(ancestor)
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
404
405
            # Check that there aren't any inventory level changes
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
406
            delta = new.changes_from(old)
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
407
            self.assertFalse(delta.has_changed(),
408
                             'Revision %s not copied correctly.'
409
                             % (ancestor,))
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
410
411
            # Now check that the file contents are all correct
1185.82.41 by Aaron Bentley
More work on installing changesets
412
            for inventory_id in old:
413
                try:
414
                    old_file = old.get_file(inventory_id)
1910.2.3 by Aaron Bentley
All tests pass
415
                except NoSuchFile:
1185.82.41 by Aaron Bentley
More work on installing changesets
416
                    continue
417
                if old_file is None:
418
                    continue
419
                self.assertEqual(old_file.read(),
420
                                 new.get_file(inventory_id).read())
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
421
        if rev_id is not None:
422
            rh = self.b1.revision_history()
423
            tree.branch.set_revision_history(rh[:rh.index(rev_id)+1])
424
            tree.update()
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
425
            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.
426
            self.assertFalse(delta.has_changed(),
427
                             'Working tree has modifications')
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
428
        return tree
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
429
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
430
    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.
431
        """Get the base revision, apply the changes, and make
432
        sure everything matches the builtin branch.
433
        """
1185.82.17 by Aaron Bentley
More API updates
434
        to_tree = self.get_checkout(base_rev_id, checkout_dir=checkout_dir)
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
435
        original_parents = to_tree.get_parent_ids()
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
436
        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.
437
        original_parents = to_tree.get_parent_ids()
1185.82.41 by Aaron Bentley
More work on installing changesets
438
        self.assertIs(repository.has_revision(base_rev_id), True)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
439
        for rev in info.real_revisions:
440
            self.assert_(not repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
441
                'Revision {%s} present before applying bundle' 
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
442
                % rev.revision_id)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
443
        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.
444
445
        for rev in info.real_revisions:
1185.82.17 by Aaron Bentley
More API updates
446
            self.assert_(repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
447
                '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.
448
                % rev.revision_id)
449
1185.82.17 by Aaron Bentley
More API updates
450
        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.
451
        # 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.
452
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
453
        self.assertEqual(original_parents + [info.target],
454
            to_tree.get_parent_ids())
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
455
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
456
        rev = info.real_revisions[-1]
1185.82.17 by Aaron Bentley
More API updates
457
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
458
        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.
459
        
460
        # 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.
461
        #       we might also check the working tree.
462
463
        base_files = list(base_tree.list_files())
464
        to_files = list(to_tree.list_files())
465
        self.assertEqual(len(base_files), len(to_files))
1185.82.66 by Aaron Bentley
Handle new executable files
466
        for base_file, to_file in zip(base_files, to_files):
467
            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.
468
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
469
        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.
470
            # Check that the meta information is the same
471
            self.assertEqual(base_tree.get_file_size(fileid),
472
                    to_tree.get_file_size(fileid))
473
            self.assertEqual(base_tree.get_file_sha1(fileid),
474
                    to_tree.get_file_sha1(fileid))
475
            # Check that the contents are the same
476
            # This is pretty expensive
477
            # self.assertEqual(base_tree.get_file(fileid).read(),
478
            #         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.
479
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
480
    def test_bundle(self):
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
481
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.14 by Aaron Bentley
API updates
482
        self.b1 = self.tree1.branch
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
483
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
484
        open('b1/one', 'wb').write('one\n')
1185.82.14 by Aaron Bentley
API updates
485
        self.tree1.add('one')
486
        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.
487
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
488
        bundle = self.get_valid_bundle(None, 'a@cset-0-1')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
489
        # FIXME: The current write_bundle api no longer supports
490
        #        setting a custom summary message
491
        #        We should re-introduce the ability, and update
492
        #        the tests to make sure it works.
493
        # bundle = self.get_valid_bundle(None, 'a@cset-0-1',
494
        #         message='With a specialized message')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
495
496
        # Make sure we can handle files with spaces, tabs, other
497
        # bogus characters
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
498
        self.build_tree([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
499
                'b1/with space.txt'
500
                , 'b1/dir/'
501
                , 'b1/dir/filein subdir.c'
502
                , 'b1/dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
503
                , 'b1/dir/ pre space'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
504
                , 'b1/sub/'
505
                , 'b1/sub/sub/'
506
                , '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
507
                ])
0.5.84 by John Arbash Meinel
(broken) problem with removes.
508
        open('b1/sub/sub/emptyfile.txt', 'wb').close()
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
509
        open('b1/dir/nolastnewline.txt', 'wb').write('bloop')
1185.82.66 by Aaron Bentley
Handle new executable files
510
        tt = TreeTransform(self.tree1)
511
        tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
512
        tt.apply()
1185.82.14 by Aaron Bentley
API updates
513
        self.tree1.add([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
514
                'with space.txt'
515
                , 'dir'
516
                , 'dir/filein subdir.c'
517
                , 'dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
518
                , 'dir/ pre space'
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
519
                , 'dir/nolastnewline.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
520
                , 'sub'
521
                , 'sub/sub'
522
                , 'sub/sub/nonempty.txt'
523
                , 'sub/sub/emptyfile.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
524
                ])
1185.82.14 by Aaron Bentley
API updates
525
        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.
526
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
527
        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.
528
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
529
        # Check a rollup bundle 
530
        bundle = self.get_valid_bundle(None, 'a@cset-0-2')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
531
532
        # Now delete entries
1185.82.21 by Aaron Bentley
Stop using deprecated function
533
        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.
534
                ['sub/sub/nonempty.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
535
                , '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.
536
                , 'sub/sub'
537
                ])
1185.82.68 by Aaron Bentley
Handle execute bit on modified files
538
        tt = TreeTransform(self.tree1)
539
        trans_id = tt.trans_id_tree_file_id('exe-1')
540
        tt.set_executability(False, trans_id)
541
        tt.apply()
1185.82.19 by Aaron Bentley
More API updates
542
        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.
543
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
544
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
545
        self.assertRaises(TestamentMismatch, self.get_invalid_bundle, 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
546
                          'a@cset-0-2', 'a@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
547
        # Check a rollup bundle 
548
        bundle = self.get_valid_bundle(None, 'a@cset-0-3')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
549
550
        # Now move the directory
1185.82.19 by Aaron Bentley
More API updates
551
        self.tree1.rename_one('dir', 'sub/dir')
552
        self.tree1.commit('rename dir', rev_id='a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
553
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
554
        bundle = self.get_valid_bundle('a@cset-0-3', 'a@cset-0-4')
555
        # Check a rollup bundle 
556
        bundle = self.get_valid_bundle(None, 'a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
557
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
558
        # Modified files
559
        open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
560
        open('b1/sub/dir/ pre space', 'ab').write('\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
561
        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.
562
        self.tree1.rename_one('sub/dir/ pre space', 
563
                              'sub/ start space')
1185.82.19 by Aaron Bentley
More API updates
564
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
565
        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.
566
1185.82.70 by Aaron Bentley
Handle renamed files better
567
        self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
568
        self.tree1.rename_one('with space.txt', 'WithCaps.txt')
569
        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.
570
        self.tree1.commit(u'swap filenames', rev_id='a@cset-0-6',
571
                          verbose=False)
572
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
573
        other = self.get_checkout('a@cset-0-5')
574
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
575
        other.commit('rename file', rev_id='a@cset-0-6b')
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
576
        _merge_helper([other.basedir, -1], [None, None],
577
                      this_dir=self.tree1.basedir)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
578
        self.tree1.commit(u'Merge', rev_id='a@cset-0-7',
1185.82.70 by Aaron Bentley
Handle renamed files better
579
                          verbose=False)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
580
        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
581
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
582
    def test_symlink_bundle(self):
1185.82.87 by Aaron Bentley
Got symlink adding working
583
        if not has_symlinks():
584
            raise TestSkipped("No symlink support")
585
        self.tree1 = BzrDir.create_standalone_workingtree('b1')
586
        self.b1 = self.tree1.branch
587
        tt = TreeTransform(self.tree1)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
588
        tt.new_symlink('link', tt.root, 'bar/foo', 'link-1')
1185.82.87 by Aaron Bentley
Got symlink adding working
589
        tt.apply()
590
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
591
        self.get_valid_bundle(None, 'l@cset-0-1')
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
592
        tt = TreeTransform(self.tree1)
593
        trans_id = tt.trans_id_tree_file_id('link-1')
594
        tt.adjust_path('link2', tt.root, trans_id)
595
        tt.delete_contents(trans_id)
596
        tt.create_symlink('mars', trans_id)
597
        tt.apply()
598
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
599
        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
600
        tt = TreeTransform(self.tree1)
601
        trans_id = tt.trans_id_tree_file_id('link-1')
602
        tt.delete_contents(trans_id)
603
        tt.create_symlink('jupiter', trans_id)
604
        tt.apply()
605
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
606
        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
607
        tt = TreeTransform(self.tree1)
608
        trans_id = tt.trans_id_tree_file_id('link-1')
609
        tt.delete_contents(trans_id)
610
        tt.apply()
611
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
612
        self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
1185.82.96 by Aaron Bentley
Got first binary test passing
613
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
614
    def test_binary_bundle(self):
1185.82.96 by Aaron Bentley
Got first binary test passing
615
        self.tree1 = BzrDir.create_standalone_workingtree('b1')
616
        self.b1 = self.tree1.branch
617
        tt = TreeTransform(self.tree1)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
618
        
619
        # Add
620
        tt.new_file('file', tt.root, '\x00\n\x00\r\x01\n\x02\r\xff', 'binary-1')
621
        tt.new_file('file2', tt.root, '\x01\n\x02\r\x03\n\x04\r\xff', 'binary-2')
1185.82.96 by Aaron Bentley
Got first binary test passing
622
        tt.apply()
623
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
624
        self.get_valid_bundle(None, 'b@cset-0-1')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
625
626
        # Delete
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
627
        tt = TreeTransform(self.tree1)
628
        trans_id = tt.trans_id_tree_file_id('binary-1')
629
        tt.delete_contents(trans_id)
630
        tt.apply()
631
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
632
        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.
633
634
        # Rename & modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
635
        tt = TreeTransform(self.tree1)
636
        trans_id = tt.trans_id_tree_file_id('binary-2')
637
        tt.adjust_path('file3', tt.root, trans_id)
638
        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.
639
        tt.create_file('file\rcontents\x00\n\x00', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
640
        tt.apply()
641
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
642
        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.
643
644
        # Modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
645
        tt = TreeTransform(self.tree1)
646
        trans_id = tt.trans_id_tree_file_id('binary-2')
647
        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.
648
        tt.create_file('\x00file\rcontents', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
649
        tt.apply()
650
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
651
        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
652
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
653
        # Rollup
654
        self.get_valid_bundle(None, 'b@cset-0-4')
655
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
656
    def test_last_modified(self):
657
        self.tree1 = BzrDir.create_standalone_workingtree('b1')
658
        self.b1 = self.tree1.branch
659
        tt = TreeTransform(self.tree1)
660
        tt.new_file('file', tt.root, 'file', 'file')
661
        tt.apply()
662
        self.tree1.commit('create file', rev_id='a@lmod-0-1')
663
664
        tt = TreeTransform(self.tree1)
665
        trans_id = tt.trans_id_tree_file_id('file')
666
        tt.delete_contents(trans_id)
667
        tt.create_file('file2', trans_id)
668
        tt.apply()
669
        self.tree1.commit('modify text', rev_id='a@lmod-0-2a')
670
671
        other = self.get_checkout('a@lmod-0-1')
672
        tt = TreeTransform(other)
673
        trans_id = tt.trans_id_tree_file_id('file')
674
        tt.delete_contents(trans_id)
675
        tt.create_file('file2', trans_id)
676
        tt.apply()
677
        other.commit('modify text in another tree', rev_id='a@lmod-0-2b')
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
678
        _merge_helper([other.basedir, -1], [None, None],
679
                      this_dir=self.tree1.basedir)
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
680
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
681
                          verbose=False)
682
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
683
        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
684
685
    def test_hide_history(self):
686
        self.tree1 = BzrDir.create_standalone_workingtree('b1')
687
        self.b1 = self.tree1.branch
688
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
689
        open('b1/one', 'wb').write('one\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
690
        self.tree1.add('one')
691
        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.
692
        open('b1/one', 'wb').write('two\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
693
        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.
694
        open('b1/one', 'wb').write('three\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
695
        self.tree1.commit('modify', rev_id='a@cset-0-3')
696
        bundle_file = StringIO()
697
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
698
                               'a@cset-0-1', bundle_file)
699
        self.assertNotContainsRe(bundle_file.getvalue(), 'two')
700
        self.assertContainsRe(bundle_file.getvalue(), 'one')
701
        self.assertContainsRe(bundle_file.getvalue(), 'three')
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
702
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
703
    def test_unicode_bundle(self):
704
        # Handle international characters
705
        os.mkdir('b1')
706
        try:
707
            f = open(u'b1/with Dod\xe9', 'wb')
708
        except UnicodeEncodeError:
709
            raise TestSkipped("Filesystem doesn't support unicode")
710
711
        self.tree1 = self.make_branch_and_tree('b1')
712
        self.b1 = self.tree1.branch
713
714
        f.write((u'A file\n'
715
            u'With international man of mystery\n'
716
            u'William Dod\xe9\n').encode('utf-8'))
717
        f.close()
718
719
        self.tree1.add([u'with Dod\xe9'])
720
        self.tree1.commit(u'i18n commit from William Dod\xe9', 
721
                          rev_id='i18n-1', committer=u'William Dod\xe9')
722
723
        # Add
724
        bundle = self.get_valid_bundle(None, 'i18n-1')
725
726
        # Modified
727
        f = open(u'b1/with Dod\xe9', 'wb')
728
        f.write(u'Modified \xb5\n'.encode('utf8'))
729
        f.close()
730
        self.tree1.commit(u'modified', rev_id='i18n-2')
731
732
        bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
733
        
734
        # Renamed
735
        self.tree1.rename_one(u'with Dod\xe9', u'B\xe5gfors')
736
        self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
737
                          committer=u'Erik B\xe5gfors')
738
739
        bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
740
741
        # Removed
742
        self.tree1.remove([u'B\xe5gfors'])
743
        self.tree1.commit(u'removed', rev_id='i18n-4')
744
745
        bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
746
747
        # Rollup
748
        bundle = self.get_valid_bundle(None, 'i18n-4')
749
750
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
751
    def test_whitespace_bundle(self):
752
        if sys.platform in ('win32', 'cygwin'):
753
            raise TestSkipped('Windows doesn\'t support filenames'
754
                              ' with tabs or trailing spaces')
755
        self.tree1 = self.make_branch_and_tree('b1')
756
        self.b1 = self.tree1.branch
757
758
        self.build_tree(['b1/trailing space '])
759
        self.tree1.add(['trailing space '])
760
        # TODO: jam 20060701 Check for handling files with '\t' characters
761
        #       once we actually support them
762
763
        # Added
764
        self.tree1.commit('funky whitespace', rev_id='white-1')
765
766
        bundle = self.get_valid_bundle(None, 'white-1')
767
768
        # Modified
769
        open('b1/trailing space ', 'ab').write('add some text\n')
770
        self.tree1.commit('add text', rev_id='white-2')
771
772
        bundle = self.get_valid_bundle('white-1', 'white-2')
773
774
        # Renamed
775
        self.tree1.rename_one('trailing space ', ' start and end space ')
776
        self.tree1.commit('rename', rev_id='white-3')
777
778
        bundle = self.get_valid_bundle('white-2', 'white-3')
779
780
        # Removed
781
        self.tree1.remove([' start and end space '])
782
        self.tree1.commit('removed', rev_id='white-4')
783
784
        bundle = self.get_valid_bundle('white-3', 'white-4')
785
        
786
        # Now test a complet roll-up
787
        bundle = self.get_valid_bundle(None, 'white-4')
788
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
789
    def test_alt_timezone_bundle(self):
790
        self.tree1 = self.make_branch_and_tree('b1')
791
        self.b1 = self.tree1.branch
792
793
        self.build_tree(['b1/newfile'])
794
        self.tree1.add(['newfile'])
795
796
        # Asia/Colombo offset = 5 hours 30 minutes
797
        self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
798
                          timezone=19800, timestamp=1152544886.0)
799
800
        bundle = self.get_valid_bundle(None, 'tz-1')
801
        
802
        rev = bundle.revisions[0]
803
        self.assertEqual('Mon 2006-07-10 20:51:26.000000000 +0530', rev.date)
804
        self.assertEqual(19800, rev.timezone)
805
        self.assertEqual(1152544886.0, rev.timestamp)
806
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
807
    def test_bundle_root_id(self):
808
        self.tree1 = self.make_branch_and_tree('b1')
809
        self.b1 = self.tree1.branch
810
        self.tree1.commit('message', rev_id='revid1')
811
        bundle = self.get_valid_bundle(None, 'revid1')
812
        tree = bundle.revision_tree(self.b1.repository, 'revid1')
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
813
        self.assertEqual('revid1', tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
814
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
815
816
class MungedBundleTester(TestCaseWithTransport):
817
818
    def build_test_bundle(self):
819
        wt = self.make_branch_and_tree('b1')
820
821
        self.build_tree(['b1/one'])
822
        wt.add('one')
823
        wt.commit('add one', rev_id='a@cset-0-1')
824
        self.build_tree(['b1/two'])
825
        wt.add('two')
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
826
        wt.commit('add two', rev_id='a@cset-0-2',
827
                  revprops={'branch-nick':'test'})
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
828
829
        bundle_txt = StringIO()
830
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
831
                               'a@cset-0-1', bundle_txt)
832
        self.assertEqual(['a@cset-0-2'], rev_ids)
833
        bundle_txt.seek(0, 0)
834
        return bundle_txt
835
836
    def check_valid(self, bundle):
837
        """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
838
        self.assertEqual(['a@cset-0-2'],
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
839
            [r.revision_id for r in bundle.real_revisions])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
840
841
    def test_extra_whitespace(self):
842
        bundle_txt = self.build_test_bundle()
843
844
        # Seek to the end of the file
845
        # Adding one extra newline used to give us
846
        # TypeError: float() argument must be a string or a number
847
        bundle_txt.seek(0, 2)
848
        bundle_txt.write('\n')
849
        bundle_txt.seek(0)
850
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
851
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
852
        self.check_valid(bundle)
853
854
    def test_extra_whitespace_2(self):
855
        bundle_txt = self.build_test_bundle()
856
857
        # Seek to the end of the file
858
        # Adding two extra newlines used to give us
859
        # MalformedPatches: The first line of all patches should be ...
860
        bundle_txt.seek(0, 2)
861
        bundle_txt.write('\n\n')
862
        bundle_txt.seek(0)
863
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
864
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
865
        self.check_valid(bundle)
866
867
    def test_missing_trailing_whitespace(self):
868
        bundle_txt = self.build_test_bundle()
869
870
        # Remove a trailing newline, it shouldn't kill the parser
871
        raw = bundle_txt.getvalue()
872
        # The contents of the bundle don't have to be this, but this
873
        # test is concerned with the exact case where the serializer
874
        # creates a blank line at the end, and fails if that
875
        # line is stripped
876
        self.assertEqual('\n\n', raw[-2:])
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
877
        bundle_txt = StringIO(raw[:-1])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
878
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
879
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
880
        self.check_valid(bundle)
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
881
1793.3.16 by John Arbash Meinel
Add tests to ensure that we gracefully handle opening and trailing non-bundle text.
882
    def test_opening_text(self):
883
        bundle_txt = self.build_test_bundle()
884
885
        bundle_txt = StringIO("Some random\nemail comments\n"
886
                              + bundle_txt.getvalue())
887
888
        bundle = read_bundle(bundle_txt)
889
        self.check_valid(bundle)
890
891
    def test_trailing_text(self):
892
        bundle_txt = self.build_test_bundle()
893
894
        bundle_txt = StringIO(bundle_txt.getvalue() +
895
                              "Some trailing\nrandom\ntext\n")
896
897
        bundle = read_bundle(bundle_txt)
898
        self.check_valid(bundle)
899