1
# Copyright (C) 2006 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""TextStore based revision store.
19
This stores revisions as individual text entries in a TextStore and
20
requires access to a inventory weave to produce object graphs.
24
from cStringIO import StringIO
31
revision as _mod_revision,
33
from bzrlib.store.revision import RevisionStore
34
from bzrlib.store.text import TextStore
35
from bzrlib.store.versioned import VersionedFileStore
36
from bzrlib.transport import get_transport
37
from bzrlib.tsort import topo_sort
40
class TextRevisionStoreTestFactory(object):
41
"""Factory to create a TextRevisionStore for testing.
43
This creates a inventory weave and hooks it into the revision store
46
def create(self, url):
47
"""Create a revision store at url."""
48
t = get_transport(url)
50
text_store = TextStore(t.clone('revstore'))
51
return TextRevisionStore(text_store)
54
return "TextRevisionStore"
57
class TextRevisionStore(RevisionStore):
58
"""A RevisionStore layering on a TextStore and Inventory weave store."""
60
def __init__(self, text_store, serializer=None):
61
"""Create a TextRevisionStore object.
63
:param text_store: the text store to put serialised revisions into.
65
super(TextRevisionStore, self).__init__(serializer)
66
self.text_store = text_store
67
self.text_store.register_suffix('sig')
69
def _add_revision(self, revision, revision_as_file, transaction):
70
"""Template method helper to store revision in this store."""
71
self.text_store.add(revision_as_file, revision.revision_id)
73
def add_revision_signature_text(self, revision_id, signature_text, transaction):
74
"""See RevisionStore.add_revision_signature_text()."""
75
self.text_store.add(StringIO(signature_text), revision_id, "sig")
77
def all_revision_ids(self, transaction):
78
"""See RevisionStore.all_revision_ids()."""
79
# for TextRevisionStores, this is only functional
80
# on listable transports.
82
for rev_id in self.text_store:
83
rev = self.get_revision(rev_id, transaction)
84
result_graph[rev_id] = rev.parent_ids
86
for rev_id, parents in result_graph.items():
87
for parent in list(parents):
88
if not parent in result_graph:
89
del parents[parents.index(parent)]
90
return topo_sort(result_graph.items())
92
def get_revisions(self, revision_ids, transaction):
93
"""See RevisionStore.get_revisions()."""
95
for revision_id in revision_ids:
96
xml_file = self._get_revision_xml_file(revision_id)
98
r = self._serializer.read_revision(xml_file)
99
except SyntaxError, e:
100
raise errors.BzrError('failed to unpack revision_xml %s %s' % (
101
revision_id, str(e)))
106
def _get_revision_xml_file(self, revision_id):
107
_mod_revision.check_not_reserved_id(revision_id)
109
return self.text_store.get(revision_id)
110
except (IndexError, KeyError):
111
raise errors.NoSuchRevision(self, revision_id)
113
def _get_signature_text(self, revision_id, transaction):
114
"""See RevisionStore._get_signature_text()."""
116
return self.text_store.get(revision_id, suffix='sig').read()
117
except (IndexError, KeyError):
118
raise errors.NoSuchRevision(self, revision_id)
120
def has_revision_id(self, revision_id, transaction):
121
"""True if the store contains revision_id."""
122
return (_mod_revision.is_null(revision_id)
123
or self.text_store.has_id(revision_id))
125
def _has_signature(self, revision_id, transaction):
126
"""See RevisionStore._has_signature()."""
127
return self.text_store.has_id(revision_id, suffix='sig')
129
def total_size(self, transaction):
130
""" See RevisionStore.total_size()."""
131
return self.text_store.total_size()