~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/versioned/__init__.py

[merge] Storage filename escaping

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
2
 
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
24
24
import urllib
25
25
 
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
 
33
import bzrlib.ui
33
34
 
34
35
 
35
36
class VersionedFileStore(TransportStore):
37
38
 
38
39
    def __init__(self, transport, prefixed=False, precious=False,
39
40
                 dir_mode=None, file_mode=None,
40
 
                 versionedfile_class=WeaveFile):
41
 
        super(WeaveStore, self).__init__(transport,
 
41
                 versionedfile_class=WeaveFile,
 
42
                 escaped=False):
 
43
        super(VersionedFileStore, self).__init__(transport,
42
44
                dir_mode=dir_mode, file_mode=file_mode,
43
 
                prefixed=prefixed, compressed=False)
 
45
                prefixed=prefixed, compressed=False, escaped=escaped)
44
46
        self._precious = precious
45
47
        self._versionedfile_class = versionedfile_class
46
48
 
61
63
 
62
64
    def filename(self, file_id):
63
65
        """Return the path relative to the transport root."""
64
 
        if self._prefixed:
65
 
            return hash_prefix(file_id) + urllib.quote(file_id)
66
 
        else:
67
 
            return urllib.quote(file_id)
 
66
        return self._relpath(file_id)
68
67
 
69
68
    def __iter__(self):
70
69
        suffixes = self._versionedfile_class.get_suffixes()
72
71
        for relpath in self._iter_files_recursive():
73
72
            for suffix in suffixes:
74
73
                if relpath.endswith(suffix):
75
 
                    id = os.path.basename(relpath[:-len(suffix)])
76
 
                    if not id in ids:
77
 
                        yield id
78
 
                        ids.add(id)
 
74
                    # TODO: use standard remove_suffix function
 
75
                    escaped_id = os.path.basename(relpath[:-len(suffix)])
 
76
                    file_id = self._unescape(escaped_id)
 
77
                    if file_id not in ids:
 
78
                        ids.add(file_id)
 
79
                        yield file_id
 
80
                    break # only one suffix can match
79
81
 
80
82
    def has_id(self, fileid):
81
83
        suffixes = self._versionedfile_class.get_suffixes()
99
101
            self._transport.delete(filename + suffix)
100
102
        self._clear_cache_id(file_id, transaction)
101
103
 
 
104
    def _get(self, file_id):
 
105
        return self._transport.get(self.filename(file_id))
 
106
 
 
107
    def _put(self, file_id, f):
 
108
        fn = self.filename(file_id)
 
109
        try:
 
110
            return self._transport.put(fn, f, mode=self._file_mode)
 
111
        except NoSuchFile:
 
112
            if not self._prefixed:
 
113
                raise
 
114
            self._transport.mkdir(os.path.dirname(fn), mode=self._dir_mode)
 
115
            return self._transport.put(fn, f, mode=self._file_mode)
 
116
 
102
117
    def get_weave(self, file_id, transaction):
103
118
        weave = transaction.map.find_weave(file_id)
104
119
        if weave is not None:
124
139
 
125
140
        Returned as a list of lines.
126
141
        """
127
 
        assert 0
128
142
        w = self.get_weave(file_id, transaction)
129
143
        return w.get_lines(rev_id)
130
144
    
146
160
                # unexpected error - NoSuchFile is raised on a missing dir only and that
147
161
                # only occurs when we are prefixed.
148
162
                raise
149
 
            self._transport.mkdir(hash_prefix(file_id), mode=self._dir_mode)
 
163
            self._transport.mkdir(self.hash_prefix(file_id), mode=self._dir_mode)
150
164
            weave = self._versionedfile_class(self.filename(file_id), self._transport, self._file_mode, create=True)
151
165
        return weave
152
166
 
246
260
            # we are copying single objects, and there may be open tranasactions
247
261
            # so again with the passthrough
248
262
            to_transaction = PassThroughTransaction()
 
263
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
249
264
        for count, f in enumerate(file_ids):
250
265
            mutter("copy weave {%s} into %s", f, self)
251
 
            if pb:
252
 
                pb.update('copy', count, len(file_ids))
 
266
            pb.update('copy', count, len(file_ids))
253
267
            # if we have it in cache, its faster.
254
268
            # joining is fast with knits, and bearable for weaves -
255
269
            # indeed the new case can be optimised if needed.
256
270
            target = self._make_new_versionedfile(f, to_transaction)
257
271
            target.join(from_store.get_weave(f, from_transaction))
258
 
        if pb:
259
 
            pb.clear()
 
272
        pb.finished()
260
273
 
261
274
    def total_size(self):
262
275
        count, bytes =  super(VersionedFileStore, self).total_size()