~ubuntu-branches/ubuntu/natty/bzr/natty-proposed

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2010-08-07 00:54:52 UTC
  • mfrom: (1.4.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20100807005452-g4zb99ezl3xn44r4
Tags: 2.2.0-1
* New upstream release.
 + Adds support for setting timestamps to originating revisions.
   Closes: #473450
 + Removes remaining string exception. Closes: #585193, LP: #586926
 + Add C extension to work around Python issue 1628205. LP: #583941,
   Closes: #577110
 + Avoids showing progress bars when --quiet is used. Closes: #542105,
   LP: #320035
 + No longer creates ~/.bazaar as root when run under sudo. LP: #376388
 + 'bzr commit' now supports -p as alternative for --show-diff. LP: #571467
 + 'bzr add' no longer adds .THIS/.BASE/.THEIRS files unless
   explicitly requested. LP: #322767
 + When parsing patch files, Bazaar now supports diff lines before each
   patch. LP: #502076
 + WorkingTrees now no longer requires using signal.signal, so can
   be used in a threaded environment. LP: #521989
 + An assertion error is no longer triggered when pushing to a pre-1.6
   Bazaar server. LP: #528041
* Bump standards version to 3.9.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
    chk_map,
27
27
    config,
28
28
    debug,
29
 
    errors,
30
29
    fetch as _mod_fetch,
31
30
    fifo_cache,
32
31
    generate_ids,
40
39
    lru_cache,
41
40
    osutils,
42
41
    revision as _mod_revision,
 
42
    static_tuple,
43
43
    symbol_versioning,
44
44
    trace,
45
45
    tsort,
46
 
    ui,
47
46
    versionedfile,
48
47
    )
49
48
from bzrlib.bundle import serializer
52
51
from bzrlib.testament import Testament
53
52
""")
54
53
 
 
54
from bzrlib import (
 
55
    errors,
 
56
    registry,
 
57
    ui,
 
58
    )
55
59
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
56
60
from bzrlib.inter import InterObject
57
61
from bzrlib.inventory import (
60
64
    ROOT_ID,
61
65
    entry_factory,
62
66
    )
63
 
from bzrlib.lock import _RelockDebugMixin
64
 
from bzrlib import registry
 
67
from bzrlib.recordcounter import RecordCounter
 
68
from bzrlib.lock import _RelockDebugMixin, LogicalLockResult
65
69
from bzrlib.trace import (
66
70
    log_exception_quietly, note, mutter, mutter_callsite, warning)
67
71
 
70
74
_deprecation_warning_done = False
71
75
 
72
76
 
 
77
class IsInWriteGroupError(errors.InternalBzrError):
 
78
 
 
79
    _fmt = "May not refresh_data of repo %(repo)s while in a write group."
 
80
 
 
81
    def __init__(self, repo):
 
82
        errors.InternalBzrError.__init__(self, repo=repo)
 
83
 
 
84
 
73
85
class CommitBuilder(object):
74
86
    """Provides an interface to build up a commit.
75
87
 
277
289
 
278
290
        :param tree: The tree which is being committed.
279
291
        """
280
 
        # NB: if there are no parents then this method is not called, so no
281
 
        # need to guard on parents having length.
 
292
        if len(self.parents) == 0:
 
293
            raise errors.RootMissing()
282
294
        entry = entry_factory['directory'](tree.path2id(''), '',
283
295
            None)
284
296
        entry.revision = self._new_revision_id
859
871
        # versioned roots do not change unless the tree found a change.
860
872
 
861
873
 
 
874
class RepositoryWriteLockResult(LogicalLockResult):
 
875
    """The result of write locking a repository.
 
876
 
 
877
    :ivar repository_token: The token obtained from the underlying lock, or
 
878
        None.
 
879
    :ivar unlock: A callable which will unlock the lock.
 
880
    """
 
881
 
 
882
    def __init__(self, unlock, repository_token):
 
883
        LogicalLockResult.__init__(self, unlock)
 
884
        self.repository_token = repository_token
 
885
 
 
886
    def __repr__(self):
 
887
        return "RepositoryWriteLockResult(%s, %s)" % (self.repository_token,
 
888
            self.unlock)
 
889
 
 
890
 
862
891
######################################################################
863
892
# Repositories
864
893
 
865
894
 
866
 
class Repository(_RelockDebugMixin):
 
895
class Repository(_RelockDebugMixin, bzrdir.ControlComponent):
867
896
    """Repository holding history for one or more branches.
868
897
 
869
898
    The repository holds and retrieves historical information including
1017
1046
                " id and insertion revid (%r, %r)"
1018
1047
                % (inv.revision_id, revision_id))
1019
1048
        if inv.root is None:
1020
 
            raise AssertionError()
 
1049
            raise errors.RootMissing()
1021
1050
        return self._add_inventory_checked(revision_id, inv, parents)
1022
1051
 
1023
1052
    def _add_inventory_checked(self, revision_id, inv, parents):
1027
1056
 
1028
1057
        :seealso: add_inventory, for the contract.
1029
1058
        """
1030
 
        inv_lines = self._serialise_inventory_to_lines(inv)
 
1059
        inv_lines = self._serializer.write_inventory_to_lines(inv)
1031
1060
        return self._inventory_add_lines(revision_id, parents,
1032
1061
            inv_lines, check_content=False)
1033
1062
 
1240
1269
        """Check a single text from this repository."""
1241
1270
        if kind == 'inventories':
1242
1271
            rev_id = record.key[0]
1243
 
            inv = self.deserialise_inventory(rev_id,
 
1272
            inv = self._deserialise_inventory(rev_id,
1244
1273
                record.get_bytes_as('fulltext'))
1245
1274
            if last_object is not None:
1246
1275
                delta = inv._make_delta(last_object)
1290
1319
 
1291
1320
        :param _format: The format of the repository on disk.
1292
1321
        :param a_bzrdir: The BzrDir of the repository.
1293
 
 
1294
 
        In the future we will have a single api for all stores for
1295
 
        getting file texts, inventories and revisions, then
1296
 
        this construct will accept instances of those things.
1297
1322
        """
 
1323
        # In the future we will have a single api for all stores for
 
1324
        # getting file texts, inventories and revisions, then
 
1325
        # this construct will accept instances of those things.
1298
1326
        super(Repository, self).__init__()
1299
1327
        self._format = _format
1300
1328
        # the following are part of the public API for Repository:
1315
1343
        # rather copying them?
1316
1344
        self._safe_to_return_from_cache = False
1317
1345
 
 
1346
    @property
 
1347
    def user_transport(self):
 
1348
        return self.bzrdir.user_transport
 
1349
 
 
1350
    @property
 
1351
    def control_transport(self):
 
1352
        return self._transport
 
1353
 
1318
1354
    def __repr__(self):
1319
1355
        if self._fallback_repositories:
1320
1356
            return '%s(%r, fallback_repositories=%r)' % (
1368
1404
        data during reads, and allows a 'write_group' to be obtained. Write
1369
1405
        groups must be used for actual data insertion.
1370
1406
 
 
1407
        A token should be passed in if you know that you have locked the object
 
1408
        some other way, and need to synchronise this object's state with that
 
1409
        fact.
 
1410
 
 
1411
        XXX: this docstring is duplicated in many places, e.g. lockable_files.py
 
1412
 
1371
1413
        :param token: if this is already locked, then lock_write will fail
1372
1414
            unless the token matches the existing lock.
1373
1415
        :returns: a token if this instance supports tokens, otherwise None.
1376
1418
        :raises MismatchedToken: if the specified token doesn't match the token
1377
1419
            of the existing lock.
1378
1420
        :seealso: start_write_group.
1379
 
 
1380
 
        A token should be passed in if you know that you have locked the object
1381
 
        some other way, and need to synchronise this object's state with that
1382
 
        fact.
1383
 
 
1384
 
        XXX: this docstring is duplicated in many places, e.g. lockable_files.py
 
1421
        :return: A RepositoryWriteLockResult.
1385
1422
        """
1386
1423
        locked = self.is_locked()
1387
 
        result = self.control_files.lock_write(token=token)
 
1424
        token = self.control_files.lock_write(token=token)
1388
1425
        if not locked:
1389
1426
            self._warn_if_deprecated()
1390
1427
            self._note_lock('w')
1392
1429
                # Writes don't affect fallback repos
1393
1430
                repo.lock_read()
1394
1431
            self._refresh_data()
1395
 
        return result
 
1432
        return RepositoryWriteLockResult(self.unlock, token)
1396
1433
 
1397
1434
    def lock_read(self):
 
1435
        """Lock the repository for read operations.
 
1436
 
 
1437
        :return: An object with an unlock method which will release the lock
 
1438
            obtained.
 
1439
        """
1398
1440
        locked = self.is_locked()
1399
1441
        self.control_files.lock_read()
1400
1442
        if not locked:
1403
1445
            for repo in self._fallback_repositories:
1404
1446
                repo.lock_read()
1405
1447
            self._refresh_data()
 
1448
        return LogicalLockResult(self.unlock)
1406
1449
 
1407
1450
    def get_physical_lock_status(self):
1408
1451
        return self.control_files.get_physical_lock_status()
1468
1511
 
1469
1512
        # now gather global repository information
1470
1513
        # XXX: This is available for many repos regardless of listability.
1471
 
        if self.bzrdir.root_transport.listable():
 
1514
        if self.user_transport.listable():
1472
1515
            # XXX: do we want to __define len__() ?
1473
1516
            # Maybe the versionedfiles object should provide a different
1474
1517
            # method to get the number of keys.
1484
1527
        :param using: If True, list only branches using this repository.
1485
1528
        """
1486
1529
        if using and not self.is_shared():
1487
 
            try:
1488
 
                return [self.bzrdir.open_branch()]
1489
 
            except errors.NotBranchError:
1490
 
                return []
 
1530
            return self.bzrdir.list_branches()
1491
1531
        class Evaluator(object):
1492
1532
 
1493
1533
            def __init__(self):
1502
1542
                    except errors.NoRepositoryPresent:
1503
1543
                        pass
1504
1544
                    else:
1505
 
                        return False, (None, repository)
 
1545
                        return False, ([], repository)
1506
1546
                self.first_call = False
1507
 
                try:
1508
 
                    value = (bzrdir.open_branch(), None)
1509
 
                except errors.NotBranchError:
1510
 
                    value = (None, None)
 
1547
                value = (bzrdir.list_branches(), None)
1511
1548
                return True, value
1512
1549
 
1513
 
        branches = []
1514
 
        for branch, repository in bzrdir.BzrDir.find_bzrdirs(
1515
 
                self.bzrdir.root_transport, evaluate=Evaluator()):
1516
 
            if branch is not None:
1517
 
                branches.append(branch)
 
1550
        ret = []
 
1551
        for branches, repository in bzrdir.BzrDir.find_bzrdirs(
 
1552
                self.user_transport, evaluate=Evaluator()):
 
1553
            if branches is not None:
 
1554
                ret.extend(branches)
1518
1555
            if not using and repository is not None:
1519
 
                branches.extend(repository.find_branches())
1520
 
        return branches
 
1556
                ret.extend(repository.find_branches())
 
1557
        return ret
1521
1558
 
1522
1559
    @needs_read_lock
1523
1560
    def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
1632
1669
        return missing_keys
1633
1670
 
1634
1671
    def refresh_data(self):
1635
 
        """Re-read any data needed to to synchronise with disk.
 
1672
        """Re-read any data needed to synchronise with disk.
1636
1673
 
1637
1674
        This method is intended to be called after another repository instance
1638
1675
        (such as one used by a smart server) has inserted data into the
1639
 
        repository. It may not be called during a write group, but may be
1640
 
        called at any other time.
 
1676
        repository. On all repositories this will work outside of write groups.
 
1677
        Some repository formats (pack and newer for bzrlib native formats)
 
1678
        support refresh_data inside write groups. If called inside a write
 
1679
        group on a repository that does not support refreshing in a write group
 
1680
        IsInWriteGroupError will be raised.
1641
1681
        """
1642
 
        if self.is_in_write_group():
1643
 
            raise errors.InternalBzrError(
1644
 
                "May not refresh_data while in a write group.")
1645
1682
        self._refresh_data()
1646
1683
 
1647
1684
    def resume_write_group(self, tokens):
1686
1723
                "May not fetch while in a write group.")
1687
1724
        # fast path same-url fetch operations
1688
1725
        # TODO: lift out to somewhere common with RemoteRepository
1689
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/401646>
 
1726
        # <https://bugs.launchpad.net/bzr/+bug/401646>
1690
1727
        if (self.has_same_location(source)
1691
1728
            and fetch_spec is None
1692
1729
            and self._has_same_fallbacks(source)):
1901
1938
                rev = self._serializer.read_revision_from_string(text)
1902
1939
                yield (revid, rev)
1903
1940
 
1904
 
    @needs_read_lock
1905
 
    def get_revision_xml(self, revision_id):
1906
 
        # TODO: jam 20070210 This shouldn't be necessary since get_revision
1907
 
        #       would have already do it.
1908
 
        # TODO: jam 20070210 Just use _serializer.write_revision_to_string()
1909
 
        # TODO: this can't just be replaced by:
1910
 
        # return self._serializer.write_revision_to_string(
1911
 
        #     self.get_revision(revision_id))
1912
 
        # as cStringIO preservers the encoding unlike write_revision_to_string
1913
 
        # or some other call down the path.
1914
 
        rev = self.get_revision(revision_id)
1915
 
        rev_tmp = cStringIO.StringIO()
1916
 
        # the current serializer..
1917
 
        self._serializer.write_revision(rev, rev_tmp)
1918
 
        rev_tmp.seek(0)
1919
 
        return rev_tmp.getvalue()
1920
 
 
1921
1941
    def get_deltas_for_revisions(self, revisions, specific_fileids=None):
1922
1942
        """Produce a generator of revision deltas.
1923
1943
 
2165
2185
        """
2166
2186
        selected_keys = set((revid,) for revid in revision_ids)
2167
2187
        w = _inv_weave or self.inventories
2168
 
        pb = ui.ui_factory.nested_progress_bar()
2169
 
        try:
2170
 
            return self._find_file_ids_from_xml_inventory_lines(
2171
 
                w.iter_lines_added_or_present_in_keys(
2172
 
                    selected_keys, pb=pb),
2173
 
                selected_keys)
2174
 
        finally:
2175
 
            pb.finished()
 
2188
        return self._find_file_ids_from_xml_inventory_lines(
 
2189
            w.iter_lines_added_or_present_in_keys(
 
2190
                selected_keys, pb=None),
 
2191
            selected_keys)
2176
2192
 
2177
2193
    def iter_files_bytes(self, desired_files):
2178
2194
        """Iterate through file versions.
2388
2404
        """single-document based inventory iteration."""
2389
2405
        inv_xmls = self._iter_inventory_xmls(revision_ids, ordering)
2390
2406
        for text, revision_id in inv_xmls:
2391
 
            yield self.deserialise_inventory(revision_id, text)
 
2407
            yield self._deserialise_inventory(revision_id, text)
2392
2408
 
2393
2409
    def _iter_inventory_xmls(self, revision_ids, ordering):
2394
2410
        if ordering is None:
2426
2442
                        next_key = None
2427
2443
                        break
2428
2444
 
2429
 
    def deserialise_inventory(self, revision_id, xml):
 
2445
    def _deserialise_inventory(self, revision_id, xml):
2430
2446
        """Transform the xml into an inventory object.
2431
2447
 
2432
2448
        :param revision_id: The expected revision id of the inventory.
2440
2456
                result.revision_id, revision_id))
2441
2457
        return result
2442
2458
 
2443
 
    def serialise_inventory(self, inv):
2444
 
        return self._serializer.write_inventory_to_string(inv)
2445
 
 
2446
 
    def _serialise_inventory_to_lines(self, inv):
2447
 
        return self._serializer.write_inventory_to_lines(inv)
2448
 
 
2449
2459
    def get_serializer_format(self):
2450
2460
        return self._serializer.format_num
2451
2461
 
2452
2462
    @needs_read_lock
2453
 
    def get_inventory_xml(self, revision_id):
2454
 
        """Get inventory XML as a file object."""
 
2463
    def _get_inventory_xml(self, revision_id):
 
2464
        """Get serialized inventory as a string."""
2455
2465
        texts = self._iter_inventory_xmls([revision_id], 'unordered')
2456
2466
        try:
2457
2467
            text, revision_id = texts.next()
2459
2469
            raise errors.HistoryMissing(self, 'inventory', revision_id)
2460
2470
        return text
2461
2471
 
2462
 
    @needs_read_lock
2463
 
    def get_inventory_sha1(self, revision_id):
2464
 
        """Return the sha1 hash of the inventory entry
2465
 
        """
2466
 
        return self.get_revision(revision_id).inventory_sha1
2467
 
 
2468
2472
    def get_rev_id_for_revno(self, revno, known_pair):
2469
2473
        """Return the revision id of a revno, given a later (revno, revid)
2470
2474
        pair in the same history.
2521
2525
            else:
2522
2526
                next_id = parents[0]
2523
2527
 
2524
 
    @needs_read_lock
2525
 
    def get_revision_inventory(self, revision_id):
2526
 
        """Return inventory of a past revision."""
2527
 
        # TODO: Unify this with get_inventory()
2528
 
        # bzr 0.0.6 and later imposes the constraint that the inventory_id
2529
 
        # must be the same as its revision, so this is trivial.
2530
 
        if revision_id is None:
2531
 
            # This does not make sense: if there is no revision,
2532
 
            # then it is the current tree inventory surely ?!
2533
 
            # and thus get_root_id() is something that looks at the last
2534
 
            # commit on the branch, and the get_root_id is an inventory check.
2535
 
            raise NotImplementedError
2536
 
            # return Inventory(self.get_root_id())
2537
 
        else:
2538
 
            return self.get_inventory(revision_id)
2539
 
 
2540
2528
    def is_shared(self):
2541
2529
        """Return True if this repository is flagged as a shared repository."""
2542
2530
        raise NotImplementedError(self.is_shared)
2576
2564
            return RevisionTree(self, Inventory(root_id=None),
2577
2565
                                _mod_revision.NULL_REVISION)
2578
2566
        else:
2579
 
            inv = self.get_revision_inventory(revision_id)
 
2567
            inv = self.get_inventory(revision_id)
2580
2568
            return RevisionTree(self, inv, revision_id)
2581
2569
 
2582
2570
    def revision_trees(self, revision_ids):
2635
2623
            keys = tsort.topo_sort(parent_map)
2636
2624
        return [None] + list(keys)
2637
2625
 
2638
 
    def pack(self, hint=None):
 
2626
    def pack(self, hint=None, clean_obsolete_packs=False):
2639
2627
        """Compress the data within the repository.
2640
2628
 
2641
2629
        This operation only makes sense for some repository types. For other
2651
2639
            obtained from the result of commit_write_group(). Out of
2652
2640
            date hints are simply ignored, because concurrent operations
2653
2641
            can obsolete them rapidly.
 
2642
 
 
2643
        :param clean_obsolete_packs: Clean obsolete packs immediately after
 
2644
            the pack operation.
2654
2645
        """
2655
2646
 
2656
2647
    def get_transaction(self):
2681
2672
    def _make_parents_provider(self):
2682
2673
        return self
2683
2674
 
 
2675
    @needs_read_lock
 
2676
    def get_known_graph_ancestry(self, revision_ids):
 
2677
        """Return the known graph for a set of revision ids and their ancestors.
 
2678
        """
 
2679
        st = static_tuple.StaticTuple
 
2680
        revision_keys = [st(r_id).intern() for r_id in revision_ids]
 
2681
        known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
 
2682
        return graph.GraphThunkIdsToKeys(known_graph)
 
2683
 
2684
2684
    def get_graph(self, other_repository=None):
2685
2685
        """Return the graph walker for this repository format"""
2686
2686
        parents_provider = self._make_parents_provider()
3085
3085
    pack_compresses = False
3086
3086
    # Does the repository inventory storage understand references to trees?
3087
3087
    supports_tree_reference = None
 
3088
    # Is the format experimental ?
 
3089
    experimental = False
3088
3090
 
3089
3091
    def __repr__(self):
3090
3092
        return "%s()" % self.__class__.__name__
3211
3213
        """
3212
3214
        raise NotImplementedError(self.open)
3213
3215
 
 
3216
    def _run_post_repo_init_hooks(self, repository, a_bzrdir, shared):
 
3217
        from bzrlib.bzrdir import BzrDir, RepoInitHookParams
 
3218
        hooks = BzrDir.hooks['post_repo_init']
 
3219
        if not hooks:
 
3220
            return
 
3221
        params = RepoInitHookParams(repository, self, a_bzrdir, shared)
 
3222
        for hook in hooks:
 
3223
            hook(params)
 
3224
 
3214
3225
 
3215
3226
class MetaDirRepositoryFormat(RepositoryFormat):
3216
3227
    """Common base class for the new repositories using the metadir layout."""
3421
3432
 
3422
3433
        :param revision_id: if None all content is copied, if NULL_REVISION no
3423
3434
                            content is copied.
3424
 
        :param pb: optional progress bar to use for progress reports. If not
3425
 
                   provided a default one will be created.
 
3435
        :param pb: ignored.
3426
3436
        :return: None.
3427
3437
        """
 
3438
        ui.ui_factory.warn_experimental_format_fetch(self)
3428
3439
        from bzrlib.fetch import RepoFetcher
3429
3440
        # See <https://launchpad.net/bugs/456077> asking for a warning here
3430
3441
        if self.source._format.network_name() != self.target._format.network_name():
3435
3446
                               from_repository=self.source,
3436
3447
                               last_revision=revision_id,
3437
3448
                               fetch_spec=fetch_spec,
3438
 
                               pb=pb, find_ghosts=find_ghosts)
 
3449
                               find_ghosts=find_ghosts)
3439
3450
 
3440
3451
    def _walk_to_common_revisions(self, revision_ids):
3441
3452
        """Walk out from revision_ids in source to revisions target has.
4015
4026
        """See InterRepository.fetch()."""
4016
4027
        if fetch_spec is not None:
4017
4028
            raise AssertionError("Not implemented yet...")
 
4029
        ui.ui_factory.warn_experimental_format_fetch(self)
4018
4030
        if (not self.source.supports_rich_root()
4019
4031
            and self.target.supports_rich_root()):
4020
4032
            self._converting_to_rich_root = True
4100
4112
        :param to_convert: The disk object to convert.
4101
4113
        :param pb: a progress bar to use for progress information.
4102
4114
        """
4103
 
        self.pb = pb
 
4115
        pb = ui.ui_factory.nested_progress_bar()
4104
4116
        self.count = 0
4105
4117
        self.total = 4
4106
4118
        # this is only useful with metadir layouts - separated repo content.
4107
4119
        # trigger an assertion if not such
4108
4120
        repo._format.get_format_string()
4109
4121
        self.repo_dir = repo.bzrdir
4110
 
        self.step('Moving repository to repository.backup')
 
4122
        pb.update('Moving repository to repository.backup')
4111
4123
        self.repo_dir.transport.move('repository', 'repository.backup')
4112
4124
        backup_transport =  self.repo_dir.transport.clone('repository.backup')
4113
4125
        repo._format.check_conversion_target(self.target_format)
4114
4126
        self.source_repo = repo._format.open(self.repo_dir,
4115
4127
            _found=True,
4116
4128
            _override_transport=backup_transport)
4117
 
        self.step('Creating new repository')
 
4129
        pb.update('Creating new repository')
4118
4130
        converted = self.target_format.initialize(self.repo_dir,
4119
4131
                                                  self.source_repo.is_shared())
4120
4132
        converted.lock_write()
4121
4133
        try:
4122
 
            self.step('Copying content')
 
4134
            pb.update('Copying content')
4123
4135
            self.source_repo.copy_content_into(converted)
4124
4136
        finally:
4125
4137
            converted.unlock()
4126
 
        self.step('Deleting old repository content')
 
4138
        pb.update('Deleting old repository content')
4127
4139
        self.repo_dir.transport.delete_tree('repository.backup')
4128
4140
        ui.ui_factory.note('repository converted')
4129
 
 
4130
 
    def step(self, message):
4131
 
        """Update the pb by a step."""
4132
 
        self.count +=1
4133
 
        self.pb.update(message, self.count, self.total)
 
4141
        pb.finished()
4134
4142
 
4135
4143
 
4136
4144
_unescape_map = {
4276
4284
                is_resume = False
4277
4285
            try:
4278
4286
                # locked_insert_stream performs a commit|suspend.
4279
 
                return self._locked_insert_stream(stream, src_format, is_resume)
 
4287
                return self._locked_insert_stream(stream, src_format,
 
4288
                    is_resume)
4280
4289
            except:
4281
4290
                self.target_repo.abort_write_group(suppress_errors=True)
4282
4291
                raise
4329
4338
                # required if the serializers are different only in terms of
4330
4339
                # the inventory.
4331
4340
                if src_serializer == to_serializer:
4332
 
                    self.target_repo.revisions.insert_record_stream(
4333
 
                        substream)
 
4341
                    self.target_repo.revisions.insert_record_stream(substream)
4334
4342
                else:
4335
4343
                    self._extract_and_insert_revisions(substream,
4336
4344
                        src_serializer)
4444
4452
        """Create a StreamSource streaming from from_repository."""
4445
4453
        self.from_repository = from_repository
4446
4454
        self.to_format = to_format
 
4455
        self._record_counter = RecordCounter()
4447
4456
 
4448
4457
    def delta_on_metadata(self):
4449
4458
        """Return True if delta's are permitted on metadata streams.