diff options
Diffstat (limited to 'Demo/pdist/RCSProxy.py')
-rwxr-xr-x | Demo/pdist/RCSProxy.py | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/Demo/pdist/RCSProxy.py b/Demo/pdist/RCSProxy.py new file mode 100755 index 0000000..0a12157 --- /dev/null +++ b/Demo/pdist/RCSProxy.py @@ -0,0 +1,285 @@ +#! /usr/local/bin/python + +"""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. + +The module defines three classes: + +RCSProxyLocal -- used for local access +RCSProxyServer -- used on the server side of remote access +RCSProxyClient -- used on the client side of remote access + +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 + + +okchars = string.letters + string.digits + '-_=+.' + + +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 + + 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 _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 _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 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) + + +class RCSProxyServer(RCSProxyLocal, server.Server): + + def __init__(self, address, verbose = server.VERBOSE): + RCSProxyLocal.__init__(self) + server.Server.__init__(self, address, verbose) + + def _close(self): + server.Server._close(self) + RCSProxyLocal._close(self) + + def _serve(self): + server.Server._serve(self) + # Retreat into start directory + while self._dirstack: self.back() + + +class RCSProxyClient(client.Client): + + def __init__(self, address, verbose = client.VERBOSE): + client.Client.__init__(self, address, verbose) + + +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() + + +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` + else: + print "%s: no such attribute" % what + sys.exit(2) + + +if __name__ == '__main__': + test() |