/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1608.2.1 by Martin Pool
[merge] Storage filename escaping
1
# Copyright (C) 2005, 2006 by Canonical Development Ltd
1 by mbp at sourcefrog
import from baz patch-364
2
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.
7
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.
12
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
16
1374 by Martin Pool
todo
17
# TODO: Could remember a bias towards whether a particular store is typically
18
# compressed or not.
19
711 by Martin Pool
- store docs
20
"""
21
Stores are the main data-storage mechanism for Bazaar-NG.
1 by mbp at sourcefrog
import from baz patch-364
22
23
A store is a simple write-once container indexed by a universally
711 by Martin Pool
- store docs
24
unique ID.
25
"""
1 by mbp at sourcefrog
import from baz patch-364
26
1442.1.51 by Robert Collins
teach iter about suffixes
27
import os
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
28
from cStringIO import StringIO
1479 by Robert Collins
More quoting at the transport layer bugfixes.
29
import urllib
1429 by Robert Collins
merge in niemeyers prefixed-store patch
30
from zlib import adler32
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
31
1442.1.44 by Robert Collins
Many transport related tweaks:
32
import bzrlib
1433 by Robert Collins
merge in and make incremental Gustavo Niemeyers nested log patch, and remove all bare exceptions in store and transport packages.
33
import bzrlib.errors as errors
1393.2.3 by John Arbash Meinel
Fixing typos, updating stores, getting tests to pass.
34
from bzrlib.errors import BzrError, UnlistableStore, TransportNotPossible
1563.2.14 by Robert Collins
Prepare weave store to delegate copy details to the versioned file.
35
from bzrlib.symbol_versioning import *
1104 by Martin Pool
- Add a simple UIFactory
36
from bzrlib.trace import mutter
1651.1.7 by Martin Pool
Move small ImmutableMemoryStore class into test module,
37
from bzrlib.transport import Transport, urlescape
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
38
from bzrlib.transport.local import LocalTransport
1 by mbp at sourcefrog
import from baz patch-364
39
40
######################################################################
41
# stores
42
43
class StoreError(Exception):
44
    pass
45
46
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
47
class Store(object):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
48
    """This class represents the abstract storage layout for saving information.
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
49
    
1 by mbp at sourcefrog
import from baz patch-364
50
    Files can be added, but not modified once they are in.  Typically
51
    the hash is used as the name, or something else known to be unique,
52
    such as a UUID.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
53
    """
54
55
    def __len__(self):
56
        raise NotImplementedError('Children should define their length')
57
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
58
    def get(self, fileid, suffix=None):
1442.1.50 by Robert Collins
test get with suffixes
59
        """Returns a file reading from a particular entry.
60
        
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
61
        If suffix is present, retrieve the named suffix for fileid.
1442.1.50 by Robert Collins
test get with suffixes
62
        """
63
        raise NotImplementedError
1442.1.35 by Robert Collins
convert all users of __getitem__ into TransportStores to use .get instead
64
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
65
    def __getitem__(self, fileid):
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
66
        """DEPRECATED. Please use .get(fileid) instead."""
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
67
        raise NotImplementedError
68
1442.1.45 by Robert Collins
replace __contains__ calls in stores with has_id
69
    #def __contains__(self, fileid):
70
    #    """Deprecated, please use has_id"""
71
    #    raise NotImplementedError
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
72
73
    def __iter__(self):
74
        raise NotImplementedError
75
907.1.43 by John Arbash Meinel
Restoring compatibility for Storage.add(file, fileid), it is a little arbitrary, and compatibility is better
76
    def add(self, f, fileid):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
77
        """Add a file object f to the store accessible from the given fileid"""
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
78
        raise NotImplementedError('Children of Store must define their method of adding entries.')
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
79
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
80
    def has_id(self, fileid, suffix=None):
81
        """Return True or false for the presence of fileid in the store.
1442.1.47 by Robert Collins
test for has with suffixed files
82
        
83
        suffix, if present, is a per file suffix, i.e. for digital signature 
84
        data."""
1442.1.45 by Robert Collins
replace __contains__ calls in stores with has_id
85
        raise NotImplementedError
907.1.36 by John Arbash Meinel
Moving the multi-get functionality higher up into the Branch class.
86
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
87
    def listable(self):
88
        """Return True if this store is able to be listed."""
89
        return hasattr(self, "__iter__")
90
1563.2.14 by Robert Collins
Prepare weave store to delegate copy details to the versioned file.
91
    def copy_all_ids(self, store_from, pb=None):
92
        """Copy all the file ids from store_from into self."""
93
        if not store_from.listable():
94
            raise UnlistableStore(store_from)
95
        ids = []
96
        for count, file_id in enumerate(store_from):
97
            if pb:
98
                pb.update('listing files', count, count)
99
            ids.append(file_id)
100
        if pb:
101
            pb.clear()
102
        mutter('copy_all ids: %r', ids)
103
        self.copy_multi(store_from, ids, pb=pb)
104
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
105
    def copy_multi(self, other, ids, pb=None, permit_failure=False):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
106
        """Copy texts for ids from other into self.
107
108
        If an id is present in self, it is skipped.  A count of copied
109
        ids is returned, which may be less than len(ids).
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
110
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
111
        :param other: Another Store object
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
112
        :param ids: A list of entry ids to be copied
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
113
        :param pb: A ProgressBar object, if none is given, the default will be created.
114
        :param permit_failure: Allow missing entries to be ignored
115
        :return: (n_copied, [failed]) The number of entries copied successfully,
116
            followed by a list of entries which could not be copied (because they
117
            were missing)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
118
        """
1185.79.2 by John Arbash Meinel
Adding progress bars to copy_all and copy_multi, fixing ordering of repository.clone() to pull inventories after weaves.
119
        if pb:
120
            pb.update('preparing to copy')
974.2.7 by aaron.bentley at utoronto
Merged from bzr.24
121
        failed = set()
1442.1.53 by Robert Collins
Unroll the multiple-copy logic enough to remove the duplicate iteration and yet retain the optimised gzip->gzip copy.
122
        count = 0
123
        ids = list(ids) # get the list for showing a length.
124
        for fileid in ids:
125
            count += 1
126
            if self.has_id(fileid):
127
                continue
128
            try:
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
129
                self._copy_one(fileid, None, other, pb)
130
                for suffix in self._suffixes:
131
                    try:
132
                        self._copy_one(fileid, suffix, other, pb)
133
                    except KeyError:
134
                        pass
1185.79.2 by John Arbash Meinel
Adding progress bars to copy_all and copy_multi, fixing ordering of repository.clone() to pull inventories after weaves.
135
                if pb:
136
                    pb.update('copy', count, len(ids))
1442.1.53 by Robert Collins
Unroll the multiple-copy logic enough to remove the duplicate iteration and yet retain the optimised gzip->gzip copy.
137
            except KeyError:
138
                if permit_failure:
139
                    failed.add(fileid)
140
                else:
141
                    raise
142
        assert count == len(ids)
1185.79.2 by John Arbash Meinel
Adding progress bars to copy_all and copy_multi, fixing ordering of repository.clone() to pull inventories after weaves.
143
        if pb:
144
            pb.clear()
1442.1.53 by Robert Collins
Unroll the multiple-copy logic enough to remove the duplicate iteration and yet retain the optimised gzip->gzip copy.
145
        return count, failed
146
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
147
    def _copy_one(self, fileid, suffix, other, pb):
1442.1.53 by Robert Collins
Unroll the multiple-copy logic enough to remove the duplicate iteration and yet retain the optimised gzip->gzip copy.
148
        """Most generic copy-one object routine.
149
        
150
        Subclasses can override this to provide an optimised
151
        copy between their own instances. Such overriden routines
152
        should call this if they have no optimised facility for a 
153
        specific 'other'.
154
        """
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
155
        mutter('Store._copy_one: %r', fileid)
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
156
        f = other.get(fileid, suffix)
157
        self.add(f, fileid, suffix)
1185.10.1 by Aaron Bentley
Added --basis option to bzr branch
158
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
159
160
class TransportStore(Store):
161
    """A TransportStore is a Store superclass for Stores that use Transports."""
162
1442.1.33 by Robert Collins
teach TransportStore.add to accept an optional file suffix, which does not alter the fileid.
163
    def add(self, f, fileid, suffix=None):
1442.1.28 by Robert Collins
pull up core TransportStore.add from TextStore.add and CompressedTextStore.add
164
        """Add contents of a file into the store.
165
166
        f -- A file-like object, or string
167
        """
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
168
        mutter("add store entry %r", fileid)
1442.1.33 by Robert Collins
teach TransportStore.add to accept an optional file suffix, which does not alter the fileid.
169
        
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
170
        names = self._id_to_names(fileid, suffix)
171
        if self._transport.has_any(names):
172
            raise BzrError("store %r already contains id %r" 
173
                           % (self._transport.base, fileid))
1442.1.28 by Robert Collins
pull up core TransportStore.add from TextStore.add and CompressedTextStore.add
174
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
175
        # Most of the time, just adding the file will work
176
        # if we find a time where it fails, (because the dir
177
        # doesn't exist), then create the dir, and try again
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
178
        self._add(names[0], f)
179
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
180
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
181
    def _add(self, relpath, f):
182
        """Actually add the file to the given location.
183
        This should be overridden by children.
184
        """
185
        raise NotImplementedError('children need to implement this function.')
1442.1.28 by Robert Collins
pull up core TransportStore.add from TextStore.add and CompressedTextStore.add
186
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
187
    def _check_fileid(self, fileid):
188
        if not isinstance(fileid, basestring):
189
            raise TypeError('Fileids should be a string type: %s %r' % (type(fileid), fileid))
190
        if '\\' in fileid or '/' in fileid:
191
            raise ValueError("invalid store id %r" % fileid)
192
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
193
    def _id_to_names(self, fileid, suffix):
194
        """Return the names in the expected order"""
1442.1.47 by Robert Collins
test for has with suffixed files
195
        if suffix is not None:
196
            fn = self._relpath(fileid, [suffix])
197
        else:
198
            fn = self._relpath(fileid)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
199
1185.65.13 by Robert Collins
Merge from integration
200
        # FIXME RBC 20051128 this belongs in TextStore.
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
201
        fn_gz = fn + '.gz'
202
        if self._compressed:
203
            return fn_gz, fn
204
        else:
205
            return fn, fn_gz
206
207
    def has_id(self, fileid, suffix=None):
208
        """See Store.has_id."""
1651.1.5 by Martin Pool
Review cleanup of TransportStore.has_id
209
        return self._transport.has_any(self._id_to_names(fileid, suffix))
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
210
211
    def _get_name(self, fileid, suffix=None):
212
        """A special check, which returns the name of an existing file.
213
        
214
        This is similar in spirit to 'has_id', but it is designed
215
        to return information about which file the store has.
216
        """
217
        for name in self._id_to_names(fileid, suffix=suffix):
218
            if self._transport.has(name):
219
                return name
220
        return None
1442.1.38 by Robert Collins
unify __contains__ for TransportStore classes
221
1442.1.36 by Robert Collins
convert get() in TextStore and CompressedTextStore into a template method
222
    def _get(self, filename):
223
        """Return an vanilla file stream for clients to read from.
224
225
        This is the body of a template method on 'get', and should be 
226
        implemented by subclasses.
227
        """
228
        raise NotImplementedError
229
1442.1.50 by Robert Collins
test get with suffixes
230
    def get(self, fileid, suffix=None):
231
        """See Store.get()."""
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
232
        names = self._id_to_names(fileid, suffix)
233
        for name in names:
234
            try:
235
                return self._get(name)
236
            except errors.NoSuchFile:
237
                pass
238
        raise KeyError(fileid)
1433 by Robert Collins
merge in and make incremental Gustavo Niemeyers nested log patch, and remove all bare exceptions in store and transport packages.
239
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
240
    def __init__(self, a_transport, prefixed=False, compressed=False,
1185.80.1 by John Arbash Meinel
Text store and weave store both allow escaping fileid paths.
241
                 dir_mode=None, file_mode=None,
242
                 escaped=False):
1651.1.7 by Martin Pool
Move small ImmutableMemoryStore class into test module,
243
        assert isinstance(a_transport, Transport)
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
244
        super(TransportStore, self).__init__()
1442.1.44 by Robert Collins
Many transport related tweaks:
245
        self._transport = a_transport
1442.1.25 by Robert Collins
Test TransportStore._relpath for simple cases: pull up _prefixed attribute as a result.
246
        self._prefixed = prefixed
1185.65.13 by Robert Collins
Merge from integration
247
        # FIXME RBC 20051128 this belongs in TextStore.
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
248
        self._compressed = compressed
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
249
        self._suffixes = set()
1185.80.1 by John Arbash Meinel
Text store and weave store both allow escaping fileid paths.
250
        self._escaped = escaped
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
251
1185.58.6 by John Arbash Meinel
Stores don't have to have a dir_mode or file_mode set
252
        # It is okay for these to be None, it just means they
253
        # will just use the filesystem defaults
254
        self._dir_mode = dir_mode
255
        self._file_mode = file_mode
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
256
1608.2.1 by Martin Pool
[merge] Storage filename escaping
257
    def _unescape(self, file_id):
258
        """If filename escaping is enabled for this store, unescape and return the filename."""
259
        if self._escaped:
260
            return urllib.unquote(file_id)
261
        else:
262
            return file_id
263
1479 by Robert Collins
More quoting at the transport layer bugfixes.
264
    def _iter_files_recursive(self):
265
        """Iterate through the files in the transport."""
266
        for quoted_relpath in self._transport.iter_files_recursive():
1608.2.1 by Martin Pool
[merge] Storage filename escaping
267
            # transport iterator always returns quoted paths, regardless of
268
            # escaping
1479 by Robert Collins
More quoting at the transport layer bugfixes.
269
            yield urllib.unquote(quoted_relpath)
270
1442.1.51 by Robert Collins
teach iter about suffixes
271
    def __iter__(self):
1479 by Robert Collins
More quoting at the transport layer bugfixes.
272
        for relpath in self._iter_files_recursive():
1442.1.51 by Robert Collins
teach iter about suffixes
273
            # worst case is one of each suffix.
274
            name = os.path.basename(relpath)
275
            if name.endswith('.gz'):
276
                name = name[:-3]
277
            skip = False
278
            for count in range(len(self._suffixes)):
279
                for suffix in self._suffixes:
280
                    if name.endswith('.' + suffix):
281
                        skip = True
282
            if not skip:
1608.2.1 by Martin Pool
[merge] Storage filename escaping
283
                yield self._unescape(name)
1442.1.51 by Robert Collins
teach iter about suffixes
284
1442.1.40 by Robert Collins
unify __len__() implementations for TransportStore classes
285
    def __len__(self):
1442.1.50 by Robert Collins
test get with suffixes
286
        return len(list(self.__iter__()))
1442.1.40 by Robert Collins
unify __len__() implementations for TransportStore classes
287
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
288
    def _relpath(self, fileid, suffixes=None):
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
289
        self._check_fileid(fileid)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
290
        if suffixes:
291
            for suffix in suffixes:
292
                if not suffix in self._suffixes:
293
                    raise ValueError("Unregistered suffix %r" % suffix)
294
                self._check_fileid(suffix)
295
        else:
296
            suffixes = []
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
297
        if self._prefixed:
1185.80.5 by John Arbash Meinel
Changing the escaping just a little bit. Now we can handle unicode characters.
298
            # hash_prefix adds the '/' separator
1608.2.1 by Martin Pool
[merge] Storage filename escaping
299
            prefix = self.hash_prefix(fileid)
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
300
        else:
1608.2.1 by Martin Pool
[merge] Storage filename escaping
301
            prefix = ''
1608.2.6 by Martin Pool
Cleanup escaped stores
302
        fileid = self._escape_file_id(fileid)
1608.2.1 by Martin Pool
[merge] Storage filename escaping
303
        path = prefix + fileid
1185.80.5 by John Arbash Meinel
Changing the escaping just a little bit. Now we can handle unicode characters.
304
        full_path = u'.'.join([path] + suffixes)
1651.1.7 by Martin Pool
Move small ImmutableMemoryStore class into test module,
305
        return urlescape(full_path)
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
306
1608.2.1 by Martin Pool
[merge] Storage filename escaping
307
    def _escape_file_id(self, file_id):
308
        """Turn a file id into a filesystem safe string.
309
310
        This is similar to a plain urllib.quote, except
311
        it uses specific safe characters, so that it doesn't
312
        have to translate a lot of valid file ids.
313
        """
314
        if not self._escaped:
315
            return file_id
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
316
        if isinstance(file_id, unicode):
317
            file_id = file_id.encode('utf-8')
1608.2.1 by Martin Pool
[merge] Storage filename escaping
318
        # @ does not get escaped. This is because it is a valid
319
        # filesystem character we use all the time, and it looks
320
        # a lot better than seeing %40 all the time.
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
321
        safe = "abcdefghijklmnopqrstuvwxyz0123456789-_@,."
322
        r = [((c in safe) and c or ('%%%02x' % ord(c)))
323
             for c in file_id]
324
        return ''.join(r)
1608.2.1 by Martin Pool
[merge] Storage filename escaping
325
326
    def hash_prefix(self, fileid):
327
        # fileid should be unescaped
328
        if self._escaped:
329
            fileid = self._escape_file_id(fileid)
330
        return "%02x/" % (adler32(fileid) & 0xff)
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
331
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
332
    def __repr__(self):
333
        if self._transport is None:
334
            return "%s(None)" % (self.__class__.__name__)
335
        else:
336
            return "%s(%r)" % (self.__class__.__name__, self._transport.base)
337
338
    __str__ = __repr__
1185.10.1 by Aaron Bentley
Added --basis option to bzr branch
339
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
340
    def listable(self):
341
        """Return True if this store is able to be listed."""
342
        return self._transport.listable()
343
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
344
    def register_suffix(self, suffix):
345
        """Register a suffix as being expected in this store."""
346
        self._check_fileid(suffix)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
347
        if suffix == 'gz':
348
            raise ValueError('You cannot register the "gz" suffix.')
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
349
        self._suffixes.add(suffix)
350
1442.1.37 by Robert Collins
pull up total_size into TransportStore
351
    def total_size(self):
352
        """Return (count, bytes)
353
354
        This is the (compressed) size stored on disk, not the size of
355
        the content."""
356
        total = 0
357
        count = 0
1442.1.44 by Robert Collins
Many transport related tweaks:
358
        for relpath in self._transport.iter_files_recursive():
1442.1.37 by Robert Collins
pull up total_size into TransportStore
359
            count += 1
1442.1.44 by Robert Collins
Many transport related tweaks:
360
            total += self._transport.stat(relpath).st_size
1442.1.37 by Robert Collins
pull up total_size into TransportStore
361
                
362
        return count, total
363
1092.2.1 by Robert Collins
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations
364
1563.2.14 by Robert Collins
Prepare weave store to delegate copy details to the versioned file.
365
@deprecated_function(zero_eight)
1185.79.2 by John Arbash Meinel
Adding progress bars to copy_all and copy_multi, fixing ordering of repository.clone() to pull inventories after weaves.
366
def copy_all(store_from, store_to, pb=None):
1185.10.1 by Aaron Bentley
Added --basis option to bzr branch
367
    """Copy all ids from one store to another."""
1563.2.14 by Robert Collins
Prepare weave store to delegate copy details to the versioned file.
368
    store_to.copy_all_ids(store_from, pb)