rewritten using rcslib.py
diff --git a/Demo/pdist/RCSProxy.py b/Demo/pdist/RCSProxy.py
index 90eaff4..c22b81d 100755
--- a/Demo/pdist/RCSProxy.py
+++ b/Demo/pdist/RCSProxy.py
@@ -7,279 +7,190 @@
 remote CVS like utility.  It is modeled after the similar module
 FSProxy.
 
-The module defines three classes:
+The module defines two classes:
 
 RCSProxyLocal  -- used for local access
 RCSProxyServer -- used on the server side of remote access
-RCSProxyClient -- used on the client side of remote access
+
+An additional class, RCSProxyClient, is defined in module rcsclient.
 
 The remote classes are instantiated with an IP address and an optional
 verbosity flag.
 """
 
 import server
-import client
 import md5
 import os
 import fnmatch
 import string
 import tempfile
+import rcslib
 
 
-okchars = string.letters + string.digits + '-_=+.'
+class DirSupport:
+
+    def __init__(self):
+	self._dirstack = []
+
+    def __del__(self):
+	self._close()
+
+    def _close(self):
+	while self._dirstack:
+	    self.back()
+
+    def pwd(self):
+	return os.getcwd()
+
+    def cd(self, name):
+	save = os.getcwd()
+	os.chdir(name)
+	self._dirstack.append(save)
+
+    def back(self):
+	if not self._dirstack:
+	    raise os.error, "empty directory stack"
+	dir = self._dirstack[-1]
+	os.chdir(dir)
+	del self._dirstack[-1]
+
+    def listsubdirs(self, pat = None):
+	files = os.listdir(os.curdir)
+	files = filter(os.path.isdir, files)
+	return self._filter(files, pat)
+
+    def isdir(self, name):
+	return os.path.isdir(name)
+
+    def mkdir(self, name):
+	os.mkdir(name, 0777)
+
+    def rmdir(self, name):
+	os.rmdir(name)
 
 
-class RCSProxyLocal:
-	
-	def __init__(self):
-		self._dirstack = []
-	
-	def _close(self):
-		while self._dirstack:
-			self.back()
-	
-	def pwd(self):
-		return os.getcwd()
-	
-	def cd(self, name):
-		save = os.getcwd()
-		os.chdir(name)
-		self._dirstack.append(save)
-	
-	def back(self):
-		if not self._dirstack:
-			raise os.error, "empty directory stack"
-		dir = self._dirstack[-1]
-		os.chdir(dir)
-		del self._dirstack[-1]
-	
-	def _filter(self, files, pat = None):
-		if pat:
-			def keep(name, pat = pat):
-				return fnmatch.fnmatch(name, pat)
-			files = filter(keep, files)
-		files.sort()
-		return files
+class RCSProxyLocal(rcslib.RCS, DirSupport):
 
-	def isfile(self, name):
-		namev = name + ',v'
-		return os.path.isfile(namev) or \
-		       os.path.isfile(os.path.join('RCS', namev))
-	
-	def _unmangle(self, name):
-		if type(name) == type(''):
-			rev = ''
-		else:
-			name, rev = name
-		return name, rev
-	
-	def checkfile(self, name):
-		name, rev = self._unmangle(name)
-		if not self.isfile(name):
-			raise os.error, 'not an rcs file %s' % `name`
-		for c in rev:
-			if c not in okchars:
-				raise ValueError, "bad char in rev"
-		return name, rev
-	
-	def listfiles(self, pat = None):
-		def isrcs(name): return name[-2:] == ',v'
-		def striprcs(name): return name[:-2]
-		files = os.listdir(os.curdir)
-		files = filter(isrcs, files)
-		if os.path.isdir('RCS'):
-			files2 = os.listdir('RCS')
-			files2 = filter(isrcs, files2)
-			files = files + files2
-		files = map(striprcs, files)
-		return self._filter(files, pat)
-	
-	def listsubdirs(self, pat = None):
-		files = os.listdir(os.curdir)
-		files = filter(os.path.isdir, files)
-		return self._filter(files, pat)
-	
-	def isdir(self, name):
-		return os.path.isdir(name)
+    def __init__(self):
+	rcslib.RCS.__init__(self)
+	DirSupport.__init__(self)
 
-	def _open(self, name, cmd = 'co -p'):
-		name, rev = self.checkfile(name)
-		namev = name + ',v'
-		if rev:
-			cmd = cmd + ' -r' + rev
-		return os.popen('%s %s' %  (cmd, `namev`))
+    def __del__(self):
+	DirSupport.__del__(self)
+	rcslib.RCS.__del__(self)
 
-	def _closepipe(self, f):
-		sts = f.close()
-		if sts:
-			raise IOError, "Exit status %d" % sts
-	
-	def _remove(self, fn):
-		try:
-			os.unlink(fn)
-		except os.error:
-			pass
-	
-	def sum(self, name):
-		f = self._open(name)
-		BUFFERSIZE = 1024*8
-		sum = md5.new()
-		while 1:
-			buffer = f.read(BUFFERSIZE)
-			if not buffer:
-				break
-			sum.update(buffer)
-		self._closepipe(f)
-		return sum.digest()
-	
-	def _list(self, function, list):
-		if list is None:
-			list = self.listfiles()
-		res = []
-		for name in list:
-			try:
-				res.append((name, function(name)))
-			except (os.error, IOError):
-				res.append((name, None))
-		return res
-	
-	def sumlist(self, list = None):
-		return self.list(self.sum, list)
-	
-	def _dict(self, function, list):
-		if list is None:
-			list = self.listfiles()
-		dict = {}
-		for name in list:
-			try:
-				dict[name] = function(name)
-			except (os.error, IOError):
-				pass
-		return dict
-	
-	def sumdict(self, list = None):
-		return self.dict(self.sum, list)
-	
-	def get(self, name):
-		f = self._open(name)
-		data = f.read()
-		self._closepipe(f)
-		return data
+    def sumlist(self, list = None):
+	return self._list(self.sum, list)
 
-	def info(self, name):
-		f = self._open(name, 'rlog -h')
-		dict = {}
-		while 1:
-			line = f.readline()
-			if not line: break
-			if line[0] == '\t':
-				continue # XXX lock details, later
-			i = string.find(line, ':')
-			if i > 0:
-				key, value = line[:i], string.strip(line[i+1:])
-				dict[key] = value
-		self._closepipe(f)
-		return dict
-	
-	def head(self, name):
-		dict = self.info(name)
-		return dict['head']
-	
-	def log(self, name, flags = ''):
-		f = self._open(name, 'rlog %s 2>&1' % flags)
-		log = f.read()
-		self._closepipe(f)
-		return log
+    def sumdict(self, list = None):
+	return self._dict(self.sum, list)
 
-	def put(self, fullname, data, message = ""):
-		if message and message[-1] != '\n':
-			message = message + '\n'
-		name, rev = self._unmangle(fullname)
-		new = not self.isfile(name)
-		if new:
-			for c in name:
-				if c not in okchars:
-					raise ValueError, "bad char in name"
-		else:
-			self._remove(name)
-		f = open(name, 'w')
-		f.write(data)
-		f.close()
-		tf = tempfile.mktemp()
-		try:
-			if not new:
-			    cmd = "rcs -l%s %s >>%s 2>&1" % (rev, name, tf)
-			    sts = os.system(cmd)
-			    if sts:
-				raise IOError, "rcs -l exit status %d" % sts
-			cmd = "ci -r%s %s >>%s 2>&1" % (rev, name, tf)
-			p = os.popen(cmd, 'w')
-			p.write(message)
-			sts = p.close()
-			if sts:
-				raise IOError, "ci exit status %d" % sts
-			messages = open(tf).read()
-			return messages or None
-		finally:
-			self._remove(tf)
-	
-	def mkdir(self, name):
-		os.mkdir(name, 0777)
-	
-	def rmdir(self, name):
-		os.rmdir(name)
+    def sum(self, name_rev):
+	f = self._open(name_rev)
+	BUFFERSIZE = 1024*8
+	sum = md5.new()
+	while 1:
+	    buffer = f.read(BUFFERSIZE)
+	    if not buffer:
+		break
+	    sum.update(buffer)
+	self._closepipe(f)
+	return sum.digest()
+
+    def get(self, name_rev):
+	f = self._open(name_rev)
+	data = f.read()
+	self._closepipe(f)
+	return data
+
+    def put(self, name_rev, data, message=None):
+	name, rev = self._unmangle(name_rev)
+	f = open(name, 'w')
+	f.write(data)
+	f.close()
+	self.checkin(name_rev, message)
+
+    def _list(self, function, list = None):
+	"""INTERNAL: apply FUNCTION to all files in LIST.
+
+	Return a list of the results.
+
+	The list defaults to all files in the directory if None.
+
+	"""
+	if list is None:
+	    list = self.listfiles()
+	res = []
+	for name in list:
+	    try:
+		res.append((name, function(name)))
+	    except (os.error, IOError):
+		res.append((name, None))
+	return res
+
+    def _dict(self, function, list = None):
+	"""INTERNAL: apply FUNCTION to all files in LIST.
+
+	Return a dictionary mapping files to results.
+
+	The list defaults to all files in the directory if None.
+
+	"""
+	if list is None:
+	    list = self.listfiles()
+	dict = {}
+	for name in list:
+	    try:
+		dict[name] = function(name)
+	    except (os.error, IOError):
+		pass
+	return dict
 
 
 class RCSProxyServer(RCSProxyLocal, server.SecureServer):
-	
-	def __init__(self, address, verbose = server.VERBOSE):
-		RCSProxyLocal.__init__(self)
-		server.SecureServer.__init__(self, address, verbose)
-	
-	def _close(self):
-		server.SecureServer._close(self)
-		RCSProxyLocal._close(self)
-	
-	def _serve(self):
-		server.SecureServer._serve(self)
-		# Retreat into start directory
-		while self._dirstack: self.back()
 
+    def __init__(self, address, verbose = server.VERBOSE):
+	RCSProxyLocal.__init__(self)
+	server.SecureServer.__init__(self, address, verbose)
 
-class RCSProxyClient(client.SecureClient):
-	
-	def __init__(self, address, verbose = client.VERBOSE):
-		client.SecureClient.__init__(self, address, verbose)
+    def _close(self):
+	server.SecureServer._close(self)
+	RCSProxyLocal._close(self)
+
+    def _serve(self):
+	server.SecureServer._serve(self)
+	# Retreat into start directory
+	while self._dirstack: self.back()
 
 
 def test_server():
-	import string
-	import sys
-	if sys.argv[1:]:
-		port = string.atoi(sys.argv[1])
-	else:
-		port = 4127
-	proxy = RCSProxyServer(('', port))
-	proxy._serverloop()
+    import string
+    import sys
+    if sys.argv[1:]:
+	port = string.atoi(sys.argv[1])
+    else:
+	port = 4127
+    proxy = RCSProxyServer(('', port))
+    proxy._serverloop()
 
 
 def test():
-	import sys
-	if not sys.argv[1:] or sys.argv[1] and sys.argv[1][0] in '0123456789':
-		test_server()
-		sys.exit(0)
-	proxy = RCSProxyLocal()
-	what = sys.argv[1]
-	if hasattr(proxy, what):
-		attr = getattr(proxy, what)
-		if callable(attr):
-			print apply(attr, tuple(sys.argv[2:]))
-		else:
-			print `attr`
+    import sys
+    if not sys.argv[1:] or sys.argv[1] and sys.argv[1][0] in '0123456789':
+	test_server()
+	sys.exit(0)
+    proxy = RCSProxyLocal()
+    what = sys.argv[1]
+    if hasattr(proxy, what):
+	attr = getattr(proxy, what)
+	if callable(attr):
+	    print apply(attr, tuple(sys.argv[2:]))
 	else:
-		print "%s: no such attribute" % what
-		sys.exit(2)
+	    print `attr`
+    else:
+	print "%s: no such attribute" % what
+	sys.exit(2)
 
 
 if __name__ == '__main__':
-	test()
+    test()