~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/compressed_text.py

  • Committer: Robert Collins
  • Date: 2005-10-09 23:42:12 UTC
  • Revision ID: robertc@robertcollins.net-20051009234212-7973344d900afb0b
merge in niemeyers prefixed-store patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
import os, tempfile, gzip
25
25
 
26
26
import bzrlib.store
 
27
from bzrlib.store import hash_prefix
27
28
from bzrlib.trace import mutter
28
 
from bzrlib.errors import BzrError
 
29
from bzrlib.errors import BzrError, FileExists
29
30
 
30
31
from StringIO import StringIO
31
 
from stat import ST_SIZE
 
32
from stat import ST_SIZE, ST_MODE, S_ISDIR
32
33
 
33
34
class CompressedTextStore(bzrlib.store.TransportStore):
34
35
    """Store that holds files indexed by unique names.
56
57
    'goodbye'
57
58
    """
58
59
 
59
 
    def __init__(self, transport):
 
60
    def __init__(self, transport, prefixed=False):
60
61
        super(CompressedTextStore, self).__init__(transport)
 
62
        self._prefixed = prefixed
61
63
 
62
64
    def _check_fileid(self, fileid):
63
65
        if '\\' in fileid or '/' in fileid:
65
67
 
66
68
    def _relpath(self, fileid):
67
69
        self._check_fileid(fileid)
68
 
        return fileid + '.gz'
 
70
        if self._prefixed:
 
71
            return hash_prefix(fileid) + fileid + ".gz"
 
72
        else:
 
73
            return fileid + ".gz"
69
74
 
70
75
    def add(self, f, fileid):
71
76
        """Add contents of a file into the store.
88
93
        if self._transport.has(fn):
89
94
            raise BzrError("store %r already contains id %r" % (self._transport.base, fileid))
90
95
 
 
96
        if self._prefixed:
 
97
            try:
 
98
                self._transport.mkdir(hash_prefix(fileid))
 
99
            except FileExists:
 
100
                pass
91
101
 
92
102
        sio = StringIO()
93
103
        gf = gzip.GzipFile(mode='wb', fileobj=sio)
196
206
            yield None
197
207
            count += 1
198
208
 
 
209
    def _iter_relpaths(self):
 
210
        transport = self._transport
 
211
        queue = list(transport.list_dir('.'))
 
212
        while queue:
 
213
            relpath = queue.pop(0)
 
214
            st = transport.stat(relpath)
 
215
            if S_ISDIR(st[ST_MODE]):
 
216
                for i, basename in enumerate(transport.list_dir(relpath)):
 
217
                    queue.insert(i, relpath+'/'+basename)
 
218
            else:
 
219
                yield relpath, st
 
220
 
199
221
    def __iter__(self):
200
 
        # TODO: case-insensitive?
201
 
        for f in self._transport.list_dir('.'):
202
 
            if f[-3:] == '.gz':
203
 
                yield f[:-3]
 
222
        for relpath, st in self._iter_relpaths():
 
223
            if relpath.endswith(".gz"):
 
224
                yield os.path.basename(relpath)[:-3]
204
225
            else:
205
 
                yield f
 
226
                yield os.path.basename(relpath)
206
227
 
207
228
    def __len__(self):
208
 
        return len([f for f in self._transport.list_dir('.')])
209
 
 
 
229
        return len(list(self._iter_relpath()))
210
230
 
211
231
    def __getitem__(self, fileid):
212
232
        """Returns a file reading from a particular entry."""
235
255
        the content."""
236
256
        total = 0
237
257
        count = 0
238
 
        relpaths = [self._relpath(fid) for fid in self]
239
 
        for st in self._transport.stat_multi(relpaths):
 
258
        for relpath, st in self._iter_relpaths():
240
259
            count += 1
241
260
            total += st[ST_SIZE]
242
261