~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

MergeĀ inĀ upstream.

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.inter import InterObject
27
28
from bzrlib.knit import KnitVersionedFile
28
29
from bzrlib.lockable_files import LockableFiles
53
54
    remote) disk.
54
55
    """
55
56
 
 
57
    @needs_write_lock
 
58
    def add_inventory(self, revid, inv, parents):
 
59
        """Add the inventory inv to the repository as revid.
 
60
        
 
61
        :param parents: The revision ids of the parents that revid
 
62
                        is known to have and are in the repository already.
 
63
 
 
64
        returns the sha1 of the serialized inventory.
 
65
        """
 
66
        inv_text = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
 
67
        inv_sha1 = bzrlib.osutils.sha_string(inv_text)
 
68
        inv_vf = self.control_weaves.get_weave('inventory',
 
69
                                               self.get_transaction())
 
70
        inv_vf.add_lines(revid, parents, bzrlib.osutils.split_lines(inv_text))
 
71
        return inv_sha1
 
72
 
 
73
    @needs_write_lock
 
74
    def add_revision(self, rev_id, rev, inv=None, config=None):
 
75
        """Add rev to the revision store as rev_id.
 
76
 
 
77
        :param rev_id: the revision id to use.
 
78
        :param rev: The revision object.
 
79
        :param inv: The inventory for the revision. if None, it will be looked
 
80
                    up in the inventory storer
 
81
        :param config: If None no digital signature will be created.
 
82
                       If supplied its signature_needed method will be used
 
83
                       to determine if a signature should be made.
 
84
        """
 
85
        if config is not None and config.signature_needed():
 
86
            if inv is None:
 
87
                inv = self.get_inventory(rev_id)
 
88
            plaintext = Testament(rev, inv).as_short_text()
 
89
            self.store_revision_signature(
 
90
                gpg.GPGStrategy(config), plaintext, rev_id)
 
91
        if not rev_id in self.get_inventory_weave():
 
92
            if inv is None:
 
93
                raise errors.WeaveRevisionNotPresent(rev_id,
 
94
                                                     self.get_inventory_weave())
 
95
            else:
 
96
                # yes, this is not suitable for adding with ghosts.
 
97
                self.add_inventory(rev_id, inv, rev.parent_ids)
 
98
            
 
99
        rev_tmp = StringIO()
 
100
        bzrlib.xml5.serializer_v5.write_revision(rev, rev_tmp)
 
101
        rev_tmp.seek(0)
 
102
        self.revision_store.add(rev_tmp, rev_id)
 
103
        mutter('added revision_id {%s}', rev_id)
 
104
 
56
105
    @needs_read_lock
57
106
    def _all_possible_ids(self):
58
107
        """Return all the possible revisions that we could find."""
72
121
            for rev_id in self.revision_store:
73
122
                rev = self.get_revision(rev_id)
74
123
                result_graph[rev_id] = rev.parent_ids
 
124
            # remove ghosts
 
125
            for rev_id, parents in result_graph.items():
 
126
                for parent in parents:
 
127
                    if not parent in result_graph:
 
128
                        del parents[parents.index(parent)]
75
129
            return topo_sort(result_graph.items())
76
130
        result = self._all_possible_ids()
77
131
        return self._eliminate_revisions_not_present(result)
206
260
        return self.get_revision_xml_file(revision_id).read()
207
261
 
208
262
    @needs_read_lock
 
263
    def get_revision_reconcile(self, revision_id):
 
264
        """'reconcile' helper routine that allows access to a revision always.
 
265
        
 
266
        This variant of get_revision does not cross check the weave graph
 
267
        against the revision one as get_revision does: but it should only
 
268
        be used by reconcile, or reconcile-alike commands that are correcting
 
269
        or testing the revision graph.
 
270
        """
 
271
        if not revision_id or not isinstance(revision_id, basestring):
 
272
            raise InvalidRevisionId(revision_id=revision_id, branch=self)
 
273
        return self._revision_store.get_revision(revision_id,
 
274
                                                 self.get_transaction())
 
275
 
 
276
    @needs_read_lock
209
277
    def get_revision(self, revision_id):
210
278
        """Return the Revision object for a named revision"""
211
 
        if not revision_id or not isinstance(revision_id, basestring):
212
 
            raise InvalidRevisionId(revision_id=revision_id, branch=self)
213
 
        return self._revision_store.get_revision(revision_id,
214
 
                                                 self.get_transaction())
 
279
        r = self.get_revision_reconcile(revision_id)
 
280
        # weave corruption can lead to absent revision markers that should be
 
281
        # present.
 
282
        # the following test is reasonably cheap (it needs a single weave read)
 
283
        # and the weave is cached in read transactions. In write transactions
 
284
        # it is not cached but typically we only read a small number of
 
285
        # revisions. For knits when they are introduced we will probably want
 
286
        # to ensure that caching write transactions are in use.
 
287
        inv = self.get_inventory_weave()
 
288
        self._check_revision_parents(r, inv)
 
289
        return r
 
290
 
 
291
    def _check_revision_parents(self, revision, inventory):
 
292
        """Private to Repository and Fetch.
 
293
        
 
294
        This checks the parentage of revision in an inventory weave for 
 
295
        consistency and is only applicable to inventory-weave-for-ancestry
 
296
        using repository formats & fetchers.
 
297
        """
 
298
        weave_parents = inventory.get_parents(revision.revision_id)
 
299
        weave_names = inventory.versions()
 
300
        for parent_id in revision.parent_ids:
 
301
            if parent_id in weave_names:
 
302
                # this parent must not be a ghost.
 
303
                if not parent_id in weave_parents:
 
304
                    # but it is a ghost
 
305
                    raise errors.CorruptRepository(self)
215
306
 
216
307
    @needs_write_lock
217
308
    def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
1005
1096
        utf8_files = [('format', self.get_format_string())]
1006
1097
        
1007
1098
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
 
1099
        repo_transport = a_bzrdir.get_repository_transport(None)
 
1100
        control_files = LockableFiles(repo_transport, 'lock')
 
1101
        control_store = self._get_control_store(repo_transport, control_files)
 
1102
        control_store.get_weave_or_empty('inventory',
 
1103
            bzrlib.transactions.PassThroughTransaction())
1008
1104
        return self.open(a_bzrdir=a_bzrdir, _found=True)
1009
1105
 
1010
1106