~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store.py

  • Committer: Robert Collins
  • Date: 2005-09-06 15:19:44 UTC
  • mto: (1092.3.1)
  • mto: This revision was merged to the branch mainline in revision 1397.
  • Revision ID: robertc@robertcollins.net-20050906151944-04320f095a2abc31
minor refactors to store, create an ImmutableMemoryStore for testing or other such operations

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
    pass
36
36
 
37
37
 
38
 
class ImmutableStore(object):
39
 
    """Store that holds files indexed by unique names.
 
38
class Store(object):
 
39
    """An abstract store that holds files indexed by unique names.
40
40
 
41
41
    Files can be added, but not modified once they are in.  Typically
42
42
    the hash is used as the name, or something else known to be unique,
57
57
    >>> st.add(StringIO('goodbye'), '123123')
58
58
    >>> st['123123'].read()
59
59
    'goodbye'
 
60
    """
 
61
 
 
62
    def total_size(self):
 
63
        """Return (count, bytes)
 
64
 
 
65
        This is the (compressed) size stored on disk, not the size of
 
66
        the content."""
 
67
        total = 0
 
68
        count = 0
 
69
        for fid in self:
 
70
            count += 1
 
71
            total += self._item_size(fid)
 
72
        return count, total
 
73
 
 
74
 
 
75
class ImmutableStore(Store):
 
76
    """Store that stores files on disk.
60
77
 
61
78
    TODO: Atomic add by writing to a temporary file and renaming.
 
79
    TODO: Guard against the same thing being stored twice, compressed and
 
80
          uncompressed during copy_multi_immutable - the window is for a
 
81
          matching store with some crack code that lets it offer a 
 
82
          non gz FOO and then a fz FOO.
62
83
 
63
84
    In bzr 0.0.5 and earlier, files within the store were marked
64
85
    readonly on disk.  This is no longer done but existing stores need
66
87
    """
67
88
 
68
89
    def __init__(self, basedir):
 
90
        super(ImmutableStore, self).__init__()
69
91
        self._basedir = basedir
70
92
 
71
93
    def _path(self, id):
174
196
        assert count == len(to_copy)
175
197
        pb.clear()
176
198
        return count, failed
177
 
    
178
199
 
179
200
    def __contains__(self, fileid):
180
201
        """"""
182
203
        return (os.access(p, os.R_OK)
183
204
                or os.access(p + '.gz', os.R_OK))
184
205
 
185
 
    # TODO: Guard against the same thing being stored twice, compressed and uncompresse
 
206
    def _item_size(self, fid):
 
207
        p = self._path(fid)
 
208
        try:
 
209
            return os.stat(p)[ST_SIZE]
 
210
        except OSError:
 
211
            return os.stat(p + '.gz')[ST_SIZE]
186
212
 
187
213
    def __iter__(self):
188
214
        for f in os.listdir(self._basedir):
195
221
    def __len__(self):
196
222
        return len(os.listdir(self._basedir))
197
223
 
198
 
 
199
224
    def __getitem__(self, fileid):
200
225
        """Returns a file reading from a particular entry."""
201
226
        p = self._path(fileid)
214
239
        raise IndexError(fileid)
215
240
 
216
241
 
217
 
    def total_size(self):
218
 
        """Return (count, bytes)
219
 
 
220
 
        This is the (compressed) size stored on disk, not the size of
221
 
        the content."""
222
 
        total = 0
223
 
        count = 0
224
 
        for fid in self:
225
 
            count += 1
226
 
            p = self._path(fid)
227
 
            try:
228
 
                total += os.stat(p)[ST_SIZE]
229
 
            except OSError:
230
 
                total += os.stat(p + '.gz')[ST_SIZE]
231
 
                
232
 
        return count, total
233
 
 
234
 
 
235
 
 
236
 
 
237
242
class ImmutableScratchStore(ImmutableStore):
238
243
    """Self-destructing test subclass of ImmutableStore.
239
244
 
241
246
 Obviously you should not put anything precious in it.
242
247
    """
243
248
    def __init__(self):
244
 
        ImmutableStore.__init__(self, tempfile.mkdtemp())
 
249
        super(ImmutableScratchStore, self).__init__(tempfile.mkdtemp())
245
250
 
246
251
    def __del__(self):
247
252
        for f in os.listdir(self._basedir):
251
256
            os.remove(fpath)
252
257
        os.rmdir(self._basedir)
253
258
        mutter("%r destroyed" % self)
 
259
 
 
260
 
 
261
class ImmutableMemoryStore(Store):
 
262
    """A memory only store."""
 
263
 
 
264
    def __init__(self):
 
265
        super(ImmutableMemoryStore, self).__init__()
 
266
        self._contents = {}
 
267
 
 
268
    def add(self, stream, fileid, compressed=True):
 
269
        if self._contents.has_key(fileid):
 
270
            raise StoreError("fileid %s already in the store" % fileid)
 
271
        self._contents[fileid] = stream.read()
 
272
 
 
273
    def __getitem__(self, fileid):
 
274
        """Returns a file reading from a particular entry."""
 
275
        if not self._contents.has_key(fileid):
 
276
            raise IndexError
 
277
        return StringIO(self._contents[fileid])
 
278
 
 
279
    def _item_size(self, fileid):
 
280
        return len(self._contents[fileid])
 
281
 
 
282
    def __iter__(self):
 
283
        return iter(self._contents.keys())