~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store.py

  • Committer: mbp at sourcefrog
  • Date: 2005-03-30 22:27:17 UTC
  • Revision ID: mbp@sourcefrog.net-20050330222717-027b5837127b938d
experiment with new nested inventory file format
not used by default yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
__copyright__ = "Copyright (C) 2005 Canonical Ltd."
24
24
__author__ = "Martin Pool <mbp@canonical.com>"
25
25
 
26
 
import os, tempfile, types, osutils
 
26
import os, tempfile, types, osutils, gzip, errno
 
27
from stat import ST_SIZE
27
28
from StringIO import StringIO
28
29
from trace import mutter
29
30
 
30
 
 
31
31
######################################################################
32
32
# stores
33
33
 
80
80
    def __repr__(self):
81
81
        return "%s(%r)" % (self.__class__.__name__, self._basedir)
82
82
 
83
 
    def add(self, f, fileid):
 
83
    def add(self, f, fileid, compressed=True):
84
84
        """Add contents of a file into the store.
85
85
 
86
86
        :param f: An open file, or file-like object."""
92
92
            content = f
93
93
        else:
94
94
            content = f.read()
95
 
        if fileid not in self:
96
 
            filename = self._path(fileid)
97
 
            f = file(filename, 'wb')
98
 
            f.write(content)
99
 
            f.flush()
100
 
            os.fsync(f.fileno())
101
 
            f.close()
102
 
            osutils.make_readonly(filename)
 
95
 
 
96
        p = self._path(fileid)
 
97
        if os.access(p, os.F_OK) or os.access(p + '.gz', os.F_OK):
 
98
            bailout("store %r already contains id %r" % (self._basedir, fileid))
 
99
 
 
100
        if compressed:
 
101
            f = gzip.GzipFile(p + '.gz', 'wb')
 
102
            os.chmod(p + '.gz', 0444)
 
103
        else:
 
104
            f = file(p, 'wb')
 
105
            os.chmod(p, 0444)
 
106
            
 
107
        f.write(content)
 
108
        f.close()
103
109
 
104
110
 
105
111
    def __contains__(self, fileid):
106
112
        """"""
107
 
        return os.access(self._path(fileid), os.R_OK)
 
113
        p = self._path(fileid)
 
114
        return (os.access(p, os.R_OK)
 
115
                or os.access(p + '.gz', os.R_OK))
108
116
 
 
117
    # TODO: Guard against the same thing being stored twice, compressed and uncompresse
109
118
 
110
119
    def __iter__(self):
111
 
        return iter(os.listdir(self._basedir))
 
120
        for f in os.listdir(self._basedir):
 
121
            if f[-3:] == '.gz':
 
122
                # TODO: case-insensitive?
 
123
                yield f[:-3]
 
124
            else:
 
125
                yield f
 
126
 
 
127
    def __len__(self):
 
128
        return len(os.listdir(self._basedir))
112
129
 
113
130
    def __getitem__(self, fileid):
114
131
        """Returns a file reading from a particular entry."""
115
 
        return file(self._path(fileid), 'rb')
116
 
 
117
 
    def delete_all(self):
118
 
        for fileid in self:
119
 
            self.delete(fileid)
120
 
 
121
 
    def delete(self, fileid):
122
 
        """Remove nominated store entry.
123
 
 
124
 
        Most stores will be add-only."""
125
 
        filename = self._path(fileid)
126
 
        ## osutils.make_writable(filename)
127
 
        os.remove(filename)
128
 
 
129
 
    def destroy(self):
130
 
        """Remove store; only allowed if it is empty."""
131
 
        os.rmdir(self._basedir)
132
 
        mutter("%r destroyed" % self)
 
132
        p = self._path(fileid)
 
133
        try:
 
134
            return gzip.GzipFile(p + '.gz', 'rb')
 
135
        except IOError, e:
 
136
            if e.errno == errno.ENOENT:
 
137
                return file(p, 'rb')
 
138
            else:
 
139
                raise e
 
140
 
 
141
    def total_size(self):
 
142
        """Return (count, bytes)
 
143
 
 
144
        This is the (compressed) size stored on disk, not the size of
 
145
        the content."""
 
146
        total = 0
 
147
        count = 0
 
148
        for fid in self:
 
149
            count += 1
 
150
            p = self._path(fid)
 
151
            try:
 
152
                total += os.stat(p)[ST_SIZE]
 
153
            except OSError:
 
154
                total += os.stat(p + '.gz')[ST_SIZE]
 
155
                
 
156
        return count, total
 
157
 
133
158
 
134
159
 
135
160
 
143
168
        ImmutableStore.__init__(self, tempfile.mkdtemp())
144
169
 
145
170
    def __del__(self):
146
 
        self.delete_all()
147
 
        self.destroy()
 
171
        for f in os.listdir(self._basedir):
 
172
            os.remove(os.path.join(self._basedir, f))
 
173
        os.rmdir(self._basedir)
 
174
        mutter("%r destroyed" % self)