/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/repository.py

  • Committer: Martin
  • Date: 2010-05-06 11:34:49 UTC
  • mto: This revision was merged to the branch mainline in revision 5246.
  • Revision ID: gzlist@googlemail.com-20100506113449-c1yd0ehutk98dycu
Test how pywintypes.error is displayed to the user

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
24
24
    bzrdir,
25
25
    check,
26
26
    chk_map,
 
27
    config,
27
28
    debug,
28
29
    errors,
 
30
    fetch as _mod_fetch,
29
31
    fifo_cache,
30
32
    generate_ids,
31
33
    gpg,
38
40
    lru_cache,
39
41
    osutils,
40
42
    revision as _mod_revision,
 
43
    static_tuple,
41
44
    symbol_versioning,
 
45
    trace,
42
46
    tsort,
43
47
    ui,
44
48
    versionedfile,
206
210
            # an inventory delta was accumulated without creating a new
207
211
            # inventory.
208
212
            basis_id = self.basis_delta_revision
209
 
            self.inv_sha1 = self.repository.add_inventory_by_delta(
 
213
            # We ignore the 'inventory' returned by add_inventory_by_delta
 
214
            # because self.new_inventory is used to hint to the rest of the
 
215
            # system what code path was taken
 
216
            self.inv_sha1, _ = self.repository.add_inventory_by_delta(
210
217
                basis_id, self._basis_delta, self._new_revision_id,
211
218
                self.parents)
212
219
        else:
857
864
# Repositories
858
865
 
859
866
 
860
 
class Repository(_RelockDebugMixin):
 
867
class Repository(_RelockDebugMixin, bzrdir.ControlComponent):
861
868
    """Repository holding history for one or more branches.
862
869
 
863
870
    The repository holds and retrieves historical information including
1021
1028
 
1022
1029
        :seealso: add_inventory, for the contract.
1023
1030
        """
1024
 
        inv_lines = self._serialise_inventory_to_lines(inv)
 
1031
        inv_lines = self._serializer.write_inventory_to_lines(inv)
1025
1032
        return self._inventory_add_lines(revision_id, parents,
1026
1033
            inv_lines, check_content=False)
1027
1034
 
1234
1241
        """Check a single text from this repository."""
1235
1242
        if kind == 'inventories':
1236
1243
            rev_id = record.key[0]
1237
 
            inv = self.deserialise_inventory(rev_id,
 
1244
            inv = self._deserialise_inventory(rev_id,
1238
1245
                record.get_bytes_as('fulltext'))
1239
1246
            if last_object is not None:
1240
1247
                delta = inv._make_delta(last_object)
1284
1291
 
1285
1292
        :param _format: The format of the repository on disk.
1286
1293
        :param a_bzrdir: The BzrDir of the repository.
1287
 
 
1288
 
        In the future we will have a single api for all stores for
1289
 
        getting file texts, inventories and revisions, then
1290
 
        this construct will accept instances of those things.
1291
1294
        """
 
1295
        # In the future we will have a single api for all stores for
 
1296
        # getting file texts, inventories and revisions, then
 
1297
        # this construct will accept instances of those things.
1292
1298
        super(Repository, self).__init__()
1293
1299
        self._format = _format
1294
1300
        # the following are part of the public API for Repository:
1300
1306
        self._reconcile_does_inventory_gc = True
1301
1307
        self._reconcile_fixes_text_parents = False
1302
1308
        self._reconcile_backsup_inventory = True
1303
 
        # not right yet - should be more semantically clear ?
1304
 
        #
1305
 
        # TODO: make sure to construct the right store classes, etc, depending
1306
 
        # on whether escaping is required.
1307
 
        self._warn_if_deprecated()
1308
1309
        self._write_group = None
1309
1310
        # Additional places to query for data.
1310
1311
        self._fallback_repositories = []
1311
1312
        # An InventoryEntry cache, used during deserialization
1312
1313
        self._inventory_entry_cache = fifo_cache.FIFOCache(10*1024)
 
1314
        # Is it safe to return inventory entries directly from the entry cache,
 
1315
        # rather copying them?
 
1316
        self._safe_to_return_from_cache = False
 
1317
 
 
1318
    @property
 
1319
    def user_transport(self):
 
1320
        return self.bzrdir.user_transport
 
1321
 
 
1322
    @property
 
1323
    def control_transport(self):
 
1324
        return self._transport
1313
1325
 
1314
1326
    def __repr__(self):
1315
1327
        if self._fallback_repositories:
1382
1394
        locked = self.is_locked()
1383
1395
        result = self.control_files.lock_write(token=token)
1384
1396
        if not locked:
 
1397
            self._warn_if_deprecated()
1385
1398
            self._note_lock('w')
1386
1399
            for repo in self._fallback_repositories:
1387
1400
                # Writes don't affect fallback repos
1393
1406
        locked = self.is_locked()
1394
1407
        self.control_files.lock_read()
1395
1408
        if not locked:
 
1409
            self._warn_if_deprecated()
1396
1410
            self._note_lock('r')
1397
1411
            for repo in self._fallback_repositories:
1398
1412
                repo.lock_read()
1462
1476
 
1463
1477
        # now gather global repository information
1464
1478
        # XXX: This is available for many repos regardless of listability.
1465
 
        if self.bzrdir.root_transport.listable():
 
1479
        if self.user_transport.listable():
1466
1480
            # XXX: do we want to __define len__() ?
1467
1481
            # Maybe the versionedfiles object should provide a different
1468
1482
            # method to get the number of keys.
1478
1492
        :param using: If True, list only branches using this repository.
1479
1493
        """
1480
1494
        if using and not self.is_shared():
1481
 
            try:
1482
 
                return [self.bzrdir.open_branch()]
1483
 
            except errors.NotBranchError:
1484
 
                return []
 
1495
            return self.bzrdir.list_branches()
1485
1496
        class Evaluator(object):
1486
1497
 
1487
1498
            def __init__(self):
1496
1507
                    except errors.NoRepositoryPresent:
1497
1508
                        pass
1498
1509
                    else:
1499
 
                        return False, (None, repository)
 
1510
                        return False, ([], repository)
1500
1511
                self.first_call = False
1501
 
                try:
1502
 
                    value = (bzrdir.open_branch(), None)
1503
 
                except errors.NotBranchError:
1504
 
                    value = (None, None)
 
1512
                value = (bzrdir.list_branches(), None)
1505
1513
                return True, value
1506
1514
 
1507
 
        branches = []
1508
 
        for branch, repository in bzrdir.BzrDir.find_bzrdirs(
1509
 
                self.bzrdir.root_transport, evaluate=Evaluator()):
1510
 
            if branch is not None:
1511
 
                branches.append(branch)
 
1515
        ret = []
 
1516
        for branches, repository in bzrdir.BzrDir.find_bzrdirs(
 
1517
                self.user_transport, evaluate=Evaluator()):
 
1518
            if branches is not None:
 
1519
                ret.extend(branches)
1512
1520
            if not using and repository is not None:
1513
 
                branches.extend(repository.find_branches())
1514
 
        return branches
 
1521
                ret.extend(repository.find_branches())
 
1522
        return ret
1515
1523
 
1516
1524
    @needs_read_lock
1517
1525
    def search_missing_revision_ids(self, other, revision_id=None, find_ghosts=True):
1895
1903
                rev = self._serializer.read_revision_from_string(text)
1896
1904
                yield (revid, rev)
1897
1905
 
1898
 
    @needs_read_lock
1899
 
    def get_revision_xml(self, revision_id):
1900
 
        # TODO: jam 20070210 This shouldn't be necessary since get_revision
1901
 
        #       would have already do it.
1902
 
        # TODO: jam 20070210 Just use _serializer.write_revision_to_string()
1903
 
        # TODO: this can't just be replaced by:
1904
 
        # return self._serializer.write_revision_to_string(
1905
 
        #     self.get_revision(revision_id))
1906
 
        # as cStringIO preservers the encoding unlike write_revision_to_string
1907
 
        # or some other call down the path.
1908
 
        rev = self.get_revision(revision_id)
1909
 
        rev_tmp = cStringIO.StringIO()
1910
 
        # the current serializer..
1911
 
        self._serializer.write_revision(rev, rev_tmp)
1912
 
        rev_tmp.seek(0)
1913
 
        return rev_tmp.getvalue()
1914
 
 
1915
1906
    def get_deltas_for_revisions(self, revisions, specific_fileids=None):
1916
1907
        """Produce a generator of revision deltas.
1917
1908
 
2159
2150
        """
2160
2151
        selected_keys = set((revid,) for revid in revision_ids)
2161
2152
        w = _inv_weave or self.inventories
2162
 
        pb = ui.ui_factory.nested_progress_bar()
2163
 
        try:
2164
 
            return self._find_file_ids_from_xml_inventory_lines(
2165
 
                w.iter_lines_added_or_present_in_keys(
2166
 
                    selected_keys, pb=pb),
2167
 
                selected_keys)
2168
 
        finally:
2169
 
            pb.finished()
 
2153
        return self._find_file_ids_from_xml_inventory_lines(
 
2154
            w.iter_lines_added_or_present_in_keys(
 
2155
                selected_keys, pb=None),
 
2156
            selected_keys)
2170
2157
 
2171
2158
    def iter_files_bytes(self, desired_files):
2172
2159
        """Iterate through file versions.
2382
2369
        """single-document based inventory iteration."""
2383
2370
        inv_xmls = self._iter_inventory_xmls(revision_ids, ordering)
2384
2371
        for text, revision_id in inv_xmls:
2385
 
            yield self.deserialise_inventory(revision_id, text)
 
2372
            yield self._deserialise_inventory(revision_id, text)
2386
2373
 
2387
2374
    def _iter_inventory_xmls(self, revision_ids, ordering):
2388
2375
        if ordering is None:
2420
2407
                        next_key = None
2421
2408
                        break
2422
2409
 
2423
 
    def deserialise_inventory(self, revision_id, xml):
 
2410
    def _deserialise_inventory(self, revision_id, xml):
2424
2411
        """Transform the xml into an inventory object.
2425
2412
 
2426
2413
        :param revision_id: The expected revision id of the inventory.
2427
2414
        :param xml: A serialised inventory.
2428
2415
        """
2429
2416
        result = self._serializer.read_inventory_from_string(xml, revision_id,
2430
 
                    entry_cache=self._inventory_entry_cache)
 
2417
                    entry_cache=self._inventory_entry_cache,
 
2418
                    return_from_cache=self._safe_to_return_from_cache)
2431
2419
        if result.revision_id != revision_id:
2432
2420
            raise AssertionError('revision id mismatch %s != %s' % (
2433
2421
                result.revision_id, revision_id))
2434
2422
        return result
2435
2423
 
2436
 
    def serialise_inventory(self, inv):
2437
 
        return self._serializer.write_inventory_to_string(inv)
2438
 
 
2439
 
    def _serialise_inventory_to_lines(self, inv):
2440
 
        return self._serializer.write_inventory_to_lines(inv)
2441
 
 
2442
2424
    def get_serializer_format(self):
2443
2425
        return self._serializer.format_num
2444
2426
 
2445
2427
    @needs_read_lock
2446
 
    def get_inventory_xml(self, revision_id):
2447
 
        """Get inventory XML as a file object."""
 
2428
    def _get_inventory_xml(self, revision_id):
 
2429
        """Get serialized inventory as a string."""
2448
2430
        texts = self._iter_inventory_xmls([revision_id], 'unordered')
2449
2431
        try:
2450
2432
            text, revision_id = texts.next()
2452
2434
            raise errors.HistoryMissing(self, 'inventory', revision_id)
2453
2435
        return text
2454
2436
 
2455
 
    @needs_read_lock
2456
 
    def get_inventory_sha1(self, revision_id):
2457
 
        """Return the sha1 hash of the inventory entry
2458
 
        """
2459
 
        return self.get_revision(revision_id).inventory_sha1
2460
 
 
2461
2437
    def get_rev_id_for_revno(self, revno, known_pair):
2462
2438
        """Return the revision id of a revno, given a later (revno, revid)
2463
2439
        pair in the same history.
2514
2490
            else:
2515
2491
                next_id = parents[0]
2516
2492
 
2517
 
    @needs_read_lock
2518
 
    def get_revision_inventory(self, revision_id):
2519
 
        """Return inventory of a past revision."""
2520
 
        # TODO: Unify this with get_inventory()
2521
 
        # bzr 0.0.6 and later imposes the constraint that the inventory_id
2522
 
        # must be the same as its revision, so this is trivial.
2523
 
        if revision_id is None:
2524
 
            # This does not make sense: if there is no revision,
2525
 
            # then it is the current tree inventory surely ?!
2526
 
            # and thus get_root_id() is something that looks at the last
2527
 
            # commit on the branch, and the get_root_id is an inventory check.
2528
 
            raise NotImplementedError
2529
 
            # return Inventory(self.get_root_id())
2530
 
        else:
2531
 
            return self.get_inventory(revision_id)
2532
 
 
2533
2493
    def is_shared(self):
2534
2494
        """Return True if this repository is flagged as a shared repository."""
2535
2495
        raise NotImplementedError(self.is_shared)
2569
2529
            return RevisionTree(self, Inventory(root_id=None),
2570
2530
                                _mod_revision.NULL_REVISION)
2571
2531
        else:
2572
 
            inv = self.get_revision_inventory(revision_id)
 
2532
            inv = self.get_inventory(revision_id)
2573
2533
            return RevisionTree(self, inv, revision_id)
2574
2534
 
2575
2535
    def revision_trees(self, revision_ids):
2628
2588
            keys = tsort.topo_sort(parent_map)
2629
2589
        return [None] + list(keys)
2630
2590
 
2631
 
    def pack(self, hint=None):
 
2591
    def pack(self, hint=None, clean_obsolete_packs=False):
2632
2592
        """Compress the data within the repository.
2633
2593
 
2634
2594
        This operation only makes sense for some repository types. For other
2644
2604
            obtained from the result of commit_write_group(). Out of
2645
2605
            date hints are simply ignored, because concurrent operations
2646
2606
            can obsolete them rapidly.
 
2607
 
 
2608
        :param clean_obsolete_packs: Clean obsolete packs immediately after
 
2609
            the pack operation.
2647
2610
        """
2648
2611
 
2649
2612
    def get_transaction(self):
2665
2628
        for ((revision_id,), parent_keys) in \
2666
2629
                self.revisions.get_parent_map(query_keys).iteritems():
2667
2630
            if parent_keys:
2668
 
                result[revision_id] = tuple(parent_revid
2669
 
                    for (parent_revid,) in parent_keys)
 
2631
                result[revision_id] = tuple([parent_revid
 
2632
                    for (parent_revid,) in parent_keys])
2670
2633
            else:
2671
2634
                result[revision_id] = (_mod_revision.NULL_REVISION,)
2672
2635
        return result
2674
2637
    def _make_parents_provider(self):
2675
2638
        return self
2676
2639
 
 
2640
    @needs_read_lock
 
2641
    def get_known_graph_ancestry(self, revision_ids):
 
2642
        """Return the known graph for a set of revision ids and their ancestors.
 
2643
        """
 
2644
        st = static_tuple.StaticTuple
 
2645
        revision_keys = [st(r_id).intern() for r_id in revision_ids]
 
2646
        known_graph = self.revisions.get_known_graph_ancestry(revision_keys)
 
2647
        return graph.GraphThunkIdsToKeys(known_graph)
 
2648
 
2677
2649
    def get_graph(self, other_repository=None):
2678
2650
        """Return the graph walker for this repository format"""
2679
2651
        parents_provider = self._make_parents_provider()
2774
2746
        result.check(callback_refs)
2775
2747
        return result
2776
2748
 
2777
 
    def _warn_if_deprecated(self):
 
2749
    def _warn_if_deprecated(self, branch=None):
2778
2750
        global _deprecation_warning_done
2779
2751
        if _deprecation_warning_done:
2780
2752
            return
2781
 
        _deprecation_warning_done = True
2782
 
        warning("Format %s for %s is deprecated - please use 'bzr upgrade' to get better performance"
2783
 
                % (self._format, self.bzrdir.transport.base))
 
2753
        try:
 
2754
            if branch is None:
 
2755
                conf = config.GlobalConfig()
 
2756
            else:
 
2757
                conf = branch.get_config()
 
2758
            if conf.suppress_warning('format_deprecation'):
 
2759
                return
 
2760
            warning("Format %s for %s is deprecated -"
 
2761
                    " please use 'bzr upgrade' to get better performance"
 
2762
                    % (self._format, self.bzrdir.transport.base))
 
2763
        finally:
 
2764
            _deprecation_warning_done = True
2784
2765
 
2785
2766
    def supports_rich_root(self):
2786
2767
        return self._format.rich_root_data
3069
3050
    pack_compresses = False
3070
3051
    # Does the repository inventory storage understand references to trees?
3071
3052
    supports_tree_reference = None
 
3053
    # Is the format experimental ?
 
3054
    experimental = False
3072
3055
 
3073
 
    def __str__(self):
3074
 
        return "<%s>" % self.__class__.__name__
 
3056
    def __repr__(self):
 
3057
        return "%s()" % self.__class__.__name__
3075
3058
 
3076
3059
    def __eq__(self, other):
3077
3060
        # format objects are generally stateless
3090
3073
        """
3091
3074
        try:
3092
3075
            transport = a_bzrdir.get_repository_transport(None)
3093
 
            format_string = transport.get("format").read()
 
3076
            format_string = transport.get_bytes("format")
3094
3077
            return format_registry.get(format_string)
3095
3078
        except errors.NoSuchFile:
3096
3079
            raise errors.NoRepositoryPresent(a_bzrdir)
3195
3178
        """
3196
3179
        raise NotImplementedError(self.open)
3197
3180
 
 
3181
    def _run_post_repo_init_hooks(self, repository, a_bzrdir, shared):
 
3182
        from bzrlib.bzrdir import BzrDir, RepoInitHookParams
 
3183
        hooks = BzrDir.hooks['post_repo_init']
 
3184
        if not hooks:
 
3185
            return
 
3186
        params = RepoInitHookParams(repository, self, a_bzrdir, shared)
 
3187
        for hook in hooks:
 
3188
            hook(params)
 
3189
 
3198
3190
 
3199
3191
class MetaDirRepositoryFormat(RepositoryFormat):
3200
3192
    """Common base class for the new repositories using the metadir layout."""
3405
3397
 
3406
3398
        :param revision_id: if None all content is copied, if NULL_REVISION no
3407
3399
                            content is copied.
3408
 
        :param pb: optional progress bar to use for progress reports. If not
3409
 
                   provided a default one will be created.
 
3400
        :param pb: ignored.
3410
3401
        :return: None.
3411
3402
        """
 
3403
        ui.ui_factory.warn_experimental_format_fetch(self)
3412
3404
        from bzrlib.fetch import RepoFetcher
 
3405
        # See <https://launchpad.net/bugs/456077> asking for a warning here
 
3406
        if self.source._format.network_name() != self.target._format.network_name():
 
3407
            ui.ui_factory.show_user_warning('cross_format_fetch',
 
3408
                from_format=self.source._format,
 
3409
                to_format=self.target._format)
3413
3410
        f = RepoFetcher(to_repository=self.target,
3414
3411
                               from_repository=self.source,
3415
3412
                               last_revision=revision_id,
3416
3413
                               fetch_spec=fetch_spec,
3417
 
                               pb=pb, find_ghosts=find_ghosts)
 
3414
                               find_ghosts=find_ghosts)
3418
3415
 
3419
3416
    def _walk_to_common_revisions(self, revision_ids):
3420
3417
        """Walk out from revision_ids in source to revisions target has.
3816
3813
                basis_id, delta, current_revision_id, parents_parents)
3817
3814
            cache[current_revision_id] = parent_tree
3818
3815
 
3819
 
    def _fetch_batch(self, revision_ids, basis_id, cache):
 
3816
    def _fetch_batch(self, revision_ids, basis_id, cache, a_graph=None):
3820
3817
        """Fetch across a few revisions.
3821
3818
 
3822
3819
        :param revision_ids: The revisions to copy
3823
3820
        :param basis_id: The revision_id of a tree that must be in cache, used
3824
3821
            as a basis for delta when no other base is available
3825
3822
        :param cache: A cache of RevisionTrees that we can use.
 
3823
        :param a_graph: A Graph object to determine the heads() of the
 
3824
            rich-root data stream.
3826
3825
        :return: The revision_id of the last converted tree. The RevisionTree
3827
3826
            for it will be in cache
3828
3827
        """
3835
3834
        pending_revisions = []
3836
3835
        parent_map = self.source.get_parent_map(revision_ids)
3837
3836
        self._fetch_parent_invs_for_stacking(parent_map, cache)
 
3837
        self.source._safe_to_return_from_cache = True
3838
3838
        for tree in self.source.revision_trees(revision_ids):
3839
3839
            # Find a inventory delta for this revision.
3840
3840
            # Find text entries that need to be copied, too.
3888
3888
            pending_revisions.append(revision)
3889
3889
            cache[current_revision_id] = tree
3890
3890
            basis_id = current_revision_id
 
3891
        self.source._safe_to_return_from_cache = False
3891
3892
        # Copy file texts
3892
3893
        from_texts = self.source.texts
3893
3894
        to_texts = self.target.texts
3894
3895
        if root_keys_to_create:
3895
 
            from bzrlib.fetch import _new_root_data_stream
3896
 
            root_stream = _new_root_data_stream(
 
3896
            root_stream = _mod_fetch._new_root_data_stream(
3897
3897
                root_keys_to_create, self._revision_id_to_root_id, parent_map,
3898
 
                self.source)
 
3898
                self.source, graph=a_graph)
3899
3899
            to_texts.insert_record_stream(root_stream)
3900
3900
        to_texts.insert_record_stream(from_texts.get_record_stream(
3901
3901
            text_keys, self.target._format._fetch_order,
3958
3958
        cache[basis_id] = basis_tree
3959
3959
        del basis_tree # We don't want to hang on to it here
3960
3960
        hints = []
 
3961
        if self._converting_to_rich_root and len(revision_ids) > 100:
 
3962
            a_graph = _mod_fetch._get_rich_root_heads_graph(self.source,
 
3963
                                                            revision_ids)
 
3964
        else:
 
3965
            a_graph = None
 
3966
 
3961
3967
        for offset in range(0, len(revision_ids), batch_size):
3962
3968
            self.target.start_write_group()
3963
3969
            try:
3964
3970
                pb.update('Transferring revisions', offset,
3965
3971
                          len(revision_ids))
3966
3972
                batch = revision_ids[offset:offset+batch_size]
3967
 
                basis_id = self._fetch_batch(batch, basis_id, cache)
 
3973
                basis_id = self._fetch_batch(batch, basis_id, cache,
 
3974
                                             a_graph=a_graph)
3968
3975
            except:
 
3976
                self.source._safe_to_return_from_cache = False
3969
3977
                self.target.abort_write_group()
3970
3978
                raise
3971
3979
            else:
3983
3991
        """See InterRepository.fetch()."""
3984
3992
        if fetch_spec is not None:
3985
3993
            raise AssertionError("Not implemented yet...")
 
3994
        ui.ui_factory.warn_experimental_format_fetch(self)
3986
3995
        if (not self.source.supports_rich_root()
3987
3996
            and self.target.supports_rich_root()):
3988
3997
            self._converting_to_rich_root = True
3989
3998
            self._revision_id_to_root_id = {}
3990
3999
        else:
3991
4000
            self._converting_to_rich_root = False
 
4001
        # See <https://launchpad.net/bugs/456077> asking for a warning here
 
4002
        if self.source._format.network_name() != self.target._format.network_name():
 
4003
            ui.ui_factory.show_user_warning('cross_format_fetch',
 
4004
                from_format=self.source._format,
 
4005
                to_format=self.target._format)
3992
4006
        revision_ids = self.target.search_missing_revision_ids(self.source,
3993
4007
            revision_id, find_ghosts=find_ghosts).get_keys()
3994
4008
        if not revision_ids:
4063
4077
        :param to_convert: The disk object to convert.
4064
4078
        :param pb: a progress bar to use for progress information.
4065
4079
        """
4066
 
        self.pb = pb
 
4080
        pb = ui.ui_factory.nested_progress_bar()
4067
4081
        self.count = 0
4068
4082
        self.total = 4
4069
4083
        # this is only useful with metadir layouts - separated repo content.
4070
4084
        # trigger an assertion if not such
4071
4085
        repo._format.get_format_string()
4072
4086
        self.repo_dir = repo.bzrdir
4073
 
        self.step('Moving repository to repository.backup')
 
4087
        pb.update('Moving repository to repository.backup')
4074
4088
        self.repo_dir.transport.move('repository', 'repository.backup')
4075
4089
        backup_transport =  self.repo_dir.transport.clone('repository.backup')
4076
4090
        repo._format.check_conversion_target(self.target_format)
4077
4091
        self.source_repo = repo._format.open(self.repo_dir,
4078
4092
            _found=True,
4079
4093
            _override_transport=backup_transport)
4080
 
        self.step('Creating new repository')
 
4094
        pb.update('Creating new repository')
4081
4095
        converted = self.target_format.initialize(self.repo_dir,
4082
4096
                                                  self.source_repo.is_shared())
4083
4097
        converted.lock_write()
4084
4098
        try:
4085
 
            self.step('Copying content')
 
4099
            pb.update('Copying content')
4086
4100
            self.source_repo.copy_content_into(converted)
4087
4101
        finally:
4088
4102
            converted.unlock()
4089
 
        self.step('Deleting old repository content')
 
4103
        pb.update('Deleting old repository content')
4090
4104
        self.repo_dir.transport.delete_tree('repository.backup')
4091
4105
        ui.ui_factory.note('repository converted')
4092
 
 
4093
 
    def step(self, message):
4094
 
        """Update the pb by a step."""
4095
 
        self.count +=1
4096
 
        self.pb.update(message, self.count, self.total)
 
4106
        pb.finished()
4097
4107
 
4098
4108
 
4099
4109
_unescape_map = {
4443
4453
        fetching the inventory weave.
4444
4454
        """
4445
4455
        if self._rich_root_upgrade():
4446
 
            import bzrlib.fetch
4447
 
            return bzrlib.fetch.Inter1and2Helper(
 
4456
            return _mod_fetch.Inter1and2Helper(
4448
4457
                self.from_repository).generate_root_texts(revs)
4449
4458
        else:
4450
4459
            return []
4592
4601
 
4593
4602
    def _get_convertable_inventory_stream(self, revision_ids,
4594
4603
                                          delta_versus_null=False):
4595
 
        # The source is using CHKs, but the target either doesn't or it has a
4596
 
        # different serializer.  The StreamSink code expects to be able to
 
4604
        # The two formats are sufficiently different that there is no fast
 
4605
        # path, so we need to send just inventorydeltas, which any
 
4606
        # sufficiently modern client can insert into any repository.
 
4607
        # The StreamSink code expects to be able to
4597
4608
        # convert on the target, so we need to put bytes-on-the-wire that can
4598
4609
        # be converted.  That means inventory deltas (if the remote is <1.19,
4599
4610
        # RemoteStreamSink will fallback to VFS to insert the deltas).