~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

 * New 'reconcile' command will check branch consistency and repair indexes
   that can become out of sync in pre 0.8 formats. (Robert Collins,
   Aaron Bentley)

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
from bzrlib.decorators import needs_read_lock, needs_write_lock
24
24
import bzrlib.errors as errors
25
25
from bzrlib.errors import InvalidRevisionId
 
26
import bzrlib.gpg as gpg
26
27
from bzrlib.lockable_files import LockableFiles
27
28
from bzrlib.osutils import safe_unicode
28
29
from bzrlib.revision import NULL_REVISION
50
51
    remote) disk.
51
52
    """
52
53
 
 
54
    @needs_write_lock
 
55
    def add_inventory(self, revid, inv, parents):
 
56
        """Add the inventory inv to the repository as revid.
 
57
        
 
58
        :param parents: The revision ids of the parents that revid
 
59
                        is known to have and are in the repository already.
 
60
 
 
61
        returns the sha1 of the serialized inventory.
 
62
        """
 
63
        inv_text = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
 
64
        inv_sha1 = bzrlib.osutils.sha_string(inv_text)
 
65
        self.control_weaves.add_text('inventory', revid,
 
66
                   bzrlib.osutils.split_lines(inv_text), parents,
 
67
                   self.get_transaction())
 
68
        return inv_sha1
 
69
 
 
70
    @needs_write_lock
 
71
    def add_revision(self, rev_id, rev, inv=None, config=None):
 
72
        """Add rev to the revision store as rev_id.
 
73
 
 
74
        :param rev_id: the revision id to use.
 
75
        :param rev: The revision object.
 
76
        :param inv: The inventory for the revision. if None, it will be looked
 
77
                    up in the inventory storer
 
78
        :param config: If None no digital signature will be created.
 
79
                       If supplied its signature_needed method will be used
 
80
                       to determine if a signature should be made.
 
81
        """
 
82
        if config is not None and config.signature_needed():
 
83
            if inv is None:
 
84
                inv = self.get_inventory(rev_id)
 
85
            plaintext = Testament(rev, inv).as_short_text()
 
86
            self.store_revision_signature(
 
87
                gpg.GPGStrategy(config), plaintext, rev_id)
 
88
        if not rev_id in self.get_inventory_weave():
 
89
            if inv is None:
 
90
                raise errors.WeaveRevisionNotPresent(rev_id,
 
91
                                                     self.get_inventory_weave())
 
92
            else:
 
93
                # yes, this is not suitable for adding with ghosts.
 
94
                self.add_inventory(rev_id, inv, rev.parent_ids)
 
95
            
 
96
        rev_tmp = StringIO()
 
97
        bzrlib.xml5.serializer_v5.write_revision(rev, rev_tmp)
 
98
        rev_tmp.seek(0)
 
99
        self.revision_store.add(rev_tmp, rev_id)
 
100
        mutter('added revision_id {%s}', rev_id)
 
101
 
53
102
    @needs_read_lock
54
103
    def _all_possible_ids(self):
55
104
        """Return all the possible revisions that we could find."""
189
238
        return self.get_revision_xml_file(revision_id).read()
190
239
 
191
240
    @needs_read_lock
192
 
    def get_revision(self, revision_id):
193
 
        """Return the Revision object for a named revision"""
 
241
    def get_revision_reconcile(self, revision_id):
 
242
        """'reconcile' helper routine that allows access to a revision always.
 
243
        
 
244
        This variant of get_revision does not cross check the weave graph
 
245
        against the revision one as get_revision does: but it should only
 
246
        be used by reconcile, or reconcile-alike commands that are correcting
 
247
        or testing the revision graph.
 
248
        """
194
249
        xml_file = self.get_revision_xml_file(revision_id)
195
250
 
196
251
        try:
204
259
        return r
205
260
 
206
261
    @needs_read_lock
 
262
    def get_revision(self, revision_id):
 
263
        """Return the Revision object for a named revision"""
 
264
        r = self.get_revision_reconcile(revision_id)
 
265
        # weave corruption can lead to absent revision markers that should be
 
266
        # present.
 
267
        # the following test is reasonably cheap (it needs a single weave read)
 
268
        # and the weave is cached in read transactions. In write transactions
 
269
        # it is not cached but typically we only read a small number of
 
270
        # revisions. For knits when they are introduced we will probably want
 
271
        # to ensure that caching write transactions are in use.
 
272
        inv = self.get_inventory_weave()
 
273
        self._check_revision_parents(r, inv)
 
274
        return r
 
275
 
 
276
    def _check_revision_parents(self, revision, inventory):
 
277
        """Private to Repository and Fetch.
 
278
        
 
279
        This checks the parentage of revision in an inventory weave for 
 
280
        consistency and is only applicable to inventory-weave-for-ancestry
 
281
        using repository formats & fetchers.
 
282
        """
 
283
        weave_parents = inventory.parent_names(revision.revision_id)
 
284
        weave_names = inventory.names()
 
285
        for parent_id in revision.parent_ids:
 
286
            if parent_id in weave_names:
 
287
                # this parent must not be a ghost.
 
288
                if not parent_id in weave_parents:
 
289
                    # but it is a ghost
 
290
                    raise errors.CorruptRepository(self)
 
291
 
 
292
    @needs_read_lock
207
293
    def get_revision_sha1(self, revision_id):
208
294
        """Hash the stored value of a revision, and return it."""
209
295
        # In the future, revision entries will be signed. At that