import os
import os.path
import string
import __builtin__

class Entry:

    def read(self):
	self.current = self.current + 1
	return self.lines[self.current - 1]

    def write(self, line):
	# this is unfortunate, but will go away when we get a real file 
	# format
	if line[-1] != "\n":
	    raise IOError, "writes to versioned files must end in newline"

	# this write() does a truncate as well. rude maybe?
	del self.lines[self.current:]
	self.lines.append(line)
	self.current = self.current + 1

    def readLines(self):
	# this returns a copy of the lines, not the lines themselves
	l =  self.lines[self.current:]
	self.current = len(self.lines)
	return l

    def readAllLines(self):
	# this returns the actual list of lines, and is used to write
	# the lines back out
	return self.lines

    def seekToStart(self):
	self.current = 0

    def __init__(self, lines):
	self.lines = lines
	self.current = 0

class File:

    def open(self, filename, mode):
	self.filename = filename
	self.entries = {}

	if mode == "r+" and not os.path.exists(filename):
	    return
	if mode == "w":
	    f = __builtin__.open(filename, "w")
	    f.close()
	    return

	f = __builtin__.open(filename, "r")

	lines = f.readlines()
	f.close()
	i = 0
	while i < len(lines):
	    tags = string.split(lines[i])
	    if tags[0] != "Version" or len(tags) != 3:
		raise IOError, "invalid versioned file"

	    try:
		lineCount = int(tags[2])
	    except ValueError:
		raise IOError, "invalid versioned file"

	    self.entries[tags[1]] = Entry(lines[i + 1: i + 1 + lineCount])
	    i = i + 1 + lineCount;

    def close(self):
	f = __builtin__.open(self.filename, "w")
	for version in self.entries.keys():
	    l = self.entries[version].readAllLines()
	    f.write("Version %s %d\n" % (version, len(l)))
	    s = string.join(l, "")
	    f.write(s)
	f.close()

	del self.entries
	del self.filename

    def setVersion(self, version):
	self.currentEntry = self.entries[version]
	self.currentEntry.seekToStart()

    def createVersion(self, version):
	self.entries[version] = Entry([])
	self.setVersion(version)

    def hasVersion(self, version):
	return self.entries.has_key(version)

    def versionList(self):
	return self.entries.keys()

    def read(self):
	return self.currentEntry.read()

    def readLines(self):
	return self.currentEntry.readLines()

    def write(self, line):
	return self.currentEntry.write(line)

    def __init__(self, filename, mode):
	return self.open(filename, mode);

def open(filename, mode):
    return File(filename, mode)

def latest(versionList):
    # for now the lastest version is the last in this list

    list = versionList[:]
    list.sort()
    return list[-1]



@@ -1003,25 +1003,104 @@
  %7B%7D%0A
-%0A%09if mode == %22r+%22
+%09self.readOnly = 0%0A%0A%09if (mode == %22r%22):%0A%09    self.readOnly = 1%0A%0A%09if (mode == %22r+%22 or mode == %22r%22)
  and
@@ -1143,16 +1143,18 @@
 return%0A%09
+el
 if mode 
@@ -1228,16 +1228,102 @@
   return
+%0A%09elif mode != %22r+%22 and mode != %22r%22:%0A%09    raise IOError, %22bad mode for open %25s%22 %25 mode
 %0A%0A%09f = _
@@ -1766,16 +1766,43 @@
 (self):%0A
+%09if self.readOnly: return%0A%0A
 %09f = __b
@@ -2547,24 +2547,99 @@
 elf, line):%0A
+%09if self.readOnly:%0A%09    raise IOError, %22cannot write to a read-only file%22%0A%0A
 %09return self

implement read-only files more cleanly (don't rewrite them on close)