/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bundle.py

  • Committer: Richard Wilbur
  • Date: 2016-02-04 19:07:28 UTC
  • mto: This revision was merged to the branch mainline in revision 6618.
  • Revision ID: richard.wilbur@gmail.com-20160204190728-p0zvfii6zase0fw7
Update COPYING.txt from the original http://www.gnu.org/licenses/gpl-2.0.txt  (Only differences were in whitespace.)  Thanks to Petr Stodulka for pointing out the discrepancy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2013, 2016 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
from cStringIO import StringIO
17
18
import os
18
 
try:
19
 
    import socketserver
20
 
except ImportError:
21
 
    import SocketServer as socketserver
 
19
import SocketServer
22
20
import sys
23
21
 
24
 
from .. import (
 
22
from bzrlib import (
 
23
    bzrdir,
25
24
    diff,
26
25
    errors,
 
26
    inventory,
27
27
    merge,
28
28
    osutils,
29
29
    revision as _mod_revision,
30
30
    tests,
31
31
    treebuilder,
32
32
    )
33
 
from ..bzr import (
34
 
    bzrdir,
35
 
    inventory,
36
 
    )
37
 
from ..bundle import read_mergeable_from_url
38
 
from ..bundle.apply_bundle import install_bundle, merge_bundle
39
 
from ..bundle.bundle_data import BundleTree
40
 
from ..directory_service import directories
41
 
from ..bundle.serializer import write_bundle, read_bundle, v09, v4
42
 
from ..bundle.serializer.v08 import BundleSerializerV08
43
 
from ..bundle.serializer.v09 import BundleSerializerV09
44
 
from ..bundle.serializer.v4 import BundleSerializerV4
45
 
from ..bzr import knitrepo
46
 
from ..sixish import (
47
 
    BytesIO,
48
 
    )
49
 
from . import (
 
33
from bzrlib.bundle import read_mergeable_from_url
 
34
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
 
35
from bzrlib.bundle.bundle_data import BundleTree
 
36
from bzrlib.directory_service import directories
 
37
from bzrlib.bundle.serializer import write_bundle, read_bundle, v09, v4
 
38
from bzrlib.bundle.serializer.v08 import BundleSerializerV08
 
39
from bzrlib.bundle.serializer.v09 import BundleSerializerV09
 
40
from bzrlib.bundle.serializer.v4 import BundleSerializerV4
 
41
from bzrlib.repofmt import knitrepo
 
42
from bzrlib.tests import (
50
43
    features,
51
44
    test_commit,
52
45
    test_read_bundle,
53
46
    test_server,
54
47
    )
55
 
from ..transform import TreeTransform
 
48
from bzrlib.transform import TreeTransform
56
49
 
57
50
 
58
51
def get_text(vf, key):
59
52
    """Get the fulltext for a given revision id that is present in the vf"""
60
53
    stream = vf.get_record_stream([key], 'unordered', True)
61
 
    record = next(stream)
 
54
    record = stream.next()
62
55
    return record.get_bytes_as('fulltext')
63
56
 
64
57
 
74
67
class MockTree(object):
75
68
 
76
69
    def __init__(self):
77
 
        from ..bzr.inventory import InventoryDirectory, ROOT_ID
 
70
        from bzrlib.inventory import InventoryDirectory, ROOT_ID
78
71
        object.__init__(self)
79
72
        self.paths = {ROOT_ID: ""}
80
73
        self.ids = {"": ROOT_ID}
90
83
    def all_file_ids(self):
91
84
        return set(self.paths.keys())
92
85
 
93
 
    def all_versioned_paths(self):
94
 
        return set(self.paths.values())
95
 
 
96
 
    def is_executable(self, path, file_id):
 
86
    def is_executable(self, file_id):
97
87
        # Not all the files are executable.
98
88
        return False
99
89
 
110
100
        return self.ids[parent_dir]
111
101
 
112
102
    def iter_entries(self):
113
 
        for path, file_id in self.ids.items():
 
103
        for path, file_id in self.ids.iteritems():
114
104
            yield path, self[file_id]
115
105
 
116
 
    def kind(self, path, file_id=None):
117
 
        if file_id is None:
118
 
            file_id = self.path2id(path)
 
106
    def kind(self, file_id):
119
107
        if file_id in self.contents:
120
108
            kind = 'file'
121
109
        else:
123
111
        return kind
124
112
 
125
113
    def make_entry(self, file_id, path):
126
 
        from ..bzr.inventory import (InventoryFile, InventoryDirectory,
 
114
        from bzrlib.inventory import (InventoryFile , InventoryDirectory,
127
115
            InventoryLink)
128
116
        name = os.path.basename(path)
129
 
        kind = self.kind(path, file_id)
 
117
        kind = self.kind(file_id)
130
118
        parent_id = self.parent_id(file_id)
131
 
        text_sha_1, text_size = self.contents_stats(path, file_id)
 
119
        text_sha_1, text_size = self.contents_stats(file_id)
132
120
        if kind == 'directory':
133
121
            ie = InventoryDirectory(file_id, name, parent_id)
134
122
        elif kind == 'file':
158
146
    def has_id(self, file_id):
159
147
        return self.id2path(file_id) is not None
160
148
 
161
 
    def get_file(self, path, file_id=None):
162
 
        if file_id is None:
163
 
            file_id = self.path2id(path)
164
 
        result = BytesIO()
165
 
        try:
166
 
            result.write(self.contents[file_id])
167
 
        except KeyError:
168
 
            raise errors.NoSuchFile(path)
169
 
        result.seek(0, 0)
 
149
    def get_file(self, file_id):
 
150
        result = StringIO()
 
151
        result.write(self.contents[file_id])
 
152
        result.seek(0,0)
170
153
        return result
171
154
 
172
 
    def get_file_revision(self, path, file_id=None):
173
 
        if file_id is None:
174
 
            file_id = self.path2id(path)
 
155
    def get_file_revision(self, file_id):
175
156
        return self.inventory[file_id].revision
176
157
 
177
 
    def get_file_size(self, path, file_id=None):
178
 
        if file_id is None:
179
 
            file_id = self.path2id(path)
 
158
    def get_file_size(self, file_id):
180
159
        return self.inventory[file_id].text_size
181
160
 
182
 
    def get_file_sha1(self, path, file_id=None):
183
 
        if file_id is None:
184
 
            file_id = self.path2id(path)
 
161
    def get_file_sha1(self, file_id):
185
162
        return self.inventory[file_id].text_sha1
186
163
 
187
 
    def contents_stats(self, path, file_id):
 
164
    def contents_stats(self, file_id):
188
165
        if file_id not in self.contents:
189
166
            return None, None
190
 
        text_sha1 = osutils.sha_file(self.get_file(path, file_id))
 
167
        text_sha1 = osutils.sha_file(self.get_file(file_id))
191
168
        return text_sha1, len(self.contents[file_id])
192
169
 
193
170
 
196
173
 
197
174
    def make_tree_1(self):
198
175
        mtree = MockTree()
199
 
        mtree.add_dir(b"a", "grandparent")
200
 
        mtree.add_dir(b"b", "grandparent/parent")
201
 
        mtree.add_file(b"c", "grandparent/parent/file", "Hello\n")
202
 
        mtree.add_dir(b"d", "grandparent/alt_parent")
 
176
        mtree.add_dir("a", "grandparent")
 
177
        mtree.add_dir("b", "grandparent/parent")
 
178
        mtree.add_file("c", "grandparent/parent/file", "Hello\n")
 
179
        mtree.add_dir("d", "grandparent/alt_parent")
203
180
        return BundleTree(mtree, ''), mtree
204
181
 
205
182
    def test_renames(self):
211
188
        self.assertEqual(btree.old_path("grandparent/parent/file"),
212
189
                         "grandparent/parent/file")
213
190
 
214
 
        self.assertEqual(btree.id2path(b"a"), "grandparent")
215
 
        self.assertEqual(btree.id2path(b"b"), "grandparent/parent")
216
 
        self.assertEqual(btree.id2path(b"c"), "grandparent/parent/file")
217
 
 
218
 
        self.assertEqual(btree.path2id("grandparent"), b"a")
219
 
        self.assertEqual(btree.path2id("grandparent/parent"), b"b")
220
 
        self.assertEqual(btree.path2id("grandparent/parent/file"), b"c")
221
 
 
222
 
        self.assertIs(btree.path2id("grandparent2"), None)
223
 
        self.assertIs(btree.path2id("grandparent2/parent"), None)
224
 
        self.assertIs(btree.path2id("grandparent2/parent/file"), None)
 
191
        self.assertEqual(btree.id2path("a"), "grandparent")
 
192
        self.assertEqual(btree.id2path("b"), "grandparent/parent")
 
193
        self.assertEqual(btree.id2path("c"), "grandparent/parent/file")
 
194
 
 
195
        self.assertEqual(btree.path2id("grandparent"), "a")
 
196
        self.assertEqual(btree.path2id("grandparent/parent"), "b")
 
197
        self.assertEqual(btree.path2id("grandparent/parent/file"), "c")
 
198
 
 
199
        self.assertTrue(btree.path2id("grandparent2") is None)
 
200
        self.assertTrue(btree.path2id("grandparent2/parent") is None)
 
201
        self.assertTrue(btree.path2id("grandparent2/parent/file") is None)
225
202
 
226
203
        btree.note_rename("grandparent", "grandparent2")
227
 
        self.assertIs(btree.old_path("grandparent"), None)
228
 
        self.assertIs(btree.old_path("grandparent/parent"), None)
229
 
        self.assertIs(btree.old_path("grandparent/parent/file"), None)
230
 
 
231
 
        self.assertEqual(btree.id2path(b"a"), "grandparent2")
232
 
        self.assertEqual(btree.id2path(b"b"), "grandparent2/parent")
233
 
        self.assertEqual(btree.id2path(b"c"), "grandparent2/parent/file")
234
 
 
235
 
        self.assertEqual(btree.path2id("grandparent2"), b"a")
236
 
        self.assertEqual(btree.path2id("grandparent2/parent"), b"b")
237
 
        self.assertEqual(btree.path2id("grandparent2/parent/file"), b"c")
 
204
        self.assertTrue(btree.old_path("grandparent") is None)
 
205
        self.assertTrue(btree.old_path("grandparent/parent") is None)
 
206
        self.assertTrue(btree.old_path("grandparent/parent/file") is None)
 
207
 
 
208
        self.assertEqual(btree.id2path("a"), "grandparent2")
 
209
        self.assertEqual(btree.id2path("b"), "grandparent2/parent")
 
210
        self.assertEqual(btree.id2path("c"), "grandparent2/parent/file")
 
211
 
 
212
        self.assertEqual(btree.path2id("grandparent2"), "a")
 
213
        self.assertEqual(btree.path2id("grandparent2/parent"), "b")
 
214
        self.assertEqual(btree.path2id("grandparent2/parent/file"), "c")
238
215
 
239
216
        self.assertTrue(btree.path2id("grandparent") is None)
240
217
        self.assertTrue(btree.path2id("grandparent/parent") is None)
241
218
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
242
219
 
243
220
        btree.note_rename("grandparent/parent", "grandparent2/parent2")
244
 
        self.assertEqual(btree.id2path(b"a"), "grandparent2")
245
 
        self.assertEqual(btree.id2path(b"b"), "grandparent2/parent2")
246
 
        self.assertEqual(btree.id2path(b"c"), "grandparent2/parent2/file")
 
221
        self.assertEqual(btree.id2path("a"), "grandparent2")
 
222
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
 
223
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file")
247
224
 
248
 
        self.assertEqual(btree.path2id("grandparent2"), b"a")
249
 
        self.assertEqual(btree.path2id("grandparent2/parent2"), b"b")
250
 
        self.assertEqual(btree.path2id("grandparent2/parent2/file"), b"c")
 
225
        self.assertEqual(btree.path2id("grandparent2"), "a")
 
226
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
 
227
        self.assertEqual(btree.path2id("grandparent2/parent2/file"), "c")
251
228
 
252
229
        self.assertTrue(btree.path2id("grandparent2/parent") is None)
253
230
        self.assertTrue(btree.path2id("grandparent2/parent/file") is None)
254
231
 
255
232
        btree.note_rename("grandparent/parent/file",
256
233
                          "grandparent2/parent2/file2")
257
 
        self.assertEqual(btree.id2path(b"a"), "grandparent2")
258
 
        self.assertEqual(btree.id2path(b"b"), "grandparent2/parent2")
259
 
        self.assertEqual(btree.id2path(b"c"), "grandparent2/parent2/file2")
 
234
        self.assertEqual(btree.id2path("a"), "grandparent2")
 
235
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
 
236
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file2")
260
237
 
261
 
        self.assertEqual(btree.path2id("grandparent2"), b"a")
262
 
        self.assertEqual(btree.path2id("grandparent2/parent2"), b"b")
263
 
        self.assertEqual(btree.path2id("grandparent2/parent2/file2"), b"c")
 
238
        self.assertEqual(btree.path2id("grandparent2"), "a")
 
239
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
 
240
        self.assertEqual(btree.path2id("grandparent2/parent2/file2"), "c")
264
241
 
265
242
        self.assertTrue(btree.path2id("grandparent2/parent2/file") is None)
266
243
 
269
246
        btree = self.make_tree_1()[0]
270
247
        btree.note_rename("grandparent/parent/file",
271
248
                          "grandparent/alt_parent/file")
272
 
        self.assertEqual(btree.id2path(b"c"), "grandparent/alt_parent/file")
273
 
        self.assertEqual(btree.path2id("grandparent/alt_parent/file"), b"c")
 
249
        self.assertEqual(btree.id2path("c"), "grandparent/alt_parent/file")
 
250
        self.assertEqual(btree.path2id("grandparent/alt_parent/file"), "c")
274
251
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
275
252
 
276
253
    def unified_diff(self, old, new):
277
 
        out = BytesIO()
 
254
        out = StringIO()
278
255
        diff.internal_diff("old", old, "new", new, out)
279
 
        out.seek(0, 0)
 
256
        out.seek(0,0)
280
257
        return out.read()
281
258
 
282
259
    def make_tree_2(self):
283
260
        btree = self.make_tree_1()[0]
284
261
        btree.note_rename("grandparent/parent/file",
285
262
                          "grandparent/alt_parent/file")
286
 
        self.assertTrue(btree.id2path(b"e") is None)
 
263
        self.assertTrue(btree.id2path("e") is None)
287
264
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
288
265
        btree.note_id("e", "grandparent/parent/file")
289
266
        return btree
293
270
        btree = self.make_tree_2()
294
271
        add_patch = self.unified_diff([], ["Extra cheese\n"])
295
272
        btree.note_patch("grandparent/parent/file", add_patch)
296
 
        btree.note_id(b'f', 'grandparent/parent/symlink', kind='symlink')
 
273
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
297
274
        btree.note_target('grandparent/parent/symlink', 'venus')
298
275
        self.adds_test(btree)
299
276
 
300
277
    def adds_test(self, btree):
301
 
        self.assertEqual(btree.id2path(b"e"), "grandparent/parent/file")
302
 
        self.assertEqual(btree.path2id("grandparent/parent/file"), b"e")
303
 
        self.assertEqual(btree.get_file("grandparent/parent/file").read(),
304
 
                         "Extra cheese\n")
305
 
        self.assertEqual(
306
 
            btree.get_symlink_target('grandparent/parent/symlink'), 'venus')
 
278
        self.assertEqual(btree.id2path("e"), "grandparent/parent/file")
 
279
        self.assertEqual(btree.path2id("grandparent/parent/file"), "e")
 
280
        self.assertEqual(btree.get_file("e").read(), "Extra cheese\n")
 
281
        self.assertEqual(btree.get_symlink_target('f'), 'venus')
307
282
 
308
283
    def test_adds2(self):
309
284
        """File/inventory adds, with patch-compatibile renames"""
325
300
        return btree
326
301
 
327
302
    def get_file_test(self, btree):
328
 
        self.assertEqual(btree.get_file(btree.id2path(b"e")).read(), "Lemon\n")
329
 
        self.assertEqual(btree.get_file(btree.id2path(b"c")).read(), "Hello\n")
 
303
        self.assertEqual(btree.get_file("e").read(), "Lemon\n")
 
304
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
330
305
 
331
306
    def test_get_file(self):
332
307
        """Get file contents"""
336
311
        self.get_file_test(btree)
337
312
 
338
313
    def test_get_file2(self):
339
 
        """Get file contents, with patch-compatible renames"""
 
314
        """Get file contents, with patch-compatibile renames"""
340
315
        btree = self.make_tree_3()
341
316
        btree.contents_by_id = False
342
317
        mod_patch = self.unified_diff([], ["Lemon\n"])
348
323
    def test_delete(self):
349
324
        "Deletion by bundle"
350
325
        btree = self.make_tree_1()[0]
351
 
        self.assertEqual(btree.get_file(btree.id2path(b"c")).read(), "Hello\n")
 
326
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
352
327
        btree.note_deletion("grandparent/parent/file")
353
 
        self.assertTrue(btree.id2path(b"c") is None)
354
 
        self.assertFalse(btree.is_versioned("grandparent/parent/file"))
 
328
        self.assertTrue(btree.id2path("c") is None)
 
329
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
355
330
 
356
331
    def sorted_ids(self, tree):
357
 
        ids = sorted(tree.all_file_ids())
 
332
        ids = list(tree.all_file_ids())
 
333
        ids.sort()
358
334
        return ids
359
335
 
360
336
    def test_iteration(self):
378
354
        serializer = BundleSerializerV08('0.8')
379
355
        b = self.make_branch('.', format=format)
380
356
        self.assertRaises(errors.IncompatibleBundleFormat, serializer.write,
381
 
                          b.repository, [], {}, BytesIO())
 
357
                          b.repository, [], {}, StringIO())
382
358
 
383
359
    def test_matched_bundle(self):
384
360
        """Don't raise IncompatibleBundleFormat for knit2 and bundle0.9"""
386
362
        format.repository_format = knitrepo.RepositoryFormatKnit3()
387
363
        serializer = BundleSerializerV09('0.9')
388
364
        b = self.make_branch('.', format=format)
389
 
        serializer.write(b.repository, [], {}, BytesIO())
 
365
        serializer.write(b.repository, [], {}, StringIO())
390
366
 
391
367
    def test_mismatched_model(self):
392
368
        """Try copying a bundle from knit2 to knit1"""
393
369
        format = bzrdir.BzrDirMetaFormat1()
394
370
        format.repository_format = knitrepo.RepositoryFormatKnit3()
395
371
        source = self.make_branch_and_tree('source', format=format)
396
 
        source.commit('one', rev_id=b'one-id')
397
 
        source.commit('two', rev_id=b'two-id')
398
 
        text = BytesIO()
 
372
        source.commit('one', rev_id='one-id')
 
373
        source.commit('two', rev_id='two-id')
 
374
        text = StringIO()
399
375
        write_bundle(source.branch.repository, 'two-id', 'null:', text,
400
376
                     format='0.9')
401
377
        text.seek(0)
426
402
        return tests.TestCaseWithTransport.make_branch(self, path, format)
427
403
 
428
404
    def create_bundle_text(self, base_rev_id, rev_id):
429
 
        bundle_txt = BytesIO()
 
405
        bundle_txt = StringIO()
430
406
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id,
431
407
                               bundle_txt, format=self.format)
432
408
        bundle_txt.seek(0)
481
457
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
482
458
        new_text = bundle_txt.getvalue().replace('executable:no',
483
459
                                               'executable:yes')
484
 
        bundle_txt = BytesIO(new_text)
 
460
        bundle_txt = StringIO(new_text)
485
461
        bundle = read_bundle(bundle_txt)
486
462
        self.valid_apply_bundle(base_rev_id, bundle)
487
463
        return bundle
488
464
 
489
465
    def test_non_bundle(self):
490
466
        self.assertRaises(errors.NotABundle,
491
 
                          read_bundle, BytesIO(b'#!/bin/sh\n'))
 
467
                          read_bundle, StringIO('#!/bin/sh\n'))
492
468
 
493
469
    def test_malformed(self):
494
470
        self.assertRaises(errors.BadBundle, read_bundle,
495
 
                          BytesIO(b'# Bazaar revision bundle v'))
 
471
                          StringIO('# Bazaar revision bundle v'))
496
472
 
497
473
    def test_crlf_bundle(self):
498
474
        try:
499
 
            read_bundle(BytesIO(b'# Bazaar revision bundle v0.8\r\n'))
 
475
            read_bundle(StringIO('# Bazaar revision bundle v0.8\r\n'))
500
476
        except errors.BadBundle:
501
477
            # It is currently permitted for bundles with crlf line endings to
502
478
            # make read_bundle raise a BadBundle, but this should be fixed.
513
489
            if not os.path.exists(checkout_dir):
514
490
                os.mkdir(checkout_dir)
515
491
        tree = self.make_branch_and_tree(checkout_dir)
516
 
        s = BytesIO()
 
492
        s = StringIO()
517
493
        ancestors = write_bundle(self.b1.repository, rev_id, 'null:', s,
518
494
                                 format=self.format)
519
495
        s.seek(0)
532
508
                                 % (ancestor,))
533
509
 
534
510
                # Now check that the file contents are all correct
535
 
                for path in old.all_versioned_paths():
 
511
                for inventory_id in old.all_file_ids():
536
512
                    try:
537
 
                        old_file = old.get_file(path)
 
513
                        old_file = old.get_file(inventory_id)
538
514
                    except errors.NoSuchFile:
539
515
                        continue
540
 
                    self.assertEqual(
541
 
                            old_file.read(), new.get_file(path).read())
 
516
                    if old_file is None:
 
517
                        continue
 
518
                    self.assertEqual(old_file.read(),
 
519
                                     new.get_file(inventory_id).read())
542
520
            finally:
543
521
                new.unlock()
544
522
                old.unlock()
567
545
        original_parents = to_tree.get_parent_ids()
568
546
        self.assertIs(repository.has_revision(base_rev_id), True)
569
547
        for rev in info.real_revisions:
570
 
            self.assertTrue(not repository.has_revision(rev.revision_id),
571
 
                            'Revision {%s} present before applying bundle'
572
 
                            % rev.revision_id)
 
548
            self.assert_(not repository.has_revision(rev.revision_id),
 
549
                'Revision {%s} present before applying bundle'
 
550
                % rev.revision_id)
573
551
        merge_bundle(info, to_tree, True, merge.Merge3Merger, False, False)
574
552
 
575
553
        for rev in info.real_revisions:
576
 
            self.assertTrue(repository.has_revision(rev.revision_id),
577
 
                            'Missing revision {%s} after applying bundle'
578
 
                            % rev.revision_id)
 
554
            self.assert_(repository.has_revision(rev.revision_id),
 
555
                'Missing revision {%s} after applying bundle'
 
556
                % rev.revision_id)
579
557
 
580
 
        self.assertTrue(to_tree.branch.repository.has_revision(info.target))
 
558
        self.assert_(to_tree.branch.repository.has_revision(info.target))
581
559
        # Do we also want to verify that all the texts have been added?
582
560
 
583
561
        self.assertEqual(original_parents + [info.target],
584
 
                         to_tree.get_parent_ids())
 
562
            to_tree.get_parent_ids())
585
563
 
586
564
        rev = info.real_revisions[-1]
587
565
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
598
576
 
599
577
        for path, status, kind, fileid, entry in base_files:
600
578
            # Check that the meta information is the same
601
 
            self.assertEqual(base_tree.get_file_size(path, fileid),
602
 
                    to_tree.get_file_size(to_tree.id2path(fileid)))
603
 
            self.assertEqual(base_tree.get_file_sha1(path, fileid),
604
 
                    to_tree.get_file_sha1(to_tree.id2path(fileid)))
 
579
            self.assertEqual(base_tree.get_file_size(fileid),
 
580
                    to_tree.get_file_size(fileid))
 
581
            self.assertEqual(base_tree.get_file_sha1(fileid),
 
582
                    to_tree.get_file_sha1(fileid))
605
583
            # Check that the contents are the same
606
584
            # This is pretty expensive
607
585
            # self.assertEqual(base_tree.get_file(fileid).read(),
611
589
        self.tree1 = self.make_branch_and_tree('b1')
612
590
        self.b1 = self.tree1.branch
613
591
 
614
 
        self.build_tree_contents([('b1/one', b'one\n')])
615
 
        self.tree1.add('one', b'one-id')
616
 
        self.tree1.set_root_id(b'root-id')
617
 
        self.tree1.commit('add one', rev_id=b'a@cset-0-1')
 
592
        self.build_tree_contents([('b1/one', 'one\n')])
 
593
        self.tree1.add('one', 'one-id')
 
594
        self.tree1.set_root_id('root-id')
 
595
        self.tree1.commit('add one', rev_id='a@cset-0-1')
618
596
 
619
 
        bundle = self.get_valid_bundle('null:', b'a@cset-0-1')
 
597
        bundle = self.get_valid_bundle('null:', 'a@cset-0-1')
620
598
 
621
599
        # Make sure we can handle files with spaces, tabs, other
622
600
        # bogus characters
630
608
                , 'b1/sub/sub/'
631
609
                , 'b1/sub/sub/nonempty.txt'
632
610
                ])
633
 
        self.build_tree_contents([('b1/sub/sub/emptyfile.txt', b''),
634
 
                                  ('b1/dir/nolastnewline.txt', b'bloop')])
 
611
        self.build_tree_contents([('b1/sub/sub/emptyfile.txt', ''),
 
612
                                  ('b1/dir/nolastnewline.txt', 'bloop')])
635
613
        tt = TreeTransform(self.tree1)
636
614
        tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
637
615
        tt.apply()
638
616
        # have to fix length of file-id so that we can predictably rewrite
639
617
        # a (length-prefixed) record containing it later.
640
 
        self.tree1.add('with space.txt', b'withspace-id')
 
618
        self.tree1.add('with space.txt', 'withspace-id')
641
619
        self.tree1.add([
642
620
                  'dir'
643
621
                , 'dir/filein subdir.c'
649
627
                , 'sub/sub/nonempty.txt'
650
628
                , 'sub/sub/emptyfile.txt'
651
629
                ])
652
 
        self.tree1.commit('add whitespace', rev_id=b'a@cset-0-2')
 
630
        self.tree1.commit('add whitespace', rev_id='a@cset-0-2')
653
631
 
654
 
        bundle = self.get_valid_bundle('a@cset-0-1', b'a@cset-0-2')
 
632
        bundle = self.get_valid_bundle('a@cset-0-1', 'a@cset-0-2')
655
633
 
656
634
        # Check a rollup bundle
657
635
        bundle = self.get_valid_bundle('null:', 'a@cset-0-2')
663
641
                , 'sub/sub'
664
642
                ])
665
643
        tt = TreeTransform(self.tree1)
666
 
        trans_id = tt.trans_id_tree_path('executable')
 
644
        trans_id = tt.trans_id_tree_file_id('exe-1')
667
645
        tt.set_executability(False, trans_id)
668
646
        tt.apply()
669
 
        self.tree1.commit('removed', rev_id=b'a@cset-0-3')
 
647
        self.tree1.commit('removed', rev_id='a@cset-0-3')
670
648
 
671
649
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
672
650
        self.assertRaises((errors.TestamentMismatch,
678
656
 
679
657
        # Now move the directory
680
658
        self.tree1.rename_one('dir', 'sub/dir')
681
 
        self.tree1.commit('rename dir', rev_id=b'a@cset-0-4')
 
659
        self.tree1.commit('rename dir', rev_id='a@cset-0-4')
682
660
 
683
661
        bundle = self.get_valid_bundle('a@cset-0-3', 'a@cset-0-4')
684
662
        # Check a rollup bundle
691
669
        with open('b1/sub/dir/nolastnewline.txt', 'ab') as f: f.write('\n')
692
670
        self.tree1.rename_one('sub/dir/ pre space',
693
671
                              'sub/ start space')
694
 
        self.tree1.commit('Modified files', rev_id=b'a@cset-0-5')
 
672
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
695
673
        bundle = self.get_valid_bundle('a@cset-0-4', 'a@cset-0-5')
696
674
 
697
675
        self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
698
676
        self.tree1.rename_one('with space.txt', 'WithCaps.txt')
699
677
        self.tree1.rename_one('temp', 'with space.txt')
700
 
        self.tree1.commit(u'swap filenames', rev_id=b'a@cset-0-6',
 
678
        self.tree1.commit(u'swap filenames', rev_id='a@cset-0-6',
701
679
                          verbose=False)
702
680
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
703
681
        other = self.get_checkout('a@cset-0-5')
707
685
                                       'a@cset-0-5')
708
686
        self.assertEqualDiff(tree1_inv, tree2_inv)
709
687
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
710
 
        other.commit('rename file', rev_id=b'a@cset-0-6b')
 
688
        other.commit('rename file', rev_id='a@cset-0-6b')
711
689
        self.tree1.merge_from_branch(other.branch)
712
 
        self.tree1.commit(u'Merge', rev_id=b'a@cset-0-7',
 
690
        self.tree1.commit(u'Merge', rev_id='a@cset-0-7',
713
691
                          verbose=False)
714
692
        bundle = self.get_valid_bundle('a@cset-0-6', 'a@cset-0-7')
715
693
 
723
701
        tt = TreeTransform(self.tree1)
724
702
        tt.new_symlink(link_name, tt.root, link_target, link_id)
725
703
        tt.apply()
726
 
        self.tree1.commit('add symlink', rev_id=b'l@cset-0-1')
 
704
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
727
705
        bundle = self.get_valid_bundle('null:', 'l@cset-0-1')
728
 
        if getattr(bundle, 'revision_tree', None) is not None:
 
706
        if getattr(bundle ,'revision_tree', None) is not None:
729
707
            # Not all bundle formats supports revision_tree
730
708
            bund_tree = bundle.revision_tree(self.b1.repository, 'l@cset-0-1')
731
 
            self.assertEqual(link_target, bund_tree.get_symlink_target(link_name))
 
709
            self.assertEqual(link_target, bund_tree.get_symlink_target(link_id))
732
710
 
733
711
        tt = TreeTransform(self.tree1)
734
 
        trans_id = tt.trans_id_tree_path(link_name)
 
712
        trans_id = tt.trans_id_tree_file_id(link_id)
735
713
        tt.adjust_path('link2', tt.root, trans_id)
736
714
        tt.delete_contents(trans_id)
737
715
        tt.create_symlink(new_link_target, trans_id)
738
716
        tt.apply()
739
 
        self.tree1.commit('rename and change symlink', rev_id=b'l@cset-0-2')
 
717
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
740
718
        bundle = self.get_valid_bundle('l@cset-0-1', 'l@cset-0-2')
741
 
        if getattr(bundle, 'revision_tree', None) is not None:
 
719
        if getattr(bundle ,'revision_tree', None) is not None:
742
720
            # Not all bundle formats supports revision_tree
743
721
            bund_tree = bundle.revision_tree(self.b1.repository, 'l@cset-0-2')
744
722
            self.assertEqual(new_link_target,
745
 
                             bund_tree.get_symlink_target('link2'))
 
723
                             bund_tree.get_symlink_target(link_id))
746
724
 
747
725
        tt = TreeTransform(self.tree1)
748
 
        trans_id = tt.trans_id_tree_path('link2')
 
726
        trans_id = tt.trans_id_tree_file_id(link_id)
749
727
        tt.delete_contents(trans_id)
750
728
        tt.create_symlink('jupiter', trans_id)
751
729
        tt.apply()
752
 
        self.tree1.commit('just change symlink target', rev_id=b'l@cset-0-3')
 
730
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
753
731
        bundle = self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
754
732
 
755
733
        tt = TreeTransform(self.tree1)
756
 
        trans_id = tt.trans_id_tree_path('link2')
 
734
        trans_id = tt.trans_id_tree_file_id(link_id)
757
735
        tt.delete_contents(trans_id)
758
736
        tt.apply()
759
 
        self.tree1.commit('Delete symlink', rev_id=b'l@cset-0-4')
 
737
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
760
738
        bundle = self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
761
739
 
762
740
    def test_symlink_bundle(self):
778
756
        tt.new_file('file2', tt.root, '\x01\n\x02\r\x03\n\x04\r\xff',
779
757
            'binary-2')
780
758
        tt.apply()
781
 
        self.tree1.commit('add binary', rev_id=b'b@cset-0-1')
 
759
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
782
760
        self.get_valid_bundle('null:', 'b@cset-0-1')
783
761
 
784
762
        # Delete
785
763
        tt = TreeTransform(self.tree1)
786
 
        trans_id = tt.trans_id_tree_path('file')
 
764
        trans_id = tt.trans_id_tree_file_id('binary-1')
787
765
        tt.delete_contents(trans_id)
788
766
        tt.apply()
789
 
        self.tree1.commit('delete binary', rev_id=b'b@cset-0-2')
 
767
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
790
768
        self.get_valid_bundle('b@cset-0-1', 'b@cset-0-2')
791
769
 
792
770
        # Rename & modify
793
771
        tt = TreeTransform(self.tree1)
794
 
        trans_id = tt.trans_id_tree_path('file2')
 
772
        trans_id = tt.trans_id_tree_file_id('binary-2')
795
773
        tt.adjust_path('file3', tt.root, trans_id)
796
774
        tt.delete_contents(trans_id)
797
775
        tt.create_file('file\rcontents\x00\n\x00', trans_id)
798
776
        tt.apply()
799
 
        self.tree1.commit('rename and modify binary', rev_id=b'b@cset-0-3')
 
777
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
800
778
        self.get_valid_bundle('b@cset-0-2', 'b@cset-0-3')
801
779
 
802
780
        # Modify
803
781
        tt = TreeTransform(self.tree1)
804
 
        trans_id = tt.trans_id_tree_path('file3')
 
782
        trans_id = tt.trans_id_tree_file_id('binary-2')
805
783
        tt.delete_contents(trans_id)
806
784
        tt.create_file('\x00file\rcontents', trans_id)
807
785
        tt.apply()
808
 
        self.tree1.commit('just modify binary', rev_id=b'b@cset-0-4')
 
786
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
809
787
        self.get_valid_bundle('b@cset-0-3', 'b@cset-0-4')
810
788
 
811
789
        # Rollup
817
795
        tt = TreeTransform(self.tree1)
818
796
        tt.new_file('file', tt.root, 'file', 'file')
819
797
        tt.apply()
820
 
        self.tree1.commit('create file', rev_id=b'a@lmod-0-1')
 
798
        self.tree1.commit('create file', rev_id='a@lmod-0-1')
821
799
 
822
800
        tt = TreeTransform(self.tree1)
823
 
        trans_id = tt.trans_id_tree_path('file')
 
801
        trans_id = tt.trans_id_tree_file_id('file')
824
802
        tt.delete_contents(trans_id)
825
803
        tt.create_file('file2', trans_id)
826
804
        tt.apply()
827
 
        self.tree1.commit('modify text', rev_id=b'a@lmod-0-2a')
 
805
        self.tree1.commit('modify text', rev_id='a@lmod-0-2a')
828
806
 
829
807
        other = self.get_checkout('a@lmod-0-1')
830
808
        tt = TreeTransform(other)
831
 
        trans_id = tt.trans_id_tree_path('file2')
 
809
        trans_id = tt.trans_id_tree_file_id('file')
832
810
        tt.delete_contents(trans_id)
833
811
        tt.create_file('file2', trans_id)
834
812
        tt.apply()
835
 
        other.commit('modify text in another tree', rev_id=b'a@lmod-0-2b')
 
813
        other.commit('modify text in another tree', rev_id='a@lmod-0-2b')
836
814
        self.tree1.merge_from_branch(other.branch)
837
 
        self.tree1.commit(u'Merge', rev_id=b'a@lmod-0-3',
 
815
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
838
816
                          verbose=False)
839
 
        self.tree1.commit(u'Merge', rev_id=b'a@lmod-0-4')
 
817
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
840
818
        bundle = self.get_valid_bundle('a@lmod-0-2a', 'a@lmod-0-4')
841
819
 
842
820
    def test_hide_history(self):
843
821
        self.tree1 = self.make_branch_and_tree('b1')
844
822
        self.b1 = self.tree1.branch
845
823
 
846
 
        with open('b1/one', 'wb') as f: f.write(b'one\n')
 
824
        with open('b1/one', 'wb') as f: f.write('one\n')
847
825
        self.tree1.add('one')
848
 
        self.tree1.commit('add file', rev_id=b'a@cset-0-1')
849
 
        with open('b1/one', 'wb') as f: f.write(b'two\n')
850
 
        self.tree1.commit('modify', rev_id=b'a@cset-0-2')
851
 
        with open('b1/one', 'wb') as f: f.write(b'three\n')
852
 
        self.tree1.commit('modify', rev_id=b'a@cset-0-3')
853
 
        bundle_file = BytesIO()
 
826
        self.tree1.commit('add file', rev_id='a@cset-0-1')
 
827
        with open('b1/one', 'wb') as f: f.write('two\n')
 
828
        self.tree1.commit('modify', rev_id='a@cset-0-2')
 
829
        with open('b1/one', 'wb') as f: f.write('three\n')
 
830
        self.tree1.commit('modify', rev_id='a@cset-0-3')
 
831
        bundle_file = StringIO()
854
832
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
855
833
                               'a@cset-0-1', bundle_file, format=self.format)
856
834
        self.assertNotContainsRe(bundle_file.getvalue(), '\btwo\b')
860
838
    def test_bundle_same_basis(self):
861
839
        """Ensure using the basis as the target doesn't cause an error"""
862
840
        self.tree1 = self.make_branch_and_tree('b1')
863
 
        self.tree1.commit('add file', rev_id=b'a@cset-0-1')
864
 
        bundle_file = BytesIO()
 
841
        self.tree1.commit('add file', rev_id='a@cset-0-1')
 
842
        bundle_file = StringIO()
865
843
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-1',
866
844
                               'a@cset-0-1', bundle_file)
867
845
 
883
861
            u'William Dod\xe9\n').encode('utf-8'))
884
862
        f.close()
885
863
 
886
 
        self.tree1.add([u'with Dod\N{Euro Sign}'], [b'withdod-id'])
 
864
        self.tree1.add([u'with Dod\N{Euro Sign}'], ['withdod-id'])
887
865
        self.tree1.commit(u'i18n commit from William Dod\xe9',
888
 
                          rev_id=b'i18n-1', committer=u'William Dod\xe9')
 
866
                          rev_id='i18n-1', committer=u'William Dod\xe9')
889
867
 
890
868
        # Add
891
869
        bundle = self.get_valid_bundle('null:', 'i18n-1')
894
872
        f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
895
873
        f.write(u'Modified \xb5\n'.encode('utf8'))
896
874
        f.close()
897
 
        self.tree1.commit(u'modified', rev_id=b'i18n-2')
 
875
        self.tree1.commit(u'modified', rev_id='i18n-2')
898
876
 
899
877
        bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
900
878
 
901
879
        # Renamed
902
880
        self.tree1.rename_one(u'with Dod\N{Euro Sign}', u'B\N{Euro Sign}gfors')
903
 
        self.tree1.commit(u'renamed, the new i18n man', rev_id=b'i18n-3',
 
881
        self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
904
882
                          committer=u'Erik B\xe5gfors')
905
883
 
906
884
        bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
907
885
 
908
886
        # Removed
909
887
        self.tree1.remove([u'B\N{Euro Sign}gfors'])
910
 
        self.tree1.commit(u'removed', rev_id=b'i18n-4')
 
888
        self.tree1.commit(u'removed', rev_id='i18n-4')
911
889
 
912
890
        bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
913
891
 
928
906
        #       once we actually support them
929
907
 
930
908
        # Added
931
 
        self.tree1.commit('funky whitespace', rev_id=b'white-1')
 
909
        self.tree1.commit('funky whitespace', rev_id='white-1')
932
910
 
933
911
        bundle = self.get_valid_bundle('null:', 'white-1')
934
912
 
935
913
        # Modified
936
914
        with open('b1/trailing space ', 'ab') as f: f.write('add some text\n')
937
 
        self.tree1.commit('add text', rev_id=b'white-2')
 
915
        self.tree1.commit('add text', rev_id='white-2')
938
916
 
939
917
        bundle = self.get_valid_bundle('white-1', 'white-2')
940
918
 
941
919
        # Renamed
942
920
        self.tree1.rename_one('trailing space ', ' start and end space ')
943
 
        self.tree1.commit('rename', rev_id=b'white-3')
 
921
        self.tree1.commit('rename', rev_id='white-3')
944
922
 
945
923
        bundle = self.get_valid_bundle('white-2', 'white-3')
946
924
 
947
925
        # Removed
948
926
        self.tree1.remove([' start and end space '])
949
 
        self.tree1.commit('removed', rev_id=b'white-4')
 
927
        self.tree1.commit('removed', rev_id='white-4')
950
928
 
951
929
        bundle = self.get_valid_bundle('white-3', 'white-4')
952
930
 
964
942
        builder.finish_tree()
965
943
 
966
944
        # Asia/Colombo offset = 5 hours 30 minutes
967
 
        self.tree1.commit('non-hour offset timezone', rev_id=b'tz-1',
 
945
        self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
968
946
                          timezone=19800, timestamp=1152544886.0)
969
947
 
970
948
        bundle = self.get_valid_bundle('null:', 'tz-1')
978
956
    def test_bundle_root_id(self):
979
957
        self.tree1 = self.make_branch_and_tree('b1')
980
958
        self.b1 = self.tree1.branch
981
 
        self.tree1.commit('message', rev_id=b'revid1')
 
959
        self.tree1.commit('message', rev_id='revid1')
982
960
        bundle = self.get_valid_bundle('null:', 'revid1')
983
961
        tree = self.get_bundle_tree(bundle, 'revid1')
984
 
        root_revision = tree.get_file_revision(u'', tree.get_root_id())
 
962
        root_revision = tree.get_file_revision(tree.get_root_id())
985
963
        self.assertEqual('revid1', root_revision)
986
964
 
987
965
    def test_install_revisions(self):
988
966
        self.tree1 = self.make_branch_and_tree('b1')
989
967
        self.b1 = self.tree1.branch
990
 
        self.tree1.commit('message', rev_id=b'rev2a')
 
968
        self.tree1.commit('message', rev_id='rev2a')
991
969
        bundle = self.get_valid_bundle('null:', 'rev2a')
992
970
        branch2 = self.make_branch('b2')
993
971
        self.assertFalse(branch2.repository.has_revision('rev2a'))
1001
979
        tree.lock_write()
1002
980
        self.addCleanup(tree.unlock)
1003
981
        tree.add([''], ['TREE_ROOT'])
1004
 
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id=b'rev1')
 
982
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1005
983
        self.b1 = tree.branch
1006
984
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
1007
985
        bundle = read_bundle(bundle_sio)
1018
996
        self.addCleanup(tree.unlock)
1019
997
 
1020
998
        tree.add([''], ['TREE_ROOT'])
1021
 
        tree.commit('One', rev_id=b'rev1',
 
999
        tree.commit('One', rev_id='rev1',
1022
1000
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
1023
1001
        self.b1 = tree.branch
1024
1002
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
1041
1019
        # whitespace.
1042
1020
        # However, Testaments assert than they are str(), and thus should not
1043
1021
        # be Unicode.
1044
 
        tree.commit('One', rev_id=b'rev1',
 
1022
        tree.commit('One', rev_id='rev1',
1045
1023
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
1046
1024
        self.b1 = tree.branch
1047
1025
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
1055
1033
    def test_bundle_with_ghosts(self):
1056
1034
        tree = self.make_branch_and_tree('tree')
1057
1035
        self.b1 = tree.branch
1058
 
        self.build_tree_contents([('tree/file', b'content1')])
 
1036
        self.build_tree_contents([('tree/file', 'content1')])
1059
1037
        tree.add(['file'])
1060
1038
        tree.commit('rev1')
1061
 
        self.build_tree_contents([('tree/file', b'content2')])
1062
 
        tree.add_parent_tree_id(b'ghost')
1063
 
        tree.commit('rev2', rev_id=b'rev2')
1064
 
        bundle = self.get_valid_bundle(b'null:', b'rev2')
 
1039
        self.build_tree_contents([('tree/file', 'content2')])
 
1040
        tree.add_parent_tree_id('ghost')
 
1041
        tree.commit('rev2', rev_id='rev2')
 
1042
        bundle = self.get_valid_bundle('null:', 'rev2')
1065
1043
 
1066
1044
    def make_simple_tree(self, format=None):
1067
1045
        tree = self.make_branch_and_tree('b1', format=format)
1072
1050
 
1073
1051
    def test_across_serializers(self):
1074
1052
        tree = self.make_simple_tree('knit')
1075
 
        tree.commit('hello', rev_id=b'rev1')
1076
 
        tree.commit('hello', rev_id=b'rev2')
 
1053
        tree.commit('hello', rev_id='rev1')
 
1054
        tree.commit('hello', rev_id='rev2')
1077
1055
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
1078
1056
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1079
1057
        bundle.install_revisions(repo)
1083
1061
 
1084
1062
    def make_repo_with_installed_revisions(self):
1085
1063
        tree = self.make_simple_tree('knit')
1086
 
        tree.commit('hello', rev_id=b'rev1')
1087
 
        tree.commit('hello', rev_id=b'rev2')
 
1064
        tree.commit('hello', rev_id='rev1')
 
1065
        tree.commit('hello', rev_id='rev2')
1088
1066
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
1089
1067
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1090
1068
        bundle.install_revisions(repo)
1109
1087
 
1110
1088
    def test_across_models_incompatible(self):
1111
1089
        tree = self.make_simple_tree('dirstate-with-subtree')
1112
 
        tree.commit('hello', rev_id=b'rev1')
1113
 
        tree.commit('hello', rev_id=b'rev2')
 
1090
        tree.commit('hello', rev_id='rev1')
 
1091
        tree.commit('hello', rev_id='rev2')
1114
1092
        try:
1115
1093
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
1116
1094
        except errors.IncompatibleBundleFormat:
1124
1102
 
1125
1103
    def test_get_merge_request(self):
1126
1104
        tree = self.make_simple_tree()
1127
 
        tree.commit('hello', rev_id=b'rev1')
1128
 
        tree.commit('hello', rev_id=b'rev2')
 
1105
        tree.commit('hello', rev_id='rev1')
 
1106
        tree.commit('hello', rev_id='rev2')
1129
1107
        bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
1130
1108
        result = bundle.get_merge_request(tree.branch.repository)
1131
1109
        self.assertEqual((None, 'rev1', 'inapplicable'), result)
1137
1115
        subtree = self.make_branch_and_tree('tree/subtree',
1138
1116
                                            format='dirstate-with-subtree')
1139
1117
        tree.add('subtree')
1140
 
        tree.commit('hello', rev_id=b'rev1')
 
1118
        tree.commit('hello', rev_id='rev1')
1141
1119
        try:
1142
1120
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
1143
1121
        except errors.IncompatibleBundleFormat:
1154
1132
        self.tree1 = self.make_branch_and_tree('tree')
1155
1133
        self.b1 = self.tree1.branch
1156
1134
        try:
1157
 
            self.tree1.commit('Revision/id/with/slashes', rev_id=b'rev/id')
 
1135
            self.tree1.commit('Revision/id/with/slashes', rev_id='rev/id')
1158
1136
        except ValueError:
1159
1137
            raise tests.TestSkipped(
1160
1138
                "Repository doesn't support revision ids with slashes")
1165
1143
        self.tree1 = self.make_branch_and_tree('tree')
1166
1144
        self.b1 = self.tree1.branch
1167
1145
        # rev1 is not present in bundle, done by fetch
1168
 
        self.build_tree_contents([('tree/file2', b'contents1')])
1169
 
        self.tree1.add('file2', b'file2-id')
1170
 
        self.tree1.commit('rev1', rev_id=b'reva')
1171
 
        self.build_tree_contents([('tree/file3', b'contents2')])
 
1146
        self.build_tree_contents([('tree/file2', 'contents1')])
 
1147
        self.tree1.add('file2', 'file2-id')
 
1148
        self.tree1.commit('rev1', rev_id='reva')
 
1149
        self.build_tree_contents([('tree/file3', 'contents2')])
1172
1150
        # rev2 is present in bundle, and done by fetch
1173
1151
        # having file1 in the bunle causes file1's versionedfile to be opened.
1174
 
        self.tree1.add('file3', b'file3-id')
 
1152
        self.tree1.add('file3', 'file3-id')
1175
1153
        self.tree1.commit('rev2')
1176
1154
        # Updating file2 should not cause an attempt to add to file1's vf
1177
 
        target = self.tree1.controldir.sprout('target').open_workingtree()
1178
 
        self.build_tree_contents([('tree/file2', b'contents3')])
1179
 
        self.tree1.commit('rev3', rev_id=b'rev3')
 
1155
        target = self.tree1.bzrdir.sprout('target').open_workingtree()
 
1156
        self.build_tree_contents([('tree/file2', 'contents3')])
 
1157
        self.tree1.commit('rev3', rev_id='rev3')
1180
1158
        bundle = self.get_valid_bundle('reva', 'rev3')
1181
1159
        if getattr(bundle, 'get_bundle_reader', None) is None:
1182
1160
            raise tests.TestSkipped('Bundle format cannot provide reader')
1183
1161
        # be sure that file1 comes before file2
1184
1162
        for b, m, k, r, f in bundle.get_bundle_reader().iter_records():
1185
 
            if f == b'file3-id':
 
1163
            if f == 'file3-id':
1186
1164
                break
1187
 
            self.assertNotEqual(f, b'file2-id')
 
1165
            self.assertNotEqual(f, 'file2-id')
1188
1166
        bundle.install_revisions(target.branch.repository)
1189
1167
 
1190
1168
 
1198
1176
        tree.lock_write()
1199
1177
        self.addCleanup(tree.unlock)
1200
1178
        tree.add([''], ['TREE_ROOT'])
1201
 
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id=b'rev1')
 
1179
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1202
1180
        self.b1 = tree.branch
1203
1181
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
1204
1182
        self.assertContainsRe(bundle_sio.getvalue(),
1230
1208
        tree.lock_write()
1231
1209
        self.addCleanup(tree.unlock)
1232
1210
        tree.add([''], ['TREE_ROOT'])
1233
 
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id=b'rev1')
 
1211
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1234
1212
        self.b1 = tree.branch
1235
1213
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
1236
1214
        txt = bundle_sio.getvalue()
1237
1215
        loc = txt.find('#   empty: ') + len('#   empty:')
1238
1216
        # Create a new bundle, which strips the trailing space after empty
1239
 
        bundle_sio = BytesIO(txt[:loc] + txt[loc+1:])
 
1217
        bundle_sio = StringIO(txt[:loc] + txt[loc+1:])
1240
1218
 
1241
1219
        self.assertContainsRe(bundle_sio.getvalue(),
1242
1220
                              '# properties:\n'
1258
1236
        self.addCleanup(tree.unlock)
1259
1237
 
1260
1238
        tree.add([''], ['TREE_ROOT'])
1261
 
        tree.commit('One', rev_id=b'rev1',
 
1239
        tree.commit('One', rev_id='rev1',
1262
1240
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
1263
1241
        self.b1 = tree.branch
1264
1242
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
1289
1267
        # whitespace.
1290
1268
        # However, Testaments assert than they are str(), and thus should not
1291
1269
        # be Unicode.
1292
 
        tree.commit('One', rev_id=b'rev1',
 
1270
        tree.commit('One', rev_id='rev1',
1293
1271
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
1294
1272
        self.b1 = tree.branch
1295
1273
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
1357
1335
            self.assertEqual(len(branch_rev.parent_ids),
1358
1336
                             len(bundle_rev.parent_ids))
1359
1337
        self.assertEqual(set(rev_ids),
1360
 
                         {r.revision_id for r in bundle.real_revisions})
 
1338
                         set([r.revision_id for r in bundle.real_revisions]))
1361
1339
        self.valid_apply_bundle(base_rev_id, bundle,
1362
1340
                                   checkout_dir=checkout_dir)
1363
1341
 
1369
1347
 
1370
1348
        :return: The in-memory bundle
1371
1349
        """
1372
 
        from ..bundle import serializer
 
1350
        from bzrlib.bundle import serializer
1373
1351
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1374
 
        new_text = self.get_raw(BytesIO(b''.join(bundle_txt)))
 
1352
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
1375
1353
        new_text = new_text.replace('<file file_id="exe-1"',
1376
1354
                                    '<file executable="y" file_id="exe-1"')
1377
1355
        new_text = new_text.replace('B260', 'B275')
1378
 
        bundle_txt = BytesIO()
 
1356
        bundle_txt = StringIO()
1379
1357
        bundle_txt.write(serializer._get_bundle_header('4'))
1380
1358
        bundle_txt.write('\n')
1381
1359
        bundle_txt.write(new_text.encode('bz2'))
1385
1363
        return bundle
1386
1364
 
1387
1365
    def create_bundle_text(self, base_rev_id, rev_id):
1388
 
        bundle_txt = BytesIO()
 
1366
        bundle_txt = StringIO()
1389
1367
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id,
1390
1368
                               bundle_txt, format=self.format)
1391
1369
        bundle_txt.seek(0)
1403
1381
 
1404
1382
    def test_creation(self):
1405
1383
        tree = self.make_branch_and_tree('tree')
1406
 
        self.build_tree_contents([('tree/file', b'contents1\nstatic\n')])
 
1384
        self.build_tree_contents([('tree/file', 'contents1\nstatic\n')])
1407
1385
        tree.add('file', 'fileid-2')
1408
 
        tree.commit('added file', rev_id=b'rev1')
1409
 
        self.build_tree_contents([('tree/file', b'contents2\nstatic\n')])
1410
 
        tree.commit('changed file', rev_id=b'rev2')
1411
 
        s = BytesIO()
 
1386
        tree.commit('added file', rev_id='rev1')
 
1387
        self.build_tree_contents([('tree/file', 'contents2\nstatic\n')])
 
1388
        tree.commit('changed file', rev_id='rev2')
 
1389
        s = StringIO()
1412
1390
        serializer = BundleSerializerV4('1.0')
1413
1391
        serializer.write(tree.branch.repository, ['rev1', 'rev2'], {}, s)
1414
1392
        s.seek(0)
1444
1422
 
1445
1423
    def test_copy_signatures(self):
1446
1424
        tree_a = self.make_branch_and_tree('tree_a')
1447
 
        import breezy.gpg
1448
 
        import breezy.commit as commit
1449
 
        oldstrategy = breezy.gpg.GPGStrategy
 
1425
        import bzrlib.gpg
 
1426
        import bzrlib.commit as commit
 
1427
        oldstrategy = bzrlib.gpg.GPGStrategy
1450
1428
        branch = tree_a.branch
1451
1429
        repo_a = branch.repository
1452
 
        tree_a.commit("base", allow_pointless=True, rev_id=b'A')
 
1430
        tree_a.commit("base", allow_pointless=True, rev_id='A')
1453
1431
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
1454
1432
        try:
1455
 
            from ..testament import Testament
 
1433
            from bzrlib.testament import Testament
1456
1434
            # monkey patch gpg signing mechanism
1457
 
            breezy.gpg.GPGStrategy = breezy.gpg.LoopbackGPGStrategy
 
1435
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
1458
1436
            new_config = test_commit.MustSignConfig()
1459
1437
            commit.Commit(config_stack=new_config).commit(message="base",
1460
1438
                                                    allow_pointless=True,
1461
 
                                                    rev_id=b'B',
 
1439
                                                    rev_id='B',
1462
1440
                                                    working_tree=tree_a)
1463
1441
            def sign(text):
1464
 
                return breezy.gpg.LoopbackGPGStrategy(None).sign(text)
 
1442
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
1465
1443
            self.assertTrue(repo_a.has_signature_for_revision_id('B'))
1466
1444
        finally:
1467
 
            breezy.gpg.GPGStrategy = oldstrategy
 
1445
            bzrlib.gpg.GPGStrategy = oldstrategy
1468
1446
        tree_b = self.make_branch_and_tree('tree_b')
1469
1447
        repo_b = tree_b.branch.repository
1470
 
        s = BytesIO()
 
1448
        s = StringIO()
1471
1449
        serializer = BundleSerializerV4('4')
1472
1450
        serializer.write(tree_a.branch.repository, ['A', 'B'], {}, s)
1473
1451
        s.seek(0)
1491
1469
 
1492
1470
        :return: The in-memory bundle
1493
1471
        """
1494
 
        from ..bundle import serializer
 
1472
        from bzrlib.bundle import serializer
1495
1473
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1496
 
        new_text = self.get_raw(BytesIO(b''.join(bundle_txt)))
 
1474
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
1497
1475
        # We are going to be replacing some text to set the executable bit on a
1498
1476
        # file. Make sure the text replacement actually works correctly.
1499
1477
        self.assertContainsRe(new_text, '(?m)B244\n\ni 1\n<inventory')
1500
1478
        new_text = new_text.replace('<file file_id="exe-1"',
1501
1479
                                    '<file executable="y" file_id="exe-1"')
1502
1480
        new_text = new_text.replace('B244', 'B259')
1503
 
        bundle_txt = BytesIO()
 
1481
        bundle_txt = StringIO()
1504
1482
        bundle_txt.write(serializer._get_bundle_header('4'))
1505
1483
        bundle_txt.write('\n')
1506
1484
        bundle_txt.write(new_text.encode('bz2'))
1512
1490
    def make_merged_branch(self):
1513
1491
        builder = self.make_branch_builder('source')
1514
1492
        builder.start_series()
1515
 
        builder.build_snapshot(None, [
 
1493
        builder.build_snapshot('a@cset-0-1', None, [
1516
1494
            ('add', ('', 'root-id', 'directory', None)),
1517
1495
            ('add', ('file', 'file-id', 'file', 'original content\n')),
1518
 
            ], revision_id='a@cset-0-1')
1519
 
        builder.build_snapshot(['a@cset-0-1'], [
1520
 
            ('modify', ('file', 'new-content\n')),
1521
 
            ], revision_id='a@cset-0-2a')
1522
 
        builder.build_snapshot(['a@cset-0-1'], [
1523
 
            ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
1524
 
            ], revision_id='a@cset-0-2b')
1525
 
        builder.build_snapshot(['a@cset-0-2a', 'a@cset-0-2b'], [
1526
 
            ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
1527
 
            ], revision_id='a@cset-0-3')
 
1496
            ])
 
1497
        builder.build_snapshot('a@cset-0-2a', ['a@cset-0-1'], [
 
1498
            ('modify', ('file-id', 'new-content\n')),
 
1499
            ])
 
1500
        builder.build_snapshot('a@cset-0-2b', ['a@cset-0-1'], [
 
1501
            ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
 
1502
            ])
 
1503
        builder.build_snapshot('a@cset-0-3', ['a@cset-0-2a', 'a@cset-0-2b'], [
 
1504
            ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
 
1505
            ])
1528
1506
        builder.finish_series()
1529
1507
        self.b1 = builder.get_branch()
1530
1508
        self.b1.lock_read()
1533
1511
    def make_bundle_just_inventories(self, base_revision_id,
1534
1512
                                     target_revision_id,
1535
1513
                                     revision_ids):
1536
 
        sio = BytesIO()
 
1514
        sio = StringIO()
1537
1515
        writer = v4.BundleWriteOperation(base_revision_id, target_revision_id,
1538
1516
                                         self.b1.repository, sio)
1539
1517
        writer.bundle.begin()
1656
1634
 
1657
1635
    def test_creating_bundle_preserves_chk_pages(self):
1658
1636
        self.make_merged_branch()
1659
 
        target = self.b1.controldir.sprout('target',
 
1637
        target = self.b1.bzrdir.sprout('target',
1660
1638
                                       revision_id='a@cset-0-2a').open_branch()
1661
1639
        bundle_txt, rev_ids = self.create_bundle_text('a@cset-0-2a',
1662
1640
                                                      'a@cset-0-3')
1681
1659
 
1682
1660
        self.build_tree(['b1/one'])
1683
1661
        wt.add('one')
1684
 
        wt.commit('add one', rev_id=b'a@cset-0-1')
 
1662
        wt.commit('add one', rev_id='a@cset-0-1')
1685
1663
        self.build_tree(['b1/two'])
1686
1664
        wt.add('two')
1687
 
        wt.commit('add two', rev_id=b'a@cset-0-2',
 
1665
        wt.commit('add two', rev_id='a@cset-0-2',
1688
1666
                  revprops={'branch-nick':'test'})
1689
1667
 
1690
 
        bundle_txt = BytesIO()
 
1668
        bundle_txt = StringIO()
1691
1669
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
1692
1670
                               'a@cset-0-1', bundle_txt, self.format)
1693
 
        self.assertEqual({'a@cset-0-2'}, set(rev_ids))
 
1671
        self.assertEqual(set(['a@cset-0-2']), set(rev_ids))
1694
1672
        bundle_txt.seek(0, 0)
1695
1673
        return bundle_txt
1696
1674
 
1740
1718
        # creates a blank line at the end, and fails if that
1741
1719
        # line is stripped
1742
1720
        self.assertEqual('\n\n', raw[-2:])
1743
 
        bundle_txt = BytesIO(raw[:-1])
 
1721
        bundle_txt = StringIO(raw[:-1])
1744
1722
 
1745
1723
        bundle = read_bundle(bundle_txt)
1746
1724
        self.check_valid(bundle)
1748
1726
    def test_opening_text(self):
1749
1727
        bundle_txt = self.build_test_bundle()
1750
1728
 
1751
 
        bundle_txt = BytesIO(
1752
 
            b"Some random\nemail comments\n" + bundle_txt.getvalue())
 
1729
        bundle_txt = StringIO("Some random\nemail comments\n"
 
1730
                              + bundle_txt.getvalue())
1753
1731
 
1754
1732
        bundle = read_bundle(bundle_txt)
1755
1733
        self.check_valid(bundle)
1757
1735
    def test_trailing_text(self):
1758
1736
        bundle_txt = self.build_test_bundle()
1759
1737
 
1760
 
        bundle_txt = BytesIO(
1761
 
            bundle_txt.getvalue() + b"Some trailing\nrandom\ntext\n")
 
1738
        bundle_txt = StringIO(bundle_txt.getvalue() +
 
1739
                              "Some trailing\nrandom\ntext\n")
1762
1740
 
1763
1741
        bundle = read_bundle(bundle_txt)
1764
1742
        self.check_valid(bundle)
1772
1750
class TestBundleWriterReader(tests.TestCase):
1773
1751
 
1774
1752
    def test_roundtrip_record(self):
1775
 
        fileobj = BytesIO()
 
1753
        fileobj = StringIO()
1776
1754
        writer = v4.BundleWriter(fileobj)
1777
1755
        writer.begin()
1778
1756
        writer.add_info_record(foo='bar')
1782
1760
        fileobj.seek(0)
1783
1761
        reader = v4.BundleReader(fileobj, stream_input=True)
1784
1762
        record_iter = reader.iter_records()
1785
 
        record = next(record_iter)
 
1763
        record = record_iter.next()
1786
1764
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1787
1765
            'info', None, None), record)
1788
 
        record = next(record_iter)
 
1766
        record = record_iter.next()
1789
1767
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1790
1768
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1791
1769
                          record)
1792
1770
 
1793
1771
    def test_roundtrip_record_memory_hungry(self):
1794
 
        fileobj = BytesIO()
 
1772
        fileobj = StringIO()
1795
1773
        writer = v4.BundleWriter(fileobj)
1796
1774
        writer.begin()
1797
1775
        writer.add_info_record(foo='bar')
1801
1779
        fileobj.seek(0)
1802
1780
        reader = v4.BundleReader(fileobj, stream_input=False)
1803
1781
        record_iter = reader.iter_records()
1804
 
        record = next(record_iter)
 
1782
        record = record_iter.next()
1805
1783
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1806
1784
            'info', None, None), record)
1807
 
        record = next(record_iter)
 
1785
        record = record_iter.next()
1808
1786
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1809
1787
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1810
1788
                          record)
1826
1804
                         v4.BundleReader.decode_name('info'))
1827
1805
 
1828
1806
    def test_too_many_names(self):
1829
 
        fileobj = BytesIO()
 
1807
        fileobj = StringIO()
1830
1808
        writer = v4.BundleWriter(fileobj)
1831
1809
        writer.begin()
1832
1810
        writer.add_info_record(foo='bar')
1834
1812
        writer.end()
1835
1813
        fileobj.seek(0)
1836
1814
        record_iter = v4.BundleReader(fileobj).iter_records()
1837
 
        record = next(record_iter)
 
1815
        record = record_iter.next()
1838
1816
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1839
1817
            'info', None, None), record)
1840
 
        self.assertRaises(errors.BadBundle, next, record_iter)
 
1818
        self.assertRaises(errors.BadBundle, record_iter.next)
1841
1819
 
1842
1820
 
1843
1821
class TestReadMergeableFromUrl(tests.TestCaseWithTransport):
1860
1838
    def test_infinite_redirects_are_not_a_bundle(self):
1861
1839
        """If a URL causes TooManyRedirections then NotABundle is raised.
1862
1840
        """
1863
 
        from .blackbox.test_push import RedirectingMemoryServer
 
1841
        from bzrlib.tests.blackbox.test_push import RedirectingMemoryServer
1864
1842
        server = RedirectingMemoryServer()
1865
1843
        self.start_server(server)
1866
1844
        url = server.get_url() + 'infinite-loop'
1879
1857
        self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url)
1880
1858
 
1881
1859
 
1882
 
class DisconnectingHandler(socketserver.BaseRequestHandler):
 
1860
class DisconnectingHandler(SocketServer.BaseRequestHandler):
1883
1861
    """A request handler that immediately closes any connection made to it."""
1884
1862
 
1885
1863
    def handle(self):