~bzr-pqm/bzr/bzr.dev

1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
1
# Copyright (C) 2005 by Canonical Development Ltd
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
17
"""
18
An implementation the primary storage type CompressedTextStore.
19
20
This store keeps compressed versions of the full text. It does not
21
do any sort of delta compression.
22
"""
23
1442.1.51 by Robert Collins
teach iter about suffixes
24
import gzip
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
25
26
import bzrlib.store
27
from bzrlib.trace import mutter
1429 by Robert Collins
merge in niemeyers prefixed-store patch
28
from bzrlib.errors import BzrError, FileExists
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
29
30
from StringIO import StringIO
31
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
32
class CompressedTextStore(bzrlib.store.TransportStore):
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
33
    """Store that holds files indexed by unique names.
34
35
    Files can be added, but not modified once they are in.  Typically
36
    the hash is used as the name, or something else known to be unique,
37
    such as a UUID.
38
39
    Files are stored gzip compressed, with no delta compression.
40
41
    >>> st = ScratchCompressedTextStore()
42
43
    >>> st.add(StringIO('hello'), 'aa')
44
    >>> 'aa' in st
45
    True
46
    >>> 'foo' in st
47
    False
48
49
    You are not allowed to add an id that is already present.
50
51
    Entries can be retrieved as files, which may then be read.
52
53
    >>> st.add(StringIO('goodbye'), '123123')
1442.1.35 by Robert Collins
convert all users of __getitem__ into TransportStores to use .get instead
54
    >>> st.get('123123').read()
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
55
    'goodbye'
56
    """
57
1442.1.32 by Robert Collins
Teach CompressedTextStore._relpath to support file suffixes too.
58
    def _relpath(self, fileid, suffixes=[]):
59
        suffixes = suffixes + ['gz']
60
        return super(CompressedTextStore, self)._relpath(fileid, suffixes)
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
61
1442.1.28 by Robert Collins
pull up core TransportStore.add from TextStore.add and CompressedTextStore.add
62
    def _add(self, fn, f):
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
63
        from cStringIO import StringIO
64
        from bzrlib.osutils import pumpfile
65
        
66
        if isinstance(f, basestring):
67
            f = StringIO(f)
68
            
69
        sio = StringIO()
70
        gf = gzip.GzipFile(mode='wb', fileobj=sio)
71
        # if pumpfile handles files that don't fit in ram,
72
        # so will this function
73
        if isinstance(f, basestring):
74
            gf.write(f)
75
        else:
76
            pumpfile(f, gf)
77
        gf.close()
78
        sio.seek(0)
79
        self._transport.put(fn, sio)
80
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
81
    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.
82
        if not (isinstance(other, CompressedTextStore)
83
            and other._prefixed == self._prefixed):
1185.16.146 by Martin Pool
Fix up assert with sideeffects in CompressedTextStore._copy_one
84
            return super(CompressedTextStore, self)._copy_one(fileid, suffix, other, pb)
1442.1.54 by Robert Collins
Teach store.copy_all about fileid suffixes
85
        if suffix is None or suffix == 'gz':
86
            path = self._relpath(fileid)
87
        else:
88
            path = self._relpath(fileid, [suffix])
1185.16.146 by Martin Pool
Fix up assert with sideeffects in CompressedTextStore._copy_one
89
        result = other._transport.copy_to([path], self._transport, pb=pb)
90
        assert result == 1      # or what???
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
91
1442.1.43 by Robert Collins
add registration of suffixes, in preparation for ensuring iteration is regular
92
    def __init__(self, transport, prefixed=False):
93
        super(CompressedTextStore, self).__init__(transport, prefixed)
94
        self.register_suffix('gz')
95
1442.1.36 by Robert Collins
convert get() in TextStore and CompressedTextStore into a template method
96
    def _get(self, filename):
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
97
        """Returns a file reading from a particular entry."""
1442.1.36 by Robert Collins
convert get() in TextStore and CompressedTextStore into a template method
98
        f = self._transport.get(filename)
1185.11.1 by John Arbash Meinel
(broken) Transport work is merged in. Tests do not pass yet.
99
        # gzip.GzipFile.read() requires a tell() function
100
        # but some transports return objects that cannot seek
101
        # so buffer them in a StringIO instead
102
        if hasattr(f, 'tell'):
103
            return gzip.GzipFile(mode='rb', fileobj=f)
104
        else:
105
            from cStringIO import StringIO
106
            sio = StringIO(f.read())
107
            return gzip.GzipFile(mode='rb', fileobj=sio)
108
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
109
1442.1.41 by Robert Collins
move duplicate scratch logic into a scratch transport
110
def ScratchTextStore():
111
    return TextStore(ScratchTransport())