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
55
def add_inventory(self, revid, inv, parents):
56
"""Add the inventory inv to the repository as revid.
58
:param parents: The revision ids of the parents that revid
59
is known to have and are in the repository already.
61
returns the sha1 of the serialized inventory.
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())
71
def add_revision(self, rev_id, rev, inv=None, config=None):
72
"""Add rev to the revision store as rev_id.
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.
82
if config is not None and config.signature_needed():
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():
90
raise errors.WeaveRevisionNotPresent(rev_id,
91
self.get_inventory_weave())
93
# yes, this is not suitable for adding with ghosts.
94
self.add_inventory(rev_id, inv, rev.parent_ids)
97
bzrlib.xml5.serializer_v5.write_revision(rev, rev_tmp)
99
self.revision_store.add(rev_tmp, rev_id)
100
mutter('added revision_id {%s}', rev_id)
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()
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.
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.
194
249
xml_file = self.get_revision_xml_file(revision_id)
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
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)
276
def _check_revision_parents(self, revision, inventory):
277
"""Private to Repository and Fetch.
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.
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:
290
raise errors.CorruptRepository(self)
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