[Pkg-bazaar-commits] ./bzr/unstable r201: Revfile: - get full text from a record- fix creation of files if they don't exist- protect against half-assed storage
mbp at sourcefrog.net
mbp at sourcefrog.net
Fri Apr 10 07:51:25 UTC 2009
------------------------------------------------------------
revno: 201
committer: mbp at sourcefrog.net
timestamp: Sat 2005-04-09 13:29:30 +1000
message:
Revfile: - get full text from a record- fix creation of files if they don't exist- protect against half-assed storage
modified:
bzrlib/revfile.py
-------------- next part --------------
=== modified file 'bzrlib/revfile.py'
--- a/bzrlib/revfile.py 2005-04-09 02:59:08 +0000
+++ b/bzrlib/revfile.py 2005-04-09 03:29:30 +0000
@@ -64,6 +64,11 @@
"""
+# TODO: Something like pread() would make this slightly simpler and
+# perhaps more efficient.
+
+# TODO: Could also try to mmap things...
+
import sys, zlib, struct, mdiff, stat, os, sha
from binascii import hexlify
@@ -76,24 +81,48 @@
_HEADER = _HEADER + ('\xff' * (_RECORDSIZE - len(_HEADER)))
_NO_BASE = 0xFFFFFFFFL
+# fields in the index record
+I_SHA = 0
+I_BASE = 1
+I_FLAGS = 2
+I_OFFSET = 3
+I_LEN = 4
+
class RevfileError(Exception):
pass
+
+
class Revfile:
def __init__(self, basename):
self.basename = basename
- self.idxfile = open(basename + '.irev', 'r+b')
- self.datafile = open(basename + '.drev', 'r+b')
- if self.last_idx() == -1:
+
+ idxname = basename + '.irev'
+ dataname = basename + '.drev'
+
+ idx_exists = os.path.exists(idxname)
+ data_exists = os.path.exists(dataname)
+
+ if idx_exists != data_exists:
+ raise RevfileError("half-assed revfile")
+
+ if not idx_exists:
+ self.idxfile = open(idxname, 'w+b')
+ self.datafile = open(dataname, 'w+b')
+
print 'init empty file'
self.idxfile.write(_HEADER)
self.idxfile.flush()
else:
+ self.idxfile = open(idxname, 'r+b')
+ self.dataname = open(dataname, 'r+b')
+
h = self.idxfile.read(_RECORDSIZE)
if h != _HEADER:
raise RevfileError("bad header %r in index of %r"
% (h, self.basename))
-
+
+
def last_idx(self):
"""Return last index already present, or -1 if none."""
l = os.fstat(self.idxfile.fileno())[stat.ST_SIZE]
@@ -152,18 +181,48 @@
return idx
+ def _get_full_text(self, idx):
+ idxrec = self[idx]
+ assert idxrec[I_FLAGS] == 0
+ assert idxrec[I_BASE] == _NO_BASE
+
+ l = idxrec[I_LEN]
+ if l == 0:
+ return ''
+
+ self.datafile.seek(idxrec[I_OFFSET])
+
+ text = self.datafile.read(l)
+ if len(text) != l:
+ raise RevfileError("short read %d of %d "
+ "getting text for record %d in %r"
+ % (len(text), l, idx, self.basename))
+
+ return text
+
+
def __len__(self):
return int(self.last_idx())
def __getitem__(self, idx):
+ """Index by sequence id returns the index field"""
+ self._seek_index(idx)
+ return self._read_next_index()
+
+
+ def _seek_index(self, idx):
self.idxfile.seek((idx + 1) * _RECORDSIZE)
+
+
+ def _read_next_index(self):
rec = self.idxfile.read(_RECORDSIZE)
if not rec:
- raise IndexError("no record %d in index for %r" % (idx, self.basename))
+ raise IndexError("end of index file")
elif len(rec) != _RECORDSIZE:
raise RevfileError("short read of %d bytes getting index %d from %r"
% (len(rec), idx, self.basename))
+
return struct.unpack(">20sIIII12x", rec)
@@ -211,7 +270,8 @@
r = Revfile("testrev")
if len(argv) < 2:
sys.stderr.write("usage: revfile dump\n"
- " revfile add\n")
+ " revfile add\n"
+ " revfile get IDX\n")
sys.exit(1)
if argv[1] == 'add':
@@ -219,6 +279,8 @@
print 'added idx %d' % new_idx
elif argv[1] == 'dump':
r.dump()
+ elif argv[1] == 'get':
+ sys.stdout.write(r._get_full_text(int(argv[2])))
else:
sys.stderr.write("unknown command %r\n" % argv[1])
sys.exit(1)
More information about the Pkg-bazaar-commits
mailing list