16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
# XXX: Some consideration of the problems that might occur if there are
20
# files whose id differs only in case. That should probably be forbidden.
23
from cStringIO import StringIO
19
# Author: Martin Pool <mbp@canonical.com>
27
25
from bzrlib.weavefile import read_weave, write_weave_v5
28
26
from bzrlib.weave import Weave
29
from bzrlib.store import Store
30
27
from bzrlib.atomicfile import AtomicFile
31
from bzrlib.errors import NoSuchFile
32
from bzrlib.trace import mutter
35
class WeaveStore(Store):
32
class WeaveStore(object):
36
33
"""Collection of several weave files in a directory.
38
35
This has some shortcuts for reading and writing them.
40
FILE_SUFFIX = '.weave'
42
def __init__(self, transport):
43
self._transport = transport
37
def __init__(self, dir, get_file=None):
45
40
self.enable_cache = False
41
if get_file is not None:
42
self.get_file = get_file
44
def get_file(self, filename):
45
return file(filename, 'rb')
48
47
def filename(self, file_id):
49
"""Return the path relative to the transport root."""
50
return file_id + WeaveStore.FILE_SUFFIX
53
l = len(WeaveStore.FILE_SUFFIX)
54
for f in self._transport.list_dir('.'):
55
if f.endswith(WeaveStore.FILE_SUFFIX):
59
def __contains__(self, fileid):
61
return self._transport.has(self.filename(fileid))
63
def _get(self, file_id):
64
return self._transport.get(self.filename(file_id))
66
def _put(self, file_id, f):
67
return self._transport.put(self.filename(file_id), f)
48
return self._dir + os.sep + file_id + '.weave'
69
51
def get_weave(self, file_id):
70
52
if self.enable_cache:
71
53
if file_id in self._cache:
72
mutter("cache hit in %s for %s", self, file_id)
73
54
return self._cache[file_id]
74
w = read_weave(self._get(file_id))
55
w = read_weave(self.get_file(self.filename(file_id)))
75
56
if self.enable_cache:
76
57
self._cache[file_id] = w
88
69
def get_weave_or_empty(self, file_id):
89
70
"""Return a weave, or an empty one if it doesn't exist."""
91
inf = self._get(file_id)
93
return Weave(weave_name=file_id)
72
inf = self.get_file(self.filename(file_id))
74
if e.errno == errno.ENOENT:
75
return Weave(weave_name=file_id)
95
79
return read_weave(inf)
82
def put_empty_weave(self, file_id):
83
self.put_weave(file_id, Weave())
98
86
def put_weave(self, file_id, weave):
99
87
"""Write back a modified weave"""
100
88
if self.enable_cache:
101
89
self._cache[file_id] = weave
104
write_weave_v5(weave, sio)
107
self._put(file_id, sio)
90
weave_fn = self.filename(file_id)
91
af = AtomicFile(weave_fn)
93
write_weave_v5(weave, af)
110
99
def add_text(self, file_id, rev_id, new_lines, parents):
113
102
w.add(rev_id, parent_idxs, new_lines)
114
103
self.put_weave(file_id, w)
116
def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents):
117
w = self.get_weave_or_empty(file_id)
118
parent_idxs = map(w.lookup, parents)
119
w.add_identical(old_rev_id, new_rev_id, parent_idxs)
120
self.put_weave(file_id, w)
122
def copy_multi(self, from_store, file_ids):
123
assert isinstance(from_store, WeaveStore)
125
mutter("copy weave {%s} into %s", f, self)
126
self._put(f, from_store._get(f))