rewritten using rcslib.py
This commit is contained in:
parent
40de53c3bd
commit
ab75eb244e
|
@ -7,279 +7,190 @@ The functionality is geared towards implementing some sort of
|
|||
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:
|
||||
class RCSProxyLocal(rcslib.RCS, DirSupport):
|
||||
|
||||
def __init__(self):
|
||||
self._dirstack = []
|
||||
def __init__(self):
|
||||
rcslib.RCS.__init__(self)
|
||||
DirSupport.__init__(self)
|
||||
|
||||
def _close(self):
|
||||
while self._dirstack:
|
||||
self.back()
|
||||
def __del__(self):
|
||||
DirSupport.__del__(self)
|
||||
rcslib.RCS.__del__(self)
|
||||
|
||||
def pwd(self):
|
||||
return os.getcwd()
|
||||
def sumlist(self, list = None):
|
||||
return self._list(self.sum, list)
|
||||
|
||||
def cd(self, name):
|
||||
save = os.getcwd()
|
||||
os.chdir(name)
|
||||
self._dirstack.append(save)
|
||||
def sumdict(self, list = None):
|
||||
return self._dict(self.sum, list)
|
||||
|
||||
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 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 _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
|
||||
def get(self, name_rev):
|
||||
f = self._open(name_rev)
|
||||
data = f.read()
|
||||
self._closepipe(f)
|
||||
return data
|
||||
|
||||
def isfile(self, name):
|
||||
namev = name + ',v'
|
||||
return os.path.isfile(namev) or \
|
||||
os.path.isfile(os.path.join('RCS', namev))
|
||||
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 _unmangle(self, name):
|
||||
if type(name) == type(''):
|
||||
rev = ''
|
||||
else:
|
||||
name, rev = name
|
||||
return name, rev
|
||||
def _list(self, function, list = None):
|
||||
"""INTERNAL: apply FUNCTION to all files in LIST.
|
||||
|
||||
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
|
||||
Return a list of the results.
|
||||
|
||||
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)
|
||||
The list defaults to all files in the directory if None.
|
||||
|
||||
def listsubdirs(self, pat = None):
|
||||
files = os.listdir(os.curdir)
|
||||
files = filter(os.path.isdir, files)
|
||||
return self._filter(files, pat)
|
||||
"""
|
||||
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 isdir(self, name):
|
||||
return os.path.isdir(name)
|
||||
def _dict(self, function, list = None):
|
||||
"""INTERNAL: apply FUNCTION to all files in LIST.
|
||||
|
||||
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`))
|
||||
Return a dictionary mapping files to results.
|
||||
|
||||
def _closepipe(self, f):
|
||||
sts = f.close()
|
||||
if sts:
|
||||
raise IOError, "Exit status %d" % sts
|
||||
The list defaults to all files in the directory if None.
|
||||
|
||||
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 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 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)
|
||||
"""
|
||||
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 __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 _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()
|
||||
|
||||
|
||||
class RCSProxyClient(client.SecureClient):
|
||||
|
||||
def __init__(self, address, verbose = client.VERBOSE):
|
||||
client.SecureClient.__init__(self, address, verbose)
|
||||
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()
|
||||
|
|
Loading…
Reference in New Issue