1
# Copyright (C) 2005 Canonical Ltd
1
# Copyright (C) 2005, 2006 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
26
26
from bzrlib.weavefile import read_weave, write_weave_v5
27
from bzrlib.weave import WeaveFile
28
from bzrlib.store import TransportStore, hash_prefix
27
from bzrlib.weave import WeaveFile, Weave
28
from bzrlib.store import TransportStore
29
29
from bzrlib.atomicfile import AtomicFile
30
30
from bzrlib.errors import NoSuchFile, FileExists
31
31
from bzrlib.symbol_versioning import *
32
32
from bzrlib.trace import mutter
35
36
class VersionedFileStore(TransportStore):
36
37
"""Collection of many versioned files in a transport."""
39
# TODO: Rather than passing versionedfile_kwargs, perhaps pass in a
40
# transport factory callable?
38
41
def __init__(self, transport, prefixed=False, precious=False,
39
42
dir_mode=None, file_mode=None,
40
43
versionedfile_class=WeaveFile,
41
versionedfile_kwargs={}):
42
super(WeaveStore, self).__init__(transport,
44
versionedfile_kwargs={},
46
super(VersionedFileStore, self).__init__(transport,
43
47
dir_mode=dir_mode, file_mode=file_mode,
44
prefixed=prefixed, compressed=False)
48
prefixed=prefixed, compressed=False, escaped=escaped)
45
49
self._precious = precious
46
50
self._versionedfile_class = versionedfile_class
47
51
self._versionedfile_kwargs = versionedfile_kwargs
64
68
def filename(self, file_id):
65
69
"""Return the path relative to the transport root."""
67
return hash_prefix(file_id) + urllib.quote(file_id)
69
return urllib.quote(file_id)
70
return self._relpath(file_id)
71
72
def __iter__(self):
72
73
suffixes = self._versionedfile_class.get_suffixes()
74
75
for relpath in self._iter_files_recursive():
75
76
for suffix in suffixes:
76
77
if relpath.endswith(suffix):
77
id = os.path.basename(relpath[:-len(suffix)])
78
# TODO: use standard remove_suffix function
79
escaped_id = os.path.basename(relpath[:-len(suffix)])
80
file_id = self._unescape(escaped_id)
81
if file_id not in ids:
84
break # only one suffix can match
82
86
def has_id(self, fileid):
83
87
suffixes = self._versionedfile_class.get_suffixes()
101
105
self._transport.delete(filename + suffix)
102
106
self._clear_cache_id(file_id, transaction)
108
def _get(self, file_id):
109
return self._transport.get(self.filename(file_id))
111
def _put(self, file_id, f):
112
fn = self.filename(file_id)
114
return self._transport.put(fn, f, mode=self._file_mode)
116
if not self._prefixed:
118
self._transport.mkdir(os.path.dirname(fn), mode=self._dir_mode)
119
return self._transport.put(fn, f, mode=self._file_mode)
104
121
def get_weave(self, file_id, transaction):
105
122
weave = transaction.map.find_weave(file_id)
106
123
if weave is not None:
151
167
# unexpected error - NoSuchFile is raised on a missing dir only and that
152
168
# only occurs when we are prefixed.
154
self._transport.mkdir(hash_prefix(file_id), mode=self._dir_mode)
155
weave = self._versionedfile_class(self.filename(file_id), self._transport, self._file_mode, create=True,
170
self._transport.mkdir(self.hash_prefix(file_id), mode=self._dir_mode)
171
weave = self._versionedfile_class(self.filename(file_id), self._transport,
172
self._file_mode, create=True,
156
173
**self._versionedfile_kwargs)
252
269
# we are copying single objects, and there may be open tranasactions
253
270
# so again with the passthrough
254
271
to_transaction = PassThroughTransaction()
272
pb = bzrlib.ui.ui_factory.nested_progress_bar()
255
273
for count, f in enumerate(file_ids):
256
274
mutter("copy weave {%s} into %s", f, self)
258
pb.update('copy', count, len(file_ids))
275
pb.update('copy', count, len(file_ids))
259
276
# if we have it in cache, its faster.
260
277
# joining is fast with knits, and bearable for weaves -
261
278
# indeed the new case can be optimised if needed.
262
279
target = self._make_new_versionedfile(f, to_transaction)
263
280
target.join(from_store.get_weave(f, from_transaction))
267
283
def total_size(self):
268
284
count, bytes = super(VersionedFileStore, self).total_size()