~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revfile.py

  • Committer: mbp at sourcefrog
  • Date: 2005-04-09 03:29:30 UTC
  • Revision ID: mbp@sourcefrog.net-20050409032930-bbbb8699e94e5b0b11c046a3
Revfile: - get full text from a record- fix creation of files if they don't exist- protect against half-assed storage

Show diffs side-by-side

added added

removed removed

Lines of Context:
64
64
"""
65
65
 
66
66
 
 
67
# TODO: Something like pread() would make this slightly simpler and
 
68
# perhaps more efficient.
 
69
 
 
70
# TODO: Could also try to mmap things...
 
71
 
67
72
 
68
73
import sys, zlib, struct, mdiff, stat, os, sha
69
74
from binascii import hexlify
76
81
_HEADER = _HEADER + ('\xff' * (_RECORDSIZE - len(_HEADER)))
77
82
_NO_BASE = 0xFFFFFFFFL
78
83
 
 
84
# fields in the index record
 
85
I_SHA = 0
 
86
I_BASE = 1
 
87
I_FLAGS = 2
 
88
I_OFFSET = 3
 
89
I_LEN = 4
 
90
 
79
91
class RevfileError(Exception):
80
92
    pass
81
93
 
 
94
 
 
95
 
82
96
class Revfile:
83
97
    def __init__(self, basename):
84
98
        self.basename = basename
85
 
        self.idxfile = open(basename + '.irev', 'r+b')
86
 
        self.datafile = open(basename + '.drev', 'r+b')
87
 
        if self.last_idx() == -1:
 
99
        
 
100
        idxname = basename + '.irev'
 
101
        dataname = basename + '.drev'
 
102
 
 
103
        idx_exists = os.path.exists(idxname)
 
104
        data_exists = os.path.exists(dataname)
 
105
 
 
106
        if idx_exists != data_exists:
 
107
            raise RevfileError("half-assed revfile")
 
108
        
 
109
        if not idx_exists:
 
110
            self.idxfile = open(idxname, 'w+b')
 
111
            self.datafile = open(dataname, 'w+b')
 
112
            
88
113
            print 'init empty file'
89
114
            self.idxfile.write(_HEADER)
90
115
            self.idxfile.flush()
91
116
        else:
 
117
            self.idxfile = open(idxname, 'r+b')
 
118
            self.dataname = open(dataname, 'r+b')
 
119
            
92
120
            h = self.idxfile.read(_RECORDSIZE)
93
121
            if h != _HEADER:
94
122
                raise RevfileError("bad header %r in index of %r"
95
123
                                   % (h, self.basename))
96
 
        
 
124
 
 
125
 
97
126
    def last_idx(self):
98
127
        """Return last index already present, or -1 if none."""
99
128
        l = os.fstat(self.idxfile.fileno())[stat.ST_SIZE]
152
181
        return idx
153
182
 
154
183
 
 
184
    def _get_full_text(self, idx):
 
185
        idxrec = self[idx]
 
186
        assert idxrec[I_FLAGS] == 0
 
187
        assert idxrec[I_BASE] == _NO_BASE
 
188
 
 
189
        l = idxrec[I_LEN]
 
190
        if l == 0:
 
191
            return ''
 
192
 
 
193
        self.datafile.seek(idxrec[I_OFFSET])
 
194
 
 
195
        text = self.datafile.read(l)
 
196
        if len(text) != l:
 
197
            raise RevfileError("short read %d of %d "
 
198
                               "getting text for record %d in %r"
 
199
                               % (len(text), l, idx, self.basename))
 
200
        
 
201
        return text
 
202
 
 
203
 
155
204
    def __len__(self):
156
205
        return int(self.last_idx())
157
206
 
158
207
 
159
208
    def __getitem__(self, idx):
 
209
        """Index by sequence id returns the index field"""
 
210
        self._seek_index(idx)
 
211
        return self._read_next_index()
 
212
 
 
213
 
 
214
    def _seek_index(self, idx):
160
215
        self.idxfile.seek((idx + 1) * _RECORDSIZE)
 
216
        
 
217
 
 
218
    def _read_next_index(self):
161
219
        rec = self.idxfile.read(_RECORDSIZE)
162
220
        if not rec:
163
 
            raise IndexError("no record %d in index for %r" % (idx, self.basename))
 
221
            raise IndexError("end of index file")
164
222
        elif len(rec) != _RECORDSIZE:
165
223
            raise RevfileError("short read of %d bytes getting index %d from %r"
166
224
                               % (len(rec), idx, self.basename))
 
225
        
167
226
        return struct.unpack(">20sIIII12x", rec)
168
227
 
169
228
        
211
270
    r = Revfile("testrev")
212
271
    if len(argv) < 2:
213
272
        sys.stderr.write("usage: revfile dump\n"
214
 
                         "       revfile add\n")
 
273
                         "       revfile add\n"
 
274
                         "       revfile get IDX\n")
215
275
        sys.exit(1)
216
276
        
217
277
    if argv[1] == 'add':
219
279
        print 'added idx %d' % new_idx
220
280
    elif argv[1] == 'dump':
221
281
        r.dump()
 
282
    elif argv[1] == 'get':
 
283
        sys.stdout.write(r._get_full_text(int(argv[2])))
222
284
    else:
223
285
        sys.stderr.write("unknown command %r\n" % argv[1])
224
286
        sys.exit(1)