1
# Copyright (C) 2005 by Canonical Development Ltd
1
# Copyright (C) 2005, 2006 by Canonical Development 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
207
207
def has_id(self, fileid, suffix=None):
208
208
"""See Store.has_id."""
209
return self._transport.has_any(self._id_to_names(fileid, suffix))
209
paths = self._id_to_names(fileid, suffix)
210
if not self._transport.has_any(paths):
211
214
def _get_name(self, fileid, suffix=None):
212
215
"""A special check, which returns the name of an existing file.
238
241
raise KeyError(fileid)
240
243
def __init__(self, a_transport, prefixed=False, compressed=False,
241
dir_mode=None, file_mode=None):
244
dir_mode=None, file_mode=None,
242
246
assert isinstance(a_transport, transport.Transport)
243
247
super(TransportStore, self).__init__()
244
248
self._transport = a_transport
246
250
# FIXME RBC 20051128 this belongs in TextStore.
247
251
self._compressed = compressed
248
252
self._suffixes = set()
253
self._escaped = escaped
250
255
# It is okay for these to be None, it just means they
251
256
# will just use the filesystem defaults
252
257
self._dir_mode = dir_mode
253
258
self._file_mode = file_mode
260
def _unescape(self, file_id):
261
"""If filename escaping is enabled for this store, unescape and return the filename."""
263
return urllib.unquote(file_id)
255
267
def _iter_files_recursive(self):
256
268
"""Iterate through the files in the transport."""
257
269
for quoted_relpath in self._transport.iter_files_recursive():
270
# transport iterator always returns quoted paths, regardless of
258
272
yield urllib.unquote(quoted_relpath)
260
274
def __iter__(self):
286
300
if self._prefixed:
287
path = [hash_prefix(fileid) + fileid]
301
# hash_prefix adds the '/' separator
302
prefix = self.hash_prefix(fileid)
290
path.extend(suffixes)
291
return transport.urlescape(u'.'.join(path))
305
fileid = self._escape_file_id(fileid)
306
path = prefix + fileid
307
full_path = u'.'.join([path] + suffixes)
308
return transport.urlescape(full_path)
310
def _escape_file_id(self, file_id):
311
"""Turn a file id into a filesystem safe string.
313
This is similar to a plain urllib.quote, except
314
it uses specific safe characters, so that it doesn't
315
have to translate a lot of valid file ids.
317
if not self._escaped:
319
if isinstance(file_id, unicode):
320
file_id = file_id.encode('utf-8')
321
# @ does not get escaped. This is because it is a valid
322
# filesystem character we use all the time, and it looks
323
# a lot better than seeing %40 all the time.
324
safe = "abcdefghijklmnopqrstuvwxyz0123456789-_@,."
325
r = [((c in safe) and c or ('%%%02x' % ord(c)))
329
def hash_prefix(self, fileid):
330
# fileid should be unescaped
332
fileid = self._escape_file_id(fileid)
333
return "%02x/" % (adler32(fileid) & 0xff)
293
335
def __repr__(self):
294
336
if self._transport is None:
331
373
def copy_all(store_from, store_to, pb=None):
332
374
"""Copy all ids from one store to another."""
333
375
store_to.copy_all_ids(store_from, pb)
336
def hash_prefix(fileid):
337
return "%02x/" % (adler32(fileid) & 0xff)