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
32
from bzrlib.store.revision import RevisionStore
33
from bzrlib.store.text import TextStore
34
from bzrlib.store.versioned import VersionedFileStore
35
from bzrlib.transport import get_transport
36
from bzrlib.tsort import topo_sort
39
class TextRevisionStoreTestFactory(object):
40
"""Factory to create a TextRevisionStore for testing.
42
This creates a inventory weave and hooks it into the revision store
45
def create(self, url):
46
"""Create a revision store at url."""
47
t = get_transport(url)
49
text_store = TextStore(t.clone('revstore'))
50
return TextRevisionStore(text_store)
53
return "TextRevisionStore"
56
class TextRevisionStore(RevisionStore):
57
"""A RevisionStore layering on a TextStore and Inventory weave store."""
59
def __init__(self, text_store, serializer=None):
60
"""Create a TextRevisionStore object.
62
:param text_store: the text store to put serialised revisions into.
64
super(TextRevisionStore, self).__init__(serializer)
65
self.text_store = text_store
66
self.text_store.register_suffix('sig')
68
def _add_revision(self, revision, revision_as_file, transaction):
69
"""Template method helper to store revision in this store."""
70
self.text_store.add(revision_as_file, revision.revision_id)
72
def add_revision_signature_text(self, revision_id, signature_text, transaction):
73
"""See RevisionStore.add_revision_signature_text()."""
74
self.text_store.add(StringIO(signature_text), revision_id, "sig")
76
def all_revision_ids(self, transaction):
77
"""See RevisionStore.all_revision_ids()."""
78
# for TextRevisionStores, this is only functional
79
# on listable transports.
80
assert self.text_store.listable()
82
for rev_id in self.text_store:
83
rev_id = osutils.safe_revision_id(rev_id)
84
rev = self.get_revision(rev_id, transaction)
85
result_graph[rev_id] = rev.parent_ids
87
for rev_id, parents in result_graph.items():
88
for parent in list(parents):
89
if not parent in result_graph:
90
del parents[parents.index(parent)]
91
return topo_sort(result_graph.items())
93
def get_revisions(self, revision_ids, transaction):
94
"""See RevisionStore.get_revisions()."""
96
for revision_id in revision_ids:
97
xml_file = self._get_revision_xml_file(revision_id)
99
r = self._serializer.read_revision(xml_file)
100
except SyntaxError, e:
101
raise errors.BzrError('failed to unpack revision_xml',
105
assert r.revision_id == revision_id
109
def _get_revision_xml_file(self, revision_id):
111
return self.text_store.get(revision_id)
112
except (IndexError, KeyError):
113
raise errors.NoSuchRevision(self, revision_id)
115
def _get_signature_text(self, revision_id, transaction):
116
"""See RevisionStore._get_signature_text()."""
118
return self.text_store.get(revision_id, suffix='sig').read()
119
except (IndexError, KeyError):
120
raise errors.NoSuchRevision(self, revision_id)
122
def has_revision_id(self, revision_id, transaction):
123
"""True if the store contains revision_id."""
124
return (revision_id is None
125
or self.text_store.has_id(revision_id))
127
def _has_signature(self, revision_id, transaction):
128
"""See RevisionStore._has_signature()."""
129
return self.text_store.has_id(revision_id, suffix='sig')
131
def total_size(self, transaction):
132
""" See RevisionStore.total_size()."""
133
return self.text_store.total_size()