~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
from bzrlib.lazy_import import lazy_import
18
18
lazy_import(globals(), """
19
 
import cStringIO
20
 
import re
21
19
import time
22
20
 
23
21
from bzrlib import (
24
22
    bzrdir,
25
23
    check,
26
 
    chk_map,
27
24
    config,
28
25
    controldir,
29
26
    debug,
32
29
    generate_ids,
33
30
    gpg,
34
31
    graph,
35
 
    inventory,
36
32
    inventory_delta,
37
33
    lockable_files,
38
34
    lockdir,
39
35
    lru_cache,
40
36
    osutils,
41
 
    pyutils,
42
37
    revision as _mod_revision,
43
38
    static_tuple,
44
 
    trace,
45
39
    tsort,
46
40
    versionedfile,
47
41
    )
48
42
from bzrlib.bundle import serializer
49
43
from bzrlib.recordcounter import RecordCounter
50
 
from bzrlib.revisiontree import RevisionTree
 
44
from bzrlib.revisiontree import InventoryRevisionTree
51
45
from bzrlib.store.versioned import VersionedFileStore
52
46
from bzrlib.testament import Testament
53
47
""")
99
93
 
100
94
    def __init__(self, repository, parents, config, timestamp=None,
101
95
                 timezone=None, committer=None, revprops=None,
102
 
                 revision_id=None):
 
96
                 revision_id=None, lossy=False):
103
97
        """Initiate a CommitBuilder.
104
98
 
105
99
        :param repository: Repository to commit to.
106
100
        :param parents: Revision ids of the parents of the new revision.
107
 
        :param config: Configuration to use.
108
101
        :param timestamp: Optional timestamp recorded for commit.
109
102
        :param timezone: Optional timezone for timestamp.
110
103
        :param committer: Optional committer to set for commit.
111
104
        :param revprops: Optional dictionary of revision properties.
112
105
        :param revision_id: Optional revision id.
 
106
        :param lossy: Whether to discard data that can not be natively
 
107
            represented, when pushing to a foreign VCS 
113
108
        """
114
109
        self._config = config
 
110
        self._lossy = lossy
115
111
 
116
112
        if committer is None:
117
113
            self._committer = self._config.username()
240
236
    def revision_tree(self):
241
237
        """Return the tree that was just committed.
242
238
 
243
 
        After calling commit() this can be called to get a RevisionTree
244
 
        representing the newly committed tree. This is preferred to
245
 
        calling Repository.revision_tree() because that may require
246
 
        deserializing the inventory, while we already have a copy in
 
239
        After calling commit() this can be called to get a
 
240
        InventoryRevisionTree representing the newly committed tree. This is
 
241
        preferred to calling Repository.revision_tree() because that may
 
242
        require deserializing the inventory, while we already have a copy in
247
243
        memory.
248
244
        """
249
245
        if self.new_inventory is None:
250
246
            self.new_inventory = self.repository.get_inventory(
251
247
                self._new_revision_id)
252
 
        return RevisionTree(self.repository, self.new_inventory,
 
248
        return InventoryRevisionTree(self.repository, self.new_inventory,
253
249
            self._new_revision_id)
254
250
 
255
251
    def finish_inventory(self):
1167
1163
        if config is not None and config.signature_needed():
1168
1164
            if inv is None:
1169
1165
                inv = self.get_inventory(revision_id)
1170
 
            plaintext = Testament(rev, inv).as_short_text()
 
1166
            tree = InventoryRevisionTree(self, inv, revision_id)
 
1167
            testament = Testament(rev, tree)
 
1168
            plaintext = testament.as_short_text()
1171
1169
            self.store_revision_signature(
1172
1170
                gpg.GPGStrategy(config), plaintext, revision_id)
1173
1171
        # check inventory present
1789
1787
 
1790
1788
    def get_commit_builder(self, branch, parents, config, timestamp=None,
1791
1789
                           timezone=None, committer=None, revprops=None,
1792
 
                           revision_id=None):
 
1790
                           revision_id=None, lossy=False):
1793
1791
        """Obtain a CommitBuilder for this repository.
1794
1792
 
1795
1793
        :param branch: Branch to commit to.
1800
1798
        :param committer: Optional committer to set for commit.
1801
1799
        :param revprops: Optional dictionary of revision properties.
1802
1800
        :param revision_id: Optional revision id.
 
1801
        :param lossy: Whether to discard data that can not be natively
 
1802
            represented, when pushing to a foreign VCS
1803
1803
        """
1804
1804
        if self._fallback_repositories and not self._format.supports_chks:
1805
1805
            raise errors.BzrError("Cannot commit directly to a stacked branch"
1806
1806
                " in pre-2a formats. See "
1807
1807
                "https://bugs.launchpad.net/bzr/+bug/375013 for details.")
1808
1808
        result = self._commit_builder_class(self, parents, config,
1809
 
            timestamp, timezone, committer, revprops, revision_id)
 
1809
            timestamp, timezone, committer, revprops, revision_id,
 
1810
            lossy)
1810
1811
        self.start_write_group()
1811
1812
        return result
1812
1813
 
2514
2515
        # TODO: refactor this to use an existing revision object
2515
2516
        # so we don't need to read it in twice.
2516
2517
        if revision_id == _mod_revision.NULL_REVISION:
2517
 
            return RevisionTree(self, Inventory(root_id=None),
2518
 
                                _mod_revision.NULL_REVISION)
 
2518
            return InventoryRevisionTree(self,
 
2519
                Inventory(root_id=None), _mod_revision.NULL_REVISION)
2519
2520
        else:
2520
2521
            inv = self.get_inventory(revision_id)
2521
 
            return RevisionTree(self, inv, revision_id)
 
2522
            return InventoryRevisionTree(self, inv, revision_id)
2522
2523
 
2523
2524
    def revision_trees(self, revision_ids):
2524
2525
        """Return Trees for revisions in this repository.
2528
2529
        """
2529
2530
        inventories = self.iter_inventories(revision_ids)
2530
2531
        for inv in inventories:
2531
 
            yield RevisionTree(self, inv, inv.revision_id)
 
2532
            yield InventoryRevisionTree(self, inv, inv.revision_id)
2532
2533
 
2533
2534
    def _filtered_revision_trees(self, revision_ids, file_ids):
2534
2535
        """Return Tree for a revision on this branch with only some files.
2544
2545
            # Should we introduce a FilteredRevisionTree class rather
2545
2546
            # than pre-filter the inventory here?
2546
2547
            filtered_inv = inv.filter(file_ids)
2547
 
            yield RevisionTree(self, filtered_inv, filtered_inv.revision_id)
 
2548
            yield InventoryRevisionTree(self, filtered_inv, filtered_inv.revision_id)
2548
2549
 
2549
2550
    @needs_read_lock
2550
2551
    def get_ancestry(self, revision_id, topo_sorted=True):
2772
2773
                except UnicodeDecodeError:
2773
2774
                    raise errors.NonAsciiRevisionId(method, self)
2774
2775
 
2775
 
    def revision_graph_can_have_wrong_parents(self):
2776
 
        """Is it possible for this repository to have a revision graph with
2777
 
        incorrect parents?
 
2776
    def _find_inconsistent_revision_parents(self, revisions_iterator=None):
 
2777
        """Find revisions with different parent lists in the revision object
 
2778
        and in the index graph.
2778
2779
 
2779
 
        If True, then this repository must also implement
2780
 
        _find_inconsistent_revision_parents so that check and reconcile can
2781
 
        check for inconsistencies before proceeding with other checks that may
2782
 
        depend on the revision index being consistent.
 
2780
        :param revisions_iterator: None, or an iterator of (revid,
 
2781
            Revision-or-None). This iterator controls the revisions checked.
 
2782
        :returns: an iterator yielding tuples of (revison-id, parents-in-index,
 
2783
            parents-in-revision).
2783
2784
        """
2784
 
        raise NotImplementedError(self.revision_graph_can_have_wrong_parents)
 
2785
        if not self.is_locked():
 
2786
            raise AssertionError()
 
2787
        vf = self.revisions
 
2788
        if revisions_iterator is None:
 
2789
            revisions_iterator = self._iter_revisions(None)
 
2790
        for revid, revision in revisions_iterator:
 
2791
            if revision is None:
 
2792
                pass
 
2793
            parent_map = vf.get_parent_map([(revid,)])
 
2794
            parents_according_to_index = tuple(parent[-1] for parent in
 
2795
                parent_map[(revid,)])
 
2796
            parents_according_to_revision = tuple(revision.parent_ids)
 
2797
            if parents_according_to_index != parents_according_to_revision:
 
2798
                yield (revid, parents_according_to_index,
 
2799
                    parents_according_to_revision)
 
2800
 
 
2801
    def _check_for_inconsistent_revision_parents(self):
 
2802
        inconsistencies = list(self._find_inconsistent_revision_parents())
 
2803
        if inconsistencies:
 
2804
            raise errors.BzrCheckError(
 
2805
                "Revision knit has inconsistent parents.")
2785
2806
 
2786
2807
 
2787
2808
def install_revision(repository, rev, revision_tree):
2846
2867
        for revision, tree in parent_trees.iteritems():
2847
2868
            if ie.file_id not in tree:
2848
2869
                continue
2849
 
            parent_id = tree.inventory[ie.file_id].revision
 
2870
            parent_id = tree.get_file_revision(ie.file_id)
2850
2871
            if parent_id in text_parents:
2851
2872
                continue
2852
2873
            text_parents.append((ie.file_id, parent_id))
3024
3045
    supports_leaving_lock = None
3025
3046
    # Does this format support the full VersionedFiles interface?
3026
3047
    supports_full_versioned_files = None
 
3048
    # Does this format support signing revision signatures?
 
3049
    supports_revision_signatures = True
 
3050
    # Can the revision graph have incorrect parents?
 
3051
    revision_graph_can_have_wrong_parents = None
3027
3052
 
3028
3053
    def __repr__(self):
3029
3054
        return "%s()" % self.__class__.__name__
3249
3274
# NOTE: These are experimental in 0.92. Stable in 1.0 and above
3250
3275
format_registry.register_lazy(
3251
3276
    'Bazaar pack repository format 1 (needs bzr 0.92)\n',
3252
 
    'bzrlib.repofmt.pack_repo',
 
3277
    'bzrlib.repofmt.knitpack_repo',
3253
3278
    'RepositoryFormatKnitPack1',
3254
3279
    )
3255
3280
format_registry.register_lazy(
3256
3281
    'Bazaar pack repository format 1 with subtree support (needs bzr 0.92)\n',
3257
 
    'bzrlib.repofmt.pack_repo',
 
3282
    'bzrlib.repofmt.knitpack_repo',
3258
3283
    'RepositoryFormatKnitPack3',
3259
3284
    )
3260
3285
format_registry.register_lazy(
3261
3286
    'Bazaar pack repository format 1 with rich root (needs bzr 1.0)\n',
3262
 
    'bzrlib.repofmt.pack_repo',
 
3287
    'bzrlib.repofmt.knitpack_repo',
3263
3288
    'RepositoryFormatKnitPack4',
3264
3289
    )
3265
3290
format_registry.register_lazy(
3266
3291
    'Bazaar RepositoryFormatKnitPack5 (bzr 1.6)\n',
3267
 
    'bzrlib.repofmt.pack_repo',
 
3292
    'bzrlib.repofmt.knitpack_repo',
3268
3293
    'RepositoryFormatKnitPack5',
3269
3294
    )
3270
3295
format_registry.register_lazy(
3271
3296
    'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6.1)\n',
3272
 
    'bzrlib.repofmt.pack_repo',
 
3297
    'bzrlib.repofmt.knitpack_repo',
3273
3298
    'RepositoryFormatKnitPack5RichRoot',
3274
3299
    )
3275
3300
format_registry.register_lazy(
3276
3301
    'Bazaar RepositoryFormatKnitPack5RichRoot (bzr 1.6)\n',
3277
 
    'bzrlib.repofmt.pack_repo',
 
3302
    'bzrlib.repofmt.knitpack_repo',
3278
3303
    'RepositoryFormatKnitPack5RichRootBroken',
3279
3304
    )
3280
3305
format_registry.register_lazy(
3281
3306
    'Bazaar RepositoryFormatKnitPack6 (bzr 1.9)\n',
3282
 
    'bzrlib.repofmt.pack_repo',
 
3307
    'bzrlib.repofmt.knitpack_repo',
3283
3308
    'RepositoryFormatKnitPack6',
3284
3309
    )
3285
3310
format_registry.register_lazy(
3286
3311
    'Bazaar RepositoryFormatKnitPack6RichRoot (bzr 1.9)\n',
3287
 
    'bzrlib.repofmt.pack_repo',
 
3312
    'bzrlib.repofmt.knitpack_repo',
3288
3313
    'RepositoryFormatKnitPack6RichRoot',
3289
3314
    )
3290
3315
format_registry.register_lazy(
3298
3323
format_registry.register_lazy(
3299
3324
    ("Bazaar development format 2 with subtree support "
3300
3325
        "(needs bzr.dev from before 1.8)\n"),
3301
 
    'bzrlib.repofmt.pack_repo',
 
3326
    'bzrlib.repofmt.knitpack_repo',
3302
3327
    'RepositoryFormatPackDevelopment2Subtree',
3303
3328
    )
3304
3329
format_registry.register_lazy(
4173
4198
                parse_result = deserialiser.parse_text_bytes(
4174
4199
                    inventory_delta_bytes)
4175
4200
            except inventory_delta.IncompatibleInventoryDelta, err:
4176
 
                trace.mutter("Incompatible delta: %s", err.msg)
 
4201
                mutter("Incompatible delta: %s", err.msg)
4177
4202
                raise errors.IncompatibleRevision(self.target_repo._format)
4178
4203
            basis_id, new_id, rich_root, tree_refs, inv_delta = parse_result
4179
4204
            revision_id = new_id