/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
1
# Copyright (C) 2005, 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1 by mbp at sourcefrog
import from baz patch-364
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1 by mbp at sourcefrog
import from baz patch-364
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1 by mbp at sourcefrog
import from baz patch-364
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
"""
1861.2.6 by Alexander Belchenko
branding: change Bazaar-NG to Bazaar
21
Stores are the main data-storage mechanism for Bazaar.
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
1955.3.13 by John Arbash Meinel
Run the full test suite, and fix up any deprecation warnings.
33
from bzrlib import (
34
    errors,
2294.1.10 by John Arbash Meinel
Switch all apis over to utf8 file ids. All tests pass
35
    osutils,
1955.3.13 by John Arbash Meinel
Run the full test suite, and fix up any deprecation warnings.
36
    symbol_versioning,
37
    urlutils,
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
38
    versionedfile,
1955.3.13 by John Arbash Meinel
Run the full test suite, and fix up any deprecation warnings.
39
    )
1393.2.3 by John Arbash Meinel
Fixing typos, updating stores, getting tests to pass.
40
from bzrlib.errors import BzrError, UnlistableStore, TransportNotPossible
1955.3.13 by John Arbash Meinel
Run the full test suite, and fix up any deprecation warnings.
41
from bzrlib.symbol_versioning import (
42
    deprecated_function,
43
    )
1104 by Martin Pool
- Add a simple UIFactory
44
from bzrlib.trace import mutter
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
45
from bzrlib.transport import Transport
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
46
from bzrlib.transport.local import LocalTransport
1 by mbp at sourcefrog
import from baz patch-364
47
48
######################################################################
49
# stores
50
51
class StoreError(Exception):
52
    pass
53
54
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
55
class Store(object):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
56
    """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
57
    
1 by mbp at sourcefrog
import from baz patch-364
58
    Files can be added, but not modified once they are in.  Typically
59
    the hash is used as the name, or something else known to be unique,
60
    such as a UUID.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
61
    """
62
63
    def __len__(self):
64
        raise NotImplementedError('Children should define their length')
65
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
    def get(self, fileid, suffix=None):
1442.1.50 by Robert Collins
test get with suffixes
67
        """Returns a file reading from a particular entry.
68
        
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
69
        If suffix is present, retrieve the named suffix for fileid.
1442.1.50 by Robert Collins
test get with suffixes
70
        """
71
        raise NotImplementedError
1442.1.35 by Robert Collins
convert all users of __getitem__ into TransportStores to use .get instead
72
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
73
    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
74
        """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.
75
        raise NotImplementedError
76
77
    def __iter__(self):
78
        raise NotImplementedError
79
907.1.43 by John Arbash Meinel
Restoring compatibility for Storage.add(file, fileid), it is a little arbitrary, and compatibility is better
80
    def add(self, f, fileid):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
81
        """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.
82
        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.
83
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
84
    def has_id(self, fileid, suffix=None):
85
        """Return True or false for the presence of fileid in the store.
1442.1.47 by Robert Collins
test for has with suffixed files
86
        
87
        suffix, if present, is a per file suffix, i.e. for digital signature 
88
        data."""
1442.1.45 by Robert Collins
replace __contains__ calls in stores with has_id
89
        raise NotImplementedError
907.1.36 by John Arbash Meinel
Moving the multi-get functionality higher up into the Branch class.
90
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
91
    def listable(self):
92
        """Return True if this store is able to be listed."""
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
93
        return (getattr(self, "__iter__", None) is not None)
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
94
1563.2.14 by Robert Collins
Prepare weave store to delegate copy details to the versioned file.
95
    def copy_all_ids(self, store_from, pb=None):
96
        """Copy all the file ids from store_from into self."""
97
        if not store_from.listable():
98
            raise UnlistableStore(store_from)
99
        ids = []
100
        for count, file_id in enumerate(store_from):
101
            if pb:
102
                pb.update('listing files', count, count)
103
            ids.append(file_id)
104
        if pb:
105
            pb.clear()
106
        mutter('copy_all ids: %r', ids)
107
        self.copy_multi(store_from, ids, pb=pb)
108
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
109
    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.
110
        """Copy texts for ids from other into self.
111
112
        If an id is present in self, it is skipped.  A count of copied
113
        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.
114
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
115
        :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.
116
        :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.
117
        :param pb: A ProgressBar object, if none is given, the default will be created.
118
        :param permit_failure: Allow missing entries to be ignored
119
        :return: (n_copied, [failed]) The number of entries copied successfully,
120
            followed by a list of entries which could not be copied (because they
121
            were missing)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
122
        """
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.
123
        if pb:
124
            pb.update('preparing to copy')
974.2.7 by aaron.bentley at utoronto
Merged from bzr.24
125
        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.
126
        count = 0
127
        for fileid in ids:
128
            count += 1
129
            if self.has_id(fileid):
130
                continue
131
            try:
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
132
                self._copy_one(fileid, None, other, pb)
133
                for suffix in self._suffixes:
134
                    try:
135
                        self._copy_one(fileid, suffix, other, pb)
136
                    except KeyError:
137
                        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.
138
                if pb:
139
                    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.
140
            except KeyError:
141
                if permit_failure:
142
                    failed.add(fileid)
143
                else:
144
                    raise
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.
145
        if pb:
146
            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.
147
        return count, failed
148
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
149
    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.
150
        """Most generic copy-one object routine.
151
        
152
        Subclasses can override this to provide an optimised
153
        copy between their own instances. Such overriden routines
154
        should call this if they have no optimised facility for a 
155
        specific 'other'.
156
        """
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
157
        mutter('Store._copy_one: %r', fileid)
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
158
        f = other.get(fileid, suffix)
159
        self.add(f, fileid, suffix)
1185.10.1 by Aaron Bentley
Added --basis option to bzr branch
160
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
161
162
class TransportStore(Store):
163
    """A TransportStore is a Store superclass for Stores that use Transports."""
164
1442.1.33 by Robert Collins
teach TransportStore.add to accept an optional file suffix, which does not alter the fileid.
165
    def add(self, f, fileid, suffix=None):
1442.1.28 by Robert Collins
pull up core TransportStore.add from TextStore.add and CompressedTextStore.add
166
        """Add contents of a file into the store.
167
1955.3.13 by John Arbash Meinel
Run the full test suite, and fix up any deprecation warnings.
168
        f -- A file-like object
1442.1.28 by Robert Collins
pull up core TransportStore.add from TextStore.add and CompressedTextStore.add
169
        """
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
170
        mutter("add store entry %r", 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
171
        names = self._id_to_names(fileid, suffix)
172
        if self._transport.has_any(names):
173
            raise BzrError("store %r already contains id %r" 
174
                           % (self._transport.base, fileid))
1442.1.28 by Robert Collins
pull up core TransportStore.add from TextStore.add and CompressedTextStore.add
175
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
176
        # Most of the time, just adding the file will work
177
        # if we find a time where it fails, (because the dir
178
        # 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
179
        self._add(names[0], f)
180
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):
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
188
        if type(fileid) != str:
189
            raise TypeError('Fileids should be bytestrings: %s %r' % (
190
                type(fileid), fileid))
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
191
        if '\\' in fileid or '/' in fileid:
192
            raise ValueError("invalid store id %r" % fileid)
193
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
194
    def _id_to_names(self, fileid, suffix):
195
        """Return the names in the expected order"""
1442.1.47 by Robert Collins
test for has with suffixed files
196
        if suffix is not None:
197
            fn = self._relpath(fileid, [suffix])
198
        else:
199
            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
200
1185.65.13 by Robert Collins
Merge from integration
201
        # 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
202
        fn_gz = fn + '.gz'
203
        if self._compressed:
204
            return fn_gz, fn
205
        else:
206
            return fn, fn_gz
207
208
    def has_id(self, fileid, suffix=None):
209
        """See Store.has_id."""
1651.1.5 by Martin Pool
Review cleanup of TransportStore.has_id
210
        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
211
212
    def _get_name(self, fileid, suffix=None):
213
        """A special check, which returns the name of an existing file.
214
        
215
        This is similar in spirit to 'has_id', but it is designed
216
        to return information about which file the store has.
217
        """
218
        for name in self._id_to_names(fileid, suffix=suffix):
219
            if self._transport.has(name):
220
                return name
221
        return None
1442.1.38 by Robert Collins
unify __contains__ for TransportStore classes
222
1442.1.36 by Robert Collins
convert get() in TextStore and CompressedTextStore into a template method
223
    def _get(self, filename):
224
        """Return an vanilla file stream for clients to read from.
225
226
        This is the body of a template method on 'get', and should be 
227
        implemented by subclasses.
228
        """
229
        raise NotImplementedError
230
1442.1.50 by Robert Collins
test get with suffixes
231
    def get(self, fileid, suffix=None):
232
        """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
233
        names = self._id_to_names(fileid, suffix)
234
        for name in names:
235
            try:
236
                return self._get(name)
237
            except errors.NoSuchFile:
238
                pass
239
        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.
240
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
241
    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.
242
                 dir_mode=None, file_mode=None,
243
                 escaped=False):
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
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
256
        # Create a key mapper to use
257
        if escaped and prefixed:
258
            self._mapper = versionedfile.HashEscapedPrefixMapper()
259
        elif not escaped and prefixed:
260
            self._mapper = versionedfile.HashPrefixMapper()
261
        elif self._escaped:
3350.6.8 by Martin Pool
Change stray pdb calls to exceptions
262
            raise ValueError(
263
                "%r: escaped unprefixed stores are not permitted."
264
                % (self,))
1608.2.1 by Martin Pool
[merge] Storage filename escaping
265
        else:
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
266
            self._mapper = versionedfile.PrefixMapper()
1608.2.1 by Martin Pool
[merge] Storage filename escaping
267
1479 by Robert Collins
More quoting at the transport layer bugfixes.
268
    def _iter_files_recursive(self):
269
        """Iterate through the files in the transport."""
270
        for quoted_relpath in self._transport.iter_files_recursive():
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
271
            yield quoted_relpath
1479 by Robert Collins
More quoting at the transport layer bugfixes.
272
1442.1.51 by Robert Collins
teach iter about suffixes
273
    def __iter__(self):
1479 by Robert Collins
More quoting at the transport layer bugfixes.
274
        for relpath in self._iter_files_recursive():
1442.1.51 by Robert Collins
teach iter about suffixes
275
            # worst case is one of each suffix.
276
            name = os.path.basename(relpath)
277
            if name.endswith('.gz'):
278
                name = name[:-3]
279
            skip = False
280
            for count in range(len(self._suffixes)):
281
                for suffix in self._suffixes:
282
                    if name.endswith('.' + suffix):
283
                        skip = True
284
            if not skip:
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
285
                yield self._mapper.unmap(name)[0]
1442.1.51 by Robert Collins
teach iter about suffixes
286
1442.1.40 by Robert Collins
unify __len__() implementations for TransportStore classes
287
    def __len__(self):
1442.1.50 by Robert Collins
test get with suffixes
288
        return len(list(self.__iter__()))
1442.1.40 by Robert Collins
unify __len__() implementations for TransportStore classes
289
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
    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
291
        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
292
        if suffixes:
293
            for suffix in suffixes:
294
                if not suffix in self._suffixes:
295
                    raise ValueError("Unregistered suffix %r" % suffix)
296
                self._check_fileid(suffix)
297
        else:
298
            suffixes = []
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
299
        path = self._mapper.map((fileid,))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
300
        full_path = '.'.join([path] + suffixes)
301
        return full_path
1442.1.24 by Robert Collins
Pull up _check_id and _relpath from Text and CompressedText stores into TransportStore
302
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
303
    def __repr__(self):
304
        if self._transport is None:
305
            return "%s(None)" % (self.__class__.__name__)
306
        else:
307
            return "%s(%r)" % (self.__class__.__name__, self._transport.base)
308
309
    __str__ = __repr__
1185.10.1 by Aaron Bentley
Added --basis option to bzr branch
310
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
311
    def listable(self):
312
        """Return True if this store is able to be listed."""
313
        return self._transport.listable()
314
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
315
    def register_suffix(self, suffix):
316
        """Register a suffix as being expected in this store."""
317
        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
318
        if suffix == 'gz':
319
            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
320
        self._suffixes.add(suffix)
321
1442.1.37 by Robert Collins
pull up total_size into TransportStore
322
    def total_size(self):
323
        """Return (count, bytes)
324
325
        This is the (compressed) size stored on disk, not the size of
326
        the content."""
327
        total = 0
328
        count = 0
1442.1.44 by Robert Collins
Many transport related tweaks:
329
        for relpath in self._transport.iter_files_recursive():
1442.1.37 by Robert Collins
pull up total_size into TransportStore
330
            count += 1
1442.1.44 by Robert Collins
Many transport related tweaks:
331
            total += self._transport.stat(relpath).st_size
1442.1.37 by Robert Collins
pull up total_size into TransportStore
332
                
333
        return count, total