1996-11-27 15:52:01 -04:00
|
|
|
#! /usr/bin/env python
|
1995-04-26 19:57:11 -03:00
|
|
|
|
|
|
|
"""RCS Proxy.
|
|
|
|
|
|
|
|
Provide a simplified interface on RCS files, locally or remotely.
|
|
|
|
The functionality is geared towards implementing some sort of
|
|
|
|
remote CVS like utility. It is modeled after the similar module
|
|
|
|
FSProxy.
|
|
|
|
|
1995-06-23 19:07:17 -03:00
|
|
|
The module defines two classes:
|
1995-04-26 19:57:11 -03:00
|
|
|
|
|
|
|
RCSProxyLocal -- used for local access
|
|
|
|
RCSProxyServer -- used on the server side of remote access
|
1995-06-23 19:07:17 -03:00
|
|
|
|
1995-06-23 19:37:53 -03:00
|
|
|
The corresponding client class, RCSProxyClient, is defined in module
|
|
|
|
rcsclient.
|
1995-04-26 19:57:11 -03:00
|
|
|
|
|
|
|
The remote classes are instantiated with an IP address and an optional
|
|
|
|
verbosity flag.
|
|
|
|
"""
|
|
|
|
|
|
|
|
import server
|
|
|
|
import md5
|
|
|
|
import os
|
|
|
|
import fnmatch
|
|
|
|
import string
|
|
|
|
import tempfile
|
1995-06-23 19:07:17 -03:00
|
|
|
import rcslib
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
1995-04-26 19:57:11 -03:00
|
|
|
|
1995-06-23 19:07:17 -03:00
|
|
|
class RCSProxyLocal(rcslib.RCS, DirSupport):
|
1995-04-26 19:57:11 -03:00
|
|
|
|
1995-06-23 19:07:17 -03:00
|
|
|
def __init__(self):
|
|
|
|
rcslib.RCS.__init__(self)
|
|
|
|
DirSupport.__init__(self)
|
|
|
|
|
|
|
|
def __del__(self):
|
|
|
|
DirSupport.__del__(self)
|
|
|
|
rcslib.RCS.__del__(self)
|
|
|
|
|
|
|
|
def sumlist(self, list = None):
|
|
|
|
return self._list(self.sum, list)
|
|
|
|
|
|
|
|
def sumdict(self, list = None):
|
|
|
|
return self._dict(self.sum, list)
|
|
|
|
|
|
|
|
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)
|
1995-06-23 19:37:53 -03:00
|
|
|
self._remove(name)
|
1995-06-23 19:07:17 -03:00
|
|
|
|
|
|
|
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
|
1995-04-26 19:57:11 -03:00
|
|
|
|
|
|
|
|
1995-06-20 23:09:20 -03:00
|
|
|
class RCSProxyServer(RCSProxyLocal, server.SecureServer):
|
1995-06-23 19:07:17 -03:00
|
|
|
|
|
|
|
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()
|
1995-04-26 19:57:11 -03:00
|
|
|
|
|
|
|
|
|
|
|
def test_server():
|
1995-06-23 19:07:17 -03:00
|
|
|
import string
|
|
|
|
import sys
|
|
|
|
if sys.argv[1:]:
|
|
|
|
port = string.atoi(sys.argv[1])
|
|
|
|
else:
|
|
|
|
port = 4127
|
|
|
|
proxy = RCSProxyServer(('', port))
|
|
|
|
proxy._serverloop()
|
1995-04-26 19:57:11 -03:00
|
|
|
|
|
|
|
|
|
|
|
def test():
|
1995-06-23 19:07:17 -03:00
|
|
|
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:]))
|
1995-04-26 19:57:11 -03:00
|
|
|
else:
|
1995-06-23 19:07:17 -03:00
|
|
|
print `attr`
|
|
|
|
else:
|
|
|
|
print "%s: no such attribute" % what
|
|
|
|
sys.exit(2)
|
1995-04-26 19:57:11 -03:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
1995-06-23 19:07:17 -03:00
|
|
|
test()
|